Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/sentry_sync.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,22 @@ WakeConditionVariable_PREVISTA(PCONDITION_VARIABLE_PREVISTA ConditionVariable)
ConditionVariable->ContinueEvent, INFINITE, FALSE);
}

inline void
WakeAllConditionVariable_PREVISTA(
PCONDITION_VARIABLE_PREVISTA ConditionVariable)
{
if (!ConditionVariable) {
return;
}

LONG waiters = InterlockedCompareExchange(
(volatile LONG *)&ConditionVariable->Waiters, 0, 0);
if (waiters > 0) {
ConditionVariable->Target = -1;
ReleaseSemaphore(ConditionVariable->Semaphore, waiters, NULL);
}
Comment thread
cursor[bot] marked this conversation as resolved.
}
Comment thread
sentry[bot] marked this conversation as resolved.

# endif /* _WIN32_WINNT < 0x0600 */

struct sentry__winmutex_s {
Expand Down Expand Up @@ -195,13 +211,15 @@ typedef CONDITION_VARIABLE_PREVISTA sentry_cond_t;
# define sentry__cond_init(CondVar) \
InitializeConditionVariable_PREVISTA(CondVar)
# define sentry__cond_wake WakeConditionVariable_PREVISTA
# define sentry__cond_wake_all WakeAllConditionVariable_PREVISTA
# define sentry__cond_wait_timeout(CondVar, Lock, Timeout) \
SleepConditionVariableCS_PREVISTA( \
CondVar, &(Lock)->critical_section, Timeout)
# else
typedef CONDITION_VARIABLE sentry_cond_t;
# define sentry__cond_init(CondVar) InitializeConditionVariable(CondVar)
# define sentry__cond_wake WakeConditionVariable
# define sentry__cond_wake_all WakeAllConditionVariable
# define sentry__cond_wait_timeout(CondVar, Lock, Timeout) \
SleepConditionVariableCS( \
CondVar, &(Lock)->critical_section, Timeout)
Expand Down Expand Up @@ -344,6 +362,7 @@ typedef pthread_cond_t sentry_cond_t;
} \
} while (0)
# define sentry__cond_wake pthread_cond_signal
# define sentry__cond_wake_all pthread_cond_broadcast
# define sentry__thread_init(ThreadId) \
memset(ThreadId, 0, sizeof(sentry_threadid_t))
# define sentry__thread_spawn(ThreadId, Func, Data) \
Expand Down
66 changes: 66 additions & 0 deletions tests/unit/test_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,72 @@ SENTRY_TEST(bgworker_delayed_shutdown)
sentry__bgworker_decref(bgw);
}

#define COND_WAKE_ALL_THREADS 2

struct cond_wake_all_state {
sentry_mutex_t mutex;
sentry_cond_t waiting_cond;
sentry_cond_t ready_cond;
volatile long waiting;
volatile long woke;
bool ready;
};

SENTRY_THREAD_FN
cond_wake_all_thread(void *data)
{
struct cond_wake_all_state *state = data;

sentry__mutex_lock(&state->mutex);
sentry__atomic_fetch_and_add(&state->waiting, 1);
sentry__cond_wake(&state->waiting_cond);
while (!state->ready) {
sentry__cond_wait(&state->ready_cond, &state->mutex);
}
sentry__atomic_fetch_and_add(&state->woke, 1);
sentry__mutex_unlock(&state->mutex);

return 0;
}

SENTRY_TEST(cond_wake_all)
{
struct cond_wake_all_state state = { 0 };
sentry_threadid_t threads[COND_WAKE_ALL_THREADS];

sentry__mutex_init(&state.mutex);
sentry__cond_init(&state.waiting_cond);
sentry__cond_init(&state.ready_cond);

for (int i = 0; i < COND_WAKE_ALL_THREADS; i++) {
sentry__thread_init(&threads[i]);
TEST_ASSERT(
sentry__thread_spawn(&threads[i], cond_wake_all_thread, &state)
== 0);
}

sentry__mutex_lock(&state.mutex);
while (sentry__atomic_fetch(&state.waiting) < COND_WAKE_ALL_THREADS) {
sentry__cond_wait(&state.waiting_cond, &state.mutex);
}
state.ready = true;
sentry__cond_wake_all(&state.ready_cond);
sentry__mutex_unlock(&state.mutex);

for (int i = 0; i < COND_WAKE_ALL_THREADS; i++) {
sentry__thread_join(threads[i]);
}

TEST_CHECK_INT_EQUAL(
sentry__atomic_fetch(&state.woke), COND_WAKE_ALL_THREADS);

#ifndef SENTRY_PLATFORM_WINDOWS
pthread_cond_destroy(&state.ready_cond);
pthread_cond_destroy(&state.waiting_cond);
#endif
sentry__mutex_free(&state.mutex);
}

SENTRY_TEST(cond_wait_timeout_overflow)
{
#if !(defined(SENTRY_PLATFORM_MACOS) \
Expand Down
1 change: 1 addition & 0 deletions tests/unit/tests.inc
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ XX(client_report_save_raw_envelope)
XX(concurrent_init)
XX(concurrent_uninit)
XX(cond_wait_timeout_overflow)
XX(cond_wake_all)
XX(continuation_no_baggage_uses_sdk_dsc)
XX(count_sampled_events)
XX(crash_context_handler_path_propagation)
Expand Down
Loading