[Git][ghc/ghc][wip/T27135] Expand all *_ALWAYS macros and remove definitions
Peter Trommler pushed to branch wip/T27135 at Glasgow Haskell Compiler / GHC Commits: b824ccf9 by Peter Trommler at 2026-04-04T19:08:37+02:00 Expand all *_ALWAYS macros and remove definitions - - - - - 9 changed files: - rts/Capability.h - rts/Interpreter.c - rts/Proftimer.c - rts/Schedule.c - rts/Schedule.h - rts/Timer.c - rts/include/stg/SMP.h - rts/posix/ticker/Pthread.c - rts/posix/ticker/TimerFd.c Changes: ===================================== rts/Capability.h ===================================== @@ -489,14 +489,14 @@ stopCapability (Capability *cap) // It may not work - the thread might be updating HpLim itself // at the same time - so we also have the context_switch/interrupted // flags as a sticky way to tell the thread to stop. - RELAXED_STORE_ALWAYS(&cap->r.rHpLim, NULL); + atomic_store_explicit(&cap->r.rHpLim, NULL, memory_order_relaxed); } INLINE_HEADER void interruptCapability (Capability *cap) { stopCapability(cap); - RELAXED_STORE_ALWAYS(&cap->interrupt, true); + atomic_store_explicit(&cap->interrupt, true, memory_order_relaxed); } INLINE_HEADER void @@ -505,7 +505,7 @@ contextSwitchCapability (Capability *cap, bool immediately) if(immediately) { stopCapability(cap); } - RELAXED_STORE_ALWAYS(&cap->context_switch, true); + atomic_store_explicit(&cap->context_switch, true, memory_order_relaxed); } #if defined(THREADED_RTS) ===================================== rts/Interpreter.c ===================================== @@ -695,7 +695,7 @@ interpretBCO (Capability* cap) // N.B. HpLim is the context-switch flag; when it // goes to zero we must return to the scheduler. - RELAXED_STORE_ALWAYS(&cap->r.rHpLim, (P_)1); + atomic_store_explicit(&cap->r.rHpLim, (P_)1, memory_order_relaxed); IF_DEBUG(interpreter, debugBelch( ===================================== rts/Proftimer.c ===================================== @@ -46,7 +46,7 @@ void stopProfTimer( void ) { #if defined(PROFILING) - RELAXED_STORE_ALWAYS(&do_prof_ticks, false); + atomic_store_explicit(&do_prof_ticks, false, memory_order_relaxed); #endif } @@ -54,7 +54,7 @@ void startProfTimer( void ) { #if defined(PROFILING) - RELAXED_STORE_ALWAYS(&do_prof_ticks, true); + atomic_store_explicit(&do_prof_ticks, true, memory_order_relaxed); #endif } @@ -62,7 +62,7 @@ void stopHeapProfTimer( void ) { if (RtsFlags.ProfFlags.doHeapProfile){ - RELAXED_STORE_ALWAYS(&heap_prof_timer_active, false); + atomic_store_explicit(&heap_prof_timer_active, false, memory_order_relaxed); pauseHeapProfTimer(); } } @@ -71,14 +71,14 @@ void startHeapProfTimer( void ) { if (RtsFlags.ProfFlags.doHeapProfile){ - RELAXED_STORE_ALWAYS(&heap_prof_timer_active, true); + atomic_store_explicit(&heap_prof_timer_active, true, memory_order_relaxed); resumeHeapProfTimer(); } } void pauseHeapProfTimer ( void ) { - RELAXED_STORE_ALWAYS(&do_heap_prof_ticks, false); + atomic_store_explicit(&do_heap_prof_ticks, false, memory_order_relaxed); } @@ -86,7 +86,7 @@ void resumeHeapProfTimer ( void ) { if (RtsFlags.ProfFlags.doHeapProfile && RtsFlags.ProfFlags.heapProfileIntervalTicks > 0) { - RELAXED_STORE_ALWAYS(&do_heap_prof_ticks, true); + atomic_store_explicit(&do_heap_prof_ticks, true, memory_order_relaxed); } } @@ -94,14 +94,14 @@ void requestHeapCensus( void ){ // If no profiling mode is passed then just ignore the call. if (RtsFlags.ProfFlags.doHeapProfile){ - RELAXED_STORE_ALWAYS(&performHeapProfile, true); + atomic_store_explicit(&performHeapProfile, true, memory_order_relaxed); } } void initProfTimer( void ) { - RELAXED_STORE_ALWAYS(&performHeapProfile, false); + atomic_store_explicit(&performHeapProfile, false, memory_order_relaxed); ticks_to_heap_profile = RtsFlags.ProfFlags.heapProfileIntervalTicks; @@ -120,7 +120,7 @@ handleProfTick(void) { #if defined(PROFILING) total_ticks++; - if (RELAXED_LOAD_ALWAYS(&do_prof_ticks)) { + if (atomic_load_explicit(&do_prof_ticks, memory_order_relaxed)) { uint32_t n; for (n=0; n < getNumCapabilities(); n++) { Capability *cap = getCapability(n); @@ -136,16 +136,17 @@ handleProfTick(void) ticks_to_ticky_sample--; if (ticks_to_ticky_sample <= 0) { ticks_to_ticky_sample = RtsFlags.ProfFlags.heapProfileIntervalTicks; - RELAXED_STORE_ALWAYS(&performTickySample, true); + atomic_store_explicit(&performTickySample, true, memory_order_relaxed); } } #endif - if (RELAXED_LOAD_ALWAYS(&do_heap_prof_ticks) && RELAXED_LOAD_ALWAYS(&heap_prof_timer_active)) { + if (atomic_load_explicit(&do_heap_prof_ticks, memory_order_relaxed) && + atomic_load_explicit(&heap_prof_timer_active, memory_order_relaxed)) { ticks_to_heap_profile--; if (ticks_to_heap_profile <= 0) { ticks_to_heap_profile = RtsFlags.ProfFlags.heapProfileIntervalTicks; - RELAXED_STORE_ALWAYS(&performHeapProfile, true); + atomic_store_explicit(&performHeapProfile, true, memory_order_relaxed); } } } ===================================== rts/Schedule.c ===================================== @@ -410,7 +410,7 @@ schedule (Capability *initialCapability, Task *task) if (RtsFlags.ConcFlags.ctxtSwitchTicks == 0 && (!emptyRunQueue(cap) || anyPendingTimeoutsOrIO(cap))) { - RELAXED_STORE(&cap->context_switch, 1); + atomic_store_explicit(&cap->context_switch, 1, memory_order_relaxed); } run_thread: @@ -1153,13 +1153,13 @@ schedulePostRunThread (Capability *cap, StgTSO *t) static bool scheduleHandleHeapOverflow( Capability *cap, StgTSO *t ) { - if (RELAXED_LOAD_ALWAYS(&cap->r.rHpLim) == NULL || - RELAXED_LOAD_ALWAYS(&cap->context_switch)) { + if (atomic_load_explicit(&cap->r.rHpLim, memory_order_relaxed) == NULL || + atomic_load_explicit(&cap->context_switch, memory_order_relaxed)) { // Sometimes we miss a context switch, e.g. when calling // primitives in a tight loop, MAYBE_GC() doesn't check the // context switch flag, and we end up waiting for a GC. // See #1984, and concurrent/should_run/1984 - RELAXED_STORE_ALWAYS(&cap->context_switch, 0); + atomic_store_explicit(&cap->context_switch, 0, memory_order_relaxed); appendToRunQueue(cap,t); } else { pushOnRunQueue(cap,t); @@ -1264,8 +1264,8 @@ scheduleHandleYield( Capability *cap, StgTSO *t, uint32_t prev_what_next ) // the CPU because the tick always arrives during GC). This way // penalises threads that do a lot of allocation, but that seems // better than the alternative. - if (RELAXED_LOAD_ALWAYS(&cap->context_switch) != 0) { - RELAXED_STORE_ALWAYS(&cap->context_switch, 0); + if (atomic_load_explicit(&cap->context_switch, memory_order_relaxed) != 0) { + atomic_store_explicit(&cap->context_switch, 0, memory_order_relaxed); appendToRunQueue(cap,t); } else { pushOnRunQueue(cap,t); ===================================== rts/Schedule.h ===================================== @@ -74,12 +74,12 @@ extern StgWord sched_state; INLINE_HEADER void setSchedState(enum SchedState ss) { - SEQ_CST_STORE_ALWAYS(&sched_state, (StgWord) ss); + atomic_store(&sched_state, (StgWord) ss); } INLINE_HEADER enum SchedState getSchedState(void) { - return (enum SchedState) SEQ_CST_LOAD_ALWAYS(&sched_state); + return (enum SchedState) atomic_load(&sched_state); } /* @@ -124,14 +124,14 @@ extern StgWord recent_activity; INLINE_HEADER enum RecentActivity setRecentActivity(enum RecentActivity new_value) { - StgWord old = SEQ_CST_XCHG_ALWAYS((StgPtr) &recent_activity, (StgWord) new_value); + StgWord old = atomic_exchange((StgPtr) &recent_activity, (StgWord) new_value); return (enum RecentActivity) old; } INLINE_HEADER enum RecentActivity getRecentActivity(void) { - return (enum RecentActivity) RELAXED_LOAD_ALWAYS(&recent_activity); + return (enum RecentActivity) atomic_load_explicit(&recent_activity, memory_order_relaxed); } extern bool heap_overflow; ===================================== rts/Timer.c ===================================== @@ -114,7 +114,7 @@ handle_tick(int unused STG_UNUSED) { handleProfTick(); if (RtsFlags.ConcFlags.ctxtSwitchTicks > 0 - && SEQ_CST_LOAD_ALWAYS(&timer_disabled) == 0) + && atomic_load(&timer_disabled) == 0) { ticks_to_ctxt_switch--; if (ticks_to_ctxt_switch <= 0) { @@ -189,7 +189,7 @@ initTimer(void) if (RtsFlags.MiscFlags.tickInterval != 0) { initTicker(RtsFlags.MiscFlags.tickInterval, handle_tick); } - SEQ_CST_STORE_ALWAYS(&timer_disabled, 1); + atomic_store(&timer_disabled, 1); #endif } @@ -197,7 +197,7 @@ void startTimer(void) { #if defined(HAVE_PREEMPTION) - if (SEQ_CST_SUB_ALWAYS(&timer_disabled, 1) == 0) { + if (atomic_fetch_sub(&timer_disabled, 1) == 1) { if (RtsFlags.MiscFlags.tickInterval != 0) { startTicker(); } @@ -209,7 +209,7 @@ void stopTimer(void) { #if defined(HAVE_PREEMPTION) - if (SEQ_CST_ADD_ALWAYS(&timer_disabled, 1) == 1) { + if (atomic_fetch_add(&timer_disabled, 1) == 0) { if (RtsFlags.MiscFlags.tickInterval != 0) { stopTicker(); } ===================================== rts/include/stg/SMP.h ===================================== @@ -20,24 +20,6 @@ void arm_atomic_spin_lock(void); void arm_atomic_spin_unlock(void); #endif -// Unconditionally atomic operations -// These are atomic even in the non-threaded RTS. These are necessary in the -// Proftimer implementation, which may be called from the pthreads-based -// Ticker implementation. -#define RELAXED_LOAD_ALWAYS(ptr) atomic_load_explicit(ptr, memory_order_relaxed) -#define RELAXED_STORE_ALWAYS(ptr,val) atomic_store_explicit(ptr, val, memory_order_relaxed) - -// Acquire/release atomic operations -#define ACQUIRE_LOAD_ALWAYS(ptr) atomic_load_explicit(ptr, memory_order_acquire) -#define RELEASE_STORE_ALWAYS(ptr,val) atomic_store_explicit(ptr, val, memory_order_release) - -// Sequentially consistent atomic operations -#define SEQ_CST_LOAD_ALWAYS(ptr) atomic_load(ptr) -#define SEQ_CST_STORE_ALWAYS(ptr,val) atomic_store(ptr, val) -#define SEQ_CST_ADD_ALWAYS(ptr,val) (atomic_fetch_add(ptr, val) + val) -#define SEQ_CST_SUB_ALWAYS(ptr,val) (atomic_fetch_sub(ptr, val) - val) -#define SEQ_CST_XCHG_ALWAYS(ptr,val) atomic_exchange(ptr, val); - #if defined(THREADED_RTS) /* ---------------------------------------------------------------------------- ===================================== rts/posix/ticker/Pthread.c ===================================== @@ -92,13 +92,13 @@ static void *itimer_thread_func(void *_handle_tick) // Relaxed is sufficient: If we don't see that exited was set in one iteration we will // see it next time. - while (!RELAXED_LOAD_ALWAYS(&exited)) { + while (!atomic_load_explicit(&exited, memory_order_relaxed)) { if (rtsSleep(itimer_interval) != 0) { sysErrorBelch("Ticker: sleep failed: %s", strerror(errno)); } // first try a cheap test - if (RELAXED_LOAD_ALWAYS(&stopped)) { + if (atomic_load_explicit(&stopped, memory_order_relaxed)) { OS_ACQUIRE_LOCK(&mutex); // should we really stop? if (stopped) { ===================================== rts/posix/ticker/TimerFd.c ===================================== @@ -109,7 +109,7 @@ static void *itimer_thread_func(void *_handle_tick) // Relaxed is sufficient: If we don't see that exited was set in one iteration we will // see it next time. - while (!RELAXED_LOAD_ALWAYS(&exited)) { + while (!atomic_load_explicit(&exited, memory_order_relaxed)) { if (poll(pollfds, 2, -1) == -1) { // While the RTS attempts to mask signals, some foreign libraries // may rely on signal delivery may unmask them. Consequently we may @@ -143,7 +143,7 @@ static void *itimer_thread_func(void *_handle_tick) } // first try a cheap test - if (RELAXED_LOAD_ALWAYS(&stopped)) { + if (atomic_load_explicit(&stopped, memory_order_relaxed)) { OS_ACQUIRE_LOCK(&mutex); // should we really stop? if (stopped) { View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/b824ccf95817baf083284969c7960b5c... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/b824ccf95817baf083284969c7960b5c... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Peter Trommler (@trommler)