// requested, but fails. Accessed atomically.
preemptGen uint32
+ // Whether this is a pending preemption signal on this M.
+ // Accessed atomically.
+ signalPending uint32
+
dlogPerM
mOS
// Acknowledge the preemption.
atomic.Xadd(&gp.m.preemptGen, 1)
+ atomic.Store(&gp.m.signalPending, 0)
}
const preemptMSupported = pushCallSupported
// required).
return
}
- signalM(mp, sigPreempt)
+ if atomic.Cas(&mp.signalPending, 0, 1) {
+ // If multiple threads are preempting the same M, it may send many
+ // signals to the same M such that it hardly make progress, causing
+ // live-lock problem. Apparently this could happen on darwin. See
+ // issue #37741.
+ // Only send a signal if there isn't already one pending.
+ signalM(mp, sigPreempt)
+ }
}
// sigFetchG fetches the value of G safely when running in a signal handler.