Use atomics for system_working global
Although it almost certainly works in this case, volatile is best not used for multi-threaded code. Using atomics instead avoids warnings from TSan. This also simplifies some logic, as system_working was previously only ever assigned to 1, so --system_working <= 0 should always return true (unless it underflowed).
This commit is contained in:
parent
d845da05e8
commit
d67d169aea
Notes:
git
2025-05-15 22:18:22 +00:00
@ -30,9 +30,6 @@ race_top:RUBY_VM_INTERRUPTED_ANY
|
|||||||
race_top:unblock_function_set
|
race_top:unblock_function_set
|
||||||
race_top:threadptr_get_interrupts
|
race_top:threadptr_get_interrupts
|
||||||
|
|
||||||
# system_working needs to be converted to atomic
|
|
||||||
race:system_working
|
|
||||||
|
|
||||||
# It's already crashing. We're doing our best
|
# It's already crashing. We're doing our best
|
||||||
signal:rb_vm_bugreport
|
signal:rb_vm_bugreport
|
||||||
race:check_reserved_signal_
|
race:check_reserved_signal_
|
||||||
|
2
thread.c
2
thread.c
@ -148,7 +148,7 @@ static int hrtime_update_expire(rb_hrtime_t *, const rb_hrtime_t);
|
|||||||
NORETURN(static void async_bug_fd(const char *mesg, int errno_arg, int fd));
|
NORETURN(static void async_bug_fd(const char *mesg, int errno_arg, int fd));
|
||||||
MAYBE_UNUSED(static int consume_communication_pipe(int fd));
|
MAYBE_UNUSED(static int consume_communication_pipe(int fd));
|
||||||
|
|
||||||
static volatile int system_working = 1;
|
static rb_atomic_t system_working = 1;
|
||||||
static rb_internal_thread_specific_key_t specific_key_count;
|
static rb_internal_thread_specific_key_t specific_key_count;
|
||||||
|
|
||||||
/********************************************************************************/
|
/********************************************************************************/
|
||||||
|
@ -2574,7 +2574,7 @@ rb_thread_wakeup_timer_thread(int sig)
|
|||||||
timer_thread_wakeup_force();
|
timer_thread_wakeup_force();
|
||||||
|
|
||||||
// interrupt main thread if main thread is available
|
// interrupt main thread if main thread is available
|
||||||
if (system_working) {
|
if (RUBY_ATOMIC_LOAD(system_working)) {
|
||||||
rb_vm_t *vm = GET_VM();
|
rb_vm_t *vm = GET_VM();
|
||||||
rb_thread_t *main_th = vm->ractor.main_thread;
|
rb_thread_t *main_th = vm->ractor.main_thread;
|
||||||
|
|
||||||
@ -3005,12 +3005,12 @@ timer_thread_func(void *ptr)
|
|||||||
|
|
||||||
RUBY_DEBUG_LOG("started%s", "");
|
RUBY_DEBUG_LOG("started%s", "");
|
||||||
|
|
||||||
while (system_working) {
|
while (RUBY_ATOMIC_LOAD(system_working)) {
|
||||||
timer_thread_check_signal(vm);
|
timer_thread_check_signal(vm);
|
||||||
timer_thread_check_timeout(vm);
|
timer_thread_check_timeout(vm);
|
||||||
ubf_wakeup_all_threads();
|
ubf_wakeup_all_threads();
|
||||||
|
|
||||||
RUBY_DEBUG_LOG("system_working:%d", system_working);
|
RUBY_DEBUG_LOG("system_working:%d", RUBY_ATOMIC_LOAD(system_working));
|
||||||
timer_thread_polling(vm);
|
timer_thread_polling(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3124,18 +3124,16 @@ rb_thread_create_timer_thread(void)
|
|||||||
static int
|
static int
|
||||||
native_stop_timer_thread(void)
|
native_stop_timer_thread(void)
|
||||||
{
|
{
|
||||||
int stopped;
|
RUBY_ATOMIC_SET(system_working, 0);
|
||||||
stopped = --system_working <= 0;
|
|
||||||
|
|
||||||
if (stopped) {
|
RUBY_DEBUG_LOG("wakeup send %d", timer_th.comm_fds[1]);
|
||||||
RUBY_DEBUG_LOG("wakeup send %d", timer_th.comm_fds[1]);
|
timer_thread_wakeup_force();
|
||||||
timer_thread_wakeup_force();
|
RUBY_DEBUG_LOG("wakeup sent");
|
||||||
RUBY_DEBUG_LOG("wakeup sent");
|
pthread_join(timer_th.pthread_id, NULL);
|
||||||
pthread_join(timer_th.pthread_id, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TT_DEBUG) fprintf(stderr, "stop timer thread\n");
|
if (TT_DEBUG) fprintf(stderr, "stop timer thread\n");
|
||||||
return stopped;
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -798,14 +798,14 @@ rb_thread_create_timer_thread(void)
|
|||||||
static int
|
static int
|
||||||
native_stop_timer_thread(void)
|
native_stop_timer_thread(void)
|
||||||
{
|
{
|
||||||
int stopped = --system_working <= 0;
|
RUBY_ATOMIC_SET(system_working, 0);
|
||||||
if (stopped) {
|
|
||||||
SetEvent(timer_thread.lock);
|
SetEvent(timer_thread.lock);
|
||||||
native_thread_join(timer_thread.id);
|
native_thread_join(timer_thread.id);
|
||||||
CloseHandle(timer_thread.lock);
|
CloseHandle(timer_thread.lock);
|
||||||
timer_thread.lock = 0;
|
timer_thread.lock = 0;
|
||||||
}
|
|
||||||
return stopped;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
x
Reference in New Issue
Block a user