Files
react/scripts/perf-counters/src/thread-local.cpp
Ben Alpert e922f869e6 Make hardware-counter.cpp compile
`g++ -std=c++11 -lpthread src/hardware-counter.cpp
src/thread-local.cpp src/test.cpp` works and runs where `src/test.cpp` is:

```

int main() {
  bool enable = true;
  std::string events = "";
  bool recordSubprocesses = false;
  HPHP::HardwareCounter::Init(enable, events, recordSubprocesses);

  HPHP::HardwareCounter::s_counter.getCheck();

  int64_t start = HPHP::HardwareCounter::GetInstructionCount();
  volatile int x;
  for (int i = 0; i < 1000000; i++) {
    x += i;
  }
  int64_t end = HPHP::HardwareCounter::GetInstructionCount();

  printf("%d\n", end - start);
}
```
2015-09-19 11:00:27 -07:00

102 lines
2.4 KiB
C++

/**
* Copyright 2010-2015, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#include "thread-local.h"
#ifdef __linux__
#include <link.h>
#include <asm/prctl.h>
#include <sys/prctl.h>
extern "C" {
extern int arch_prctl(int, unsigned long*);
}
#endif //__linux__
namespace HPHP {
#ifdef USE_GCC_FAST_TLS
void ThreadLocalManager::OnThreadExit(void* p) {
auto list = getList(p);
p = list->head;
delete list;
while (p != nullptr) {
auto* pNode = static_cast<ThreadLocalNode<void>*>(p);
if (pNode->m_on_thread_exit_fn) {
pNode->m_on_thread_exit_fn(p);
}
p = pNode->m_next;
}
}
void ThreadLocalManager::PushTop(void* nodePtr, size_t nodeSize) {
auto& node = *static_cast<ThreadLocalNode<void>*>(nodePtr);
auto key = GetManager().m_key;
auto list = getList(pthread_getspecific(key));
if (UNLIKELY(!list)) {
ThreadLocalSetValue(key, list = new ThreadLocalList);
}
node.m_next = list->head;
node.m_size = nodeSize;
list->head = node.m_next;
}
ThreadLocalManager& ThreadLocalManager::GetManager() {
static ThreadLocalManager m;
return m;
}
#ifdef __APPLE__
ThreadLocalManager::ThreadLocalList::ThreadLocalList() {
pthread_t self = pthread_self();
handler.__routine = ThreadLocalManager::OnThreadExit;
handler.__arg = this;
handler.__next = self->__cleanup_stack;
self->__cleanup_stack = &handler;
}
#endif
#endif
#ifdef __linux__
static int visit_phdr(dl_phdr_info* info, size_t, void*) {
for (size_t i = 0, n = info->dlpi_phnum; i < n; ++i) {
const auto& hdr = info->dlpi_phdr[i];
auto addr = info->dlpi_addr + hdr.p_vaddr;
if (addr < 0x100000000LL && hdr.p_type == PT_TLS) {
// found the main thread-local section
assert(int(hdr.p_memsz) == hdr.p_memsz); // ensure no truncation
return hdr.p_memsz;
}
}
return 0;
}
std::pair<void*,size_t> getCppTdata() {
uintptr_t addr;
if (!arch_prctl(ARCH_GET_FS, &addr)) {
// fs points to the end of the threadlocal area.
size_t size = dl_iterate_phdr(&visit_phdr, nullptr);
return {(void*)(addr - size), size};
}
return {nullptr, 0};
}
#else
// how do you find the thread local section on your system?
std::pair<void*,size_t> getCppTdata() {
return {nullptr, 0};
}
#endif //__linux__
}