// Make sure pendingPreemptSignals is correct when an M exits.
                // For #41702.
                if atomic.Load(&mp.signalPending) != 0 {
-                       atomic.Xadd(&pendingPreemptSignals, -1)
+                       pendingPreemptSignals.Add(-1)
                }
        }
 
 // pendingPreemptSignals is the number of preemption signals
 // that have been sent but not received. This is only used on Darwin.
 // For #41702.
-var pendingPreemptSignals uint32
+var pendingPreemptSignals atomic.Int32
 
 // Called from syscall package before Exec.
 //
        // On Darwin, wait for all pending preemption signals to
        // be received. See issue #41702.
        if GOOS == "darwin" || GOOS == "ios" {
-               for int32(atomic.Load(&pendingPreemptSignals)) > 0 {
+               for pendingPreemptSignals.Load() > 0 {
                        osyield()
                }
        }
 
        atomic.Store(&gp.m.signalPending, 0)
 
        if GOOS == "darwin" || GOOS == "ios" {
-               atomic.Xadd(&pendingPreemptSignals, -1)
+               pendingPreemptSignals.Add(-1)
        }
 }
 
 
        if atomic.Cas(&mp.signalPending, 0, 1) {
                if GOOS == "darwin" || GOOS == "ios" {
-                       atomic.Xadd(&pendingPreemptSignals, 1)
+                       pendingPreemptSignals.Add(1)
                }
 
                // If multiple threads are preempting the same M, it may send many
                        // The default behavior for sigPreempt is to ignore
                        // the signal, so badsignal will be a no-op anyway.
                        if GOOS == "darwin" || GOOS == "ios" {
-                               atomic.Xadd(&pendingPreemptSignals, -1)
+                               pendingPreemptSignals.Add(-1)
                        }
                        return
                }