Update threading.cpp to have helgrind annotations

This commit is contained in:
gingerBill
2023-01-16 19:23:13 +00:00
parent edb23db2ae
commit 4a8564aff7
2 changed files with 43 additions and 8 deletions

View File

@@ -465,8 +465,6 @@ typedef i32 b32; // NOTE(bill): Prefer this!!!
#if !defined(gb_thread_local) #if !defined(gb_thread_local)
#if defined(_MSC_VER) && _MSC_VER >= 1300 #if defined(_MSC_VER) && _MSC_VER >= 1300
#define gb_thread_local __declspec(thread) #define gb_thread_local __declspec(thread)
#elif defined(__GNUC__)
#define gb_thread_local __thread
#else #else
#define gb_thread_local thread_local #define gb_thread_local thread_local
#endif #endif

View File

@@ -1,11 +1,31 @@
#if defined(GB_SYSTEM_LINUX) #if defined(GB_SYSTEM_LINUX)
#include <signal.h> #include <signal.h>
#if __has_include(<valgrind/helgrind.h>)
#include <valgrind/helgrind.h>
#define HAS_VALGRIND
#endif
#endif #endif
#if defined(GB_SYSTEM_WINDOWS) #if defined(GB_SYSTEM_WINDOWS)
#pragma warning(push) #pragma warning(push)
#pragma warning(disable: 4505) #pragma warning(disable: 4505)
#endif #endif
#if defined(HAS_VALGRIND)
#define ANNOTATE_LOCK_PRE(m, t) VALGRIND_HG_MUTEX_LOCK_PRE(m, t)
#define ANNOTATE_LOCK_POST(m) VALGRIND_HG_MUTEX_LOCK_POST(m)
#define ANNOTATE_UNLOCK_PRE(m) VALGRIND_HG_MUTEX_UNLOCK_PRE(m)
#define ANNOTATE_UNLOCK_POST(m) VALGRIND_HG_MUTEX_UNLOCK_POST(m)
#define ANNOTATE_SEM_WAIT_POST(s) VALGRIND_HG_SEM_WAIT_POST(s)
#define ANNOTATE_SEM_POST_PRE(s) VALGRIND_HG_SEM_POST_PRE(s)
#else
#define ANNOTATE_LOCK_PRE(m, t)
#define ANNOTATE_LOCK_POST(m)
#define ANNOTATE_UNLOCK_PRE(m)
#define ANNOTATE_UNLOCK_POST(m)
#define ANNOTATE_SEM_WAIT_POST(s)
#define ANNOTATE_SEM_POST_PRE(s)
#endif
struct BlockingMutex; struct BlockingMutex;
struct RecursiveMutex; struct RecursiveMutex;
struct RwMutex; struct RwMutex;
@@ -32,7 +52,7 @@ struct Thread {
#else #else
pthread_t posix_handle; pthread_t posix_handle;
#endif #endif
isize idx; isize idx;
WorkerTask *queue; WorkerTask *queue;
@@ -208,7 +228,7 @@ gb_internal void semaphore_wait(Semaphore *s) {
struct Condition { struct Condition {
CONDITION_VARIABLE cond; CONDITION_VARIABLE cond;
}; };
gb_internal void condition_broadcast(Condition *c) { gb_internal void condition_broadcast(Condition *c) {
WakeAllConditionVariable(&c->cond); WakeAllConditionVariable(&c->cond);
} }
@@ -250,6 +270,14 @@ gb_internal void semaphore_wait(Semaphore *s) {
}; };
struct BlockingMutex { struct BlockingMutex {
#if defined(HAS_VALGRIND)
BlockingMutex() {
VALGRIND_HG_MUTEX_INIT_POST(this, 0);
}
~BlockingMutex() {
VALGRIND_HG_MUTEX_DESTROY_PRE(this);
}
#endif
i32 state_; i32 state_;
Futex &state() { Futex &state() {
@@ -289,14 +317,21 @@ gb_internal void semaphore_wait(Semaphore *s) {
} }
gb_internal void mutex_lock(BlockingMutex *m) { gb_internal void mutex_lock(BlockingMutex *m) {
ANNOTATE_LOCK_PRE(m, 0);
i32 v = m->state().exchange(Internal_Mutex_State_Locked, std::memory_order_acquire); i32 v = m->state().exchange(Internal_Mutex_State_Locked, std::memory_order_acquire);
if (v != Internal_Mutex_State_Unlocked) { if (v != Internal_Mutex_State_Unlocked) {
mutex_lock_slow(m, v); mutex_lock_slow(m, v);
} }
ANNOTATE_LOCK_POST(m);
} }
gb_internal bool mutex_try_lock(BlockingMutex *m) { gb_internal bool mutex_try_lock(BlockingMutex *m) {
ANNOTATE_LOCK_PRE(m, 1);
i32 v = m->state().exchange(Internal_Mutex_State_Locked, std::memory_order_acquire); i32 v = m->state().exchange(Internal_Mutex_State_Locked, std::memory_order_acquire);
return v == Internal_Mutex_State_Unlocked; if (v == Internal_Mutex_State_Unlocked) {
ANNOTATE_LOCK_POST(m);
return true;
}
return false;
} }
gb_no_inline gb_internal void mutex_unlock_slow(BlockingMutex *m) { gb_no_inline gb_internal void mutex_unlock_slow(BlockingMutex *m) {
@@ -304,6 +339,7 @@ gb_internal void semaphore_wait(Semaphore *s) {
} }
gb_internal void mutex_unlock(BlockingMutex *m) { gb_internal void mutex_unlock(BlockingMutex *m) {
ANNOTATE_UNLOCK_PRE(m);
i32 v = m->state().exchange(Internal_Mutex_State_Unlocked, std::memory_order_release); i32 v = m->state().exchange(Internal_Mutex_State_Unlocked, std::memory_order_release);
switch (v) { switch (v) {
case Internal_Mutex_State_Unlocked: case Internal_Mutex_State_Unlocked:
@@ -316,8 +352,9 @@ gb_internal void semaphore_wait(Semaphore *s) {
mutex_unlock_slow(m); mutex_unlock_slow(m);
break; break;
} }
ANNOTATE_UNLOCK_POST(m);
} }
struct Condition { struct Condition {
i32 state_; i32 state_;
@@ -472,7 +509,7 @@ gb_internal void *internal_thread_proc(void *arg) {
sigfillset(&mask); sigfillset(&mask);
GB_ASSERT_MSG(pthread_sigmask(SIG_BLOCK, &mask, nullptr) == 0, "failed to block signals"); GB_ASSERT_MSG(pthread_sigmask(SIG_BLOCK, &mask, nullptr) == 0, "failed to block signals");
#endif #endif
Thread *t = cast(Thread *)arg; Thread *t = cast(Thread *)arg;
thread_pool_thread_proc(t); thread_pool_thread_proc(t);
return NULL; return NULL;
@@ -767,4 +804,4 @@ gb_internal void futex_wait(Futex *f, Footex val) {
#if defined(GB_SYSTEM_WINDOWS) #if defined(GB_SYSTEM_WINDOWS)
#pragma warning(pop) #pragma warning(pop)
#endif #endif