Skip to content

Commit

Permalink
Add threadid to AsyncStackRootHolder (#644)
Browse files Browse the repository at this point in the history
* Add threadid to AsyncStackRoot

* Add syscall.h

* fix build

* add unistd.h

* Add processthreadsapi.h

* Add windows.h

* address comments

* address comments

* fix build

* move threadid to AsyncStackRootHolder

* run files through clang-format

* reduce the number of ifdefs

* Remove external dir (#645)

* remove utils namespace
  • Loading branch information
jesswong authored Dec 4, 2024
1 parent 1dd0208 commit ef5d04e
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 47 deletions.
6 changes: 2 additions & 4 deletions include/unifex/tracing/async_stack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ struct AsyncStackRoot;
struct AsyncStackFrame;
namespace detail {
class ScopedAsyncStackRoot;
}
} // namespace detail

// Get access to the current thread's top-most AsyncStackRoot.
//
Expand Down Expand Up @@ -321,9 +321,7 @@ struct frame_ptr {
return frame_ptr{p};
}

explicit operator void*() const noexcept {
return p_;
}
explicit operator void*() const noexcept { return p_; }

private:
void* p_;
Expand Down
110 changes: 67 additions & 43 deletions source/async_stack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@
#include <mutex>

#if !defined(UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD)
#if defined(__linux__)
# define UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD 1
#else
# if defined(__linux__)
# define UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD 1
# else
// defaults to using vector to store AsyncStackRoots instead of a pthread key
# define UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD 0
#endif
# define UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD 0
# endif
#endif

#if UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD
Expand All @@ -41,9 +41,14 @@ extern "C" {
// Initialise to some value that will be interpreted as an invalid key.
inline pthread_key_t folly_async_stack_root_tls_key = 0xFFFF'FFFFu;
}
#else
# include <vector>
#endif //UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD
#else
# include <vector>
# if defined(_WIN32)
# include <windows.h>
# elif defined(__linux__)
# include <unistd.h>
# endif // defined(_WIN32)
#endif // UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD

namespace unifex {

Expand All @@ -58,34 +63,47 @@ struct AsyncStackRootHolderList {
asyncStackRootHolders_.reserve(50);
}

void add(void* holder) {
std::lock_guard<std::mutex> lock(mutex_);
asyncStackRootHolders_.push_back(holder);
}
void add(void* holder) {
std::lock_guard<std::mutex> lock(mutex_);
asyncStackRootHolders_.push_back(holder);
}

void remove(void* holder) {
std::lock_guard<std::mutex> lock(mutex_);
auto it = std::find(asyncStackRootHolders_.begin(), asyncStackRootHolders_.end(), holder);
if (it != asyncStackRootHolders_.end()) {
std::swap(*it, asyncStackRootHolders_.back());
asyncStackRootHolders_.pop_back();
void remove(void* holder) {
std::lock_guard<std::mutex> lock(mutex_);
auto it = std::find(
asyncStackRootHolders_.begin(), asyncStackRootHolders_.end(), holder);
if (it != asyncStackRootHolders_.end()) {
std::swap(*it, asyncStackRootHolders_.back());
asyncStackRootHolders_.pop_back();
}
}
}

std::vector<void*> getAsyncStackRoots() {
if (!mutex_.try_lock()) {
// assume we crashed holding the lock and give up
return {};
std::vector<void*> getAsyncStackRoots() {
if (!mutex_.try_lock()) {
// assume we crashed holding the lock and give up
return {};
}
std::lock_guard<std::mutex> lock(mutex_, std::adopt_lock);
return asyncStackRootHolders_;
}
std::lock_guard<std::mutex> lock(mutex_, std::adopt_lock);
return asyncStackRootHolders_;
}
};

extern "C" {
auto* kUnifexAsyncStackRootHolderList = new AsyncStackRootHolderList();
auto* kUnifexAsyncStackRootHolderList = new AsyncStackRootHolderList();
}

static std::uint64_t get_os_thread_id() {
# if defined(__APPLE__)
std::uint64_t tid;
pthread_threadid_np(nullptr, &tid);
return tid;
# elif defined(_WIN32)
return std::uint64_t(GetCurrentThreadId());
# else
return std::uint64_t(gettid());
# endif
}
#endif // UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD == 0
#endif // UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD == 0

namespace {

Expand All @@ -108,23 +126,26 @@ static void ensureAsyncRootTlsKeyIsInitialised() noexcept {
#endif

struct AsyncStackRootHolder {

AsyncStackRootHolder() noexcept {
#if UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD
ensureAsyncRootTlsKeyIsInitialised();
[[maybe_unused]] const int result =
pthread_setspecific(folly_async_stack_root_tls_key, this);
UNIFEX_ASSERT(result == 0);
#else
kUnifexAsyncStackRootHolderList->add(this);
#endif
#if UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD
ensureAsyncRootTlsKeyIsInitialised();
[[maybe_unused]] const int result =
pthread_setspecific(folly_async_stack_root_tls_key, this);
UNIFEX_ASSERT(result == 0);
#else
kUnifexAsyncStackRootHolderList->add(this);
threadId = unifex::get_os_thread_id();
#endif
}

#if !UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD
~AsyncStackRootHolder() noexcept {
kUnifexAsyncStackRootHolderList->remove(this);
}
#endif
#if !UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD
~AsyncStackRootHolder() noexcept {
kUnifexAsyncStackRootHolderList->remove(this);
}

std::uint64_t get_thread_id() const noexcept { return threadId; }

#endif

AsyncStackRoot* get() const noexcept {
return value.load(std::memory_order_relaxed);
Expand All @@ -139,6 +160,9 @@ struct AsyncStackRootHolder {
}

std::atomic<AsyncStackRoot*> value{nullptr};
#if !UNIFEX_ASYNC_STACK_ROOT_USE_PTHREAD
std::uint64_t threadId = 0;
#endif
};

static thread_local AsyncStackRootHolder currentThreadAsyncStackRoot;
Expand Down Expand Up @@ -220,6 +244,6 @@ UNIFEX_NO_INLINE void resumeCoroutineWithNewAsyncStackRoot(
h.resume();
}

#endif // FOLLY_HAS_COROUTINES
#endif // !UNIFEX_NO_COROUTINES

} // namespace unifex

0 comments on commit ef5d04e

Please sign in to comment.