@@ -16,6 +16,7 @@ package kernel
1616
1717import (
1818 "gvisor.dev/gvisor/pkg/abi/linux"
19+ "gvisor.dev/gvisor/pkg/atomicbitops"
1920 "gvisor.dev/gvisor/pkg/bits"
2021)
2122
@@ -35,8 +36,7 @@ const (
3536)
3637
3738// pendingSignals holds a collection of pending signals. The zero value of
38- // pendingSignals is a valid empty collection. pendingSignals is thread-unsafe;
39- // users must provide synchronization.
39+ // pendingSignals is a valid empty collection.
4040//
4141// +stateify savable
4242type pendingSignals struct {
@@ -45,11 +45,19 @@ type pendingSignals struct {
4545 // Note that signals is zero-indexed, but signal 1 is the first valid
4646 // signal, so signals[0] contains signals with signo 1 etc. This offset is
4747 // usually handled by using Signal.index().
48+ //
49+ // signals is protected by the signal mutex for the containing Task or
50+ // ThreadGroup.
4851 signals [linux .SignalMaximum ]pendingSignalQueue `state:".([]savedPendingSignal)"`
4952
5053 // Bit i of pendingSet is set iff there is at least one signal with signo
5154 // i+1 pending.
52- pendingSet linux.SignalSet `state:"manual"`
55+ //
56+ // pendingSet is accessed using atomic memory operations, and is protected
57+ // by the signal mutex (such that reading pendingSet is safe if either the
58+ // signal mutex is locked or if atomic memory operations are used, while
59+ // writing pendingSet requires both).
60+ pendingSet atomicbitops.Uint64 `state:"manual"`
5361}
5462
5563// pendingSignalQueue holds a pendingSignalList for a single signal number.
@@ -86,7 +94,7 @@ func (p *pendingSignals) enqueue(info *linux.SignalInfo, timer *IntervalTimer) b
8694 }
8795 q .pendingSignalList .PushBack (& pendingSignal {SignalInfo : info , timer : timer })
8896 q .length ++
89- p .pendingSet |= linux .SignalSetOf (sig )
97+ p .pendingSet . Store ( p . pendingSet . RacyLoad () | uint64 ( linux .SignalSetOf (sig )) )
9098 return true
9199}
92100
@@ -103,7 +111,7 @@ func (p *pendingSignals) dequeue(mask linux.SignalSet) *linux.SignalInfo {
103111 // process, POSIX leaves it unspecified which is delivered first. Linux,
104112 // like many other implementations, gives priority to standard signals in
105113 // this case." - signal(7)
106- lowestPendingUnblockedBit := bits .TrailingZeros64 (uint64 ( p .pendingSet &^ mask ))
114+ lowestPendingUnblockedBit := bits .TrailingZeros64 (p .pendingSet . RacyLoad () &^ uint64 ( mask ))
107115 if lowestPendingUnblockedBit >= linux .SignalMaximum {
108116 return nil
109117 }
@@ -119,7 +127,7 @@ func (p *pendingSignals) dequeueSpecific(sig linux.Signal) *linux.SignalInfo {
119127 q .pendingSignalList .Remove (ps )
120128 q .length --
121129 if q .length == 0 {
122- p .pendingSet &^= linux .SignalSetOf (sig )
130+ p .pendingSet . Store ( p . pendingSet . RacyLoad () &^ uint64 ( linux .SignalSetOf (sig )) )
123131 }
124132 if ps .timer != nil {
125133 ps .timer .updateDequeuedSignalLocked (ps .SignalInfo )
@@ -137,5 +145,5 @@ func (p *pendingSignals) discardSpecific(sig linux.Signal) {
137145 }
138146 q .pendingSignalList .Reset ()
139147 q .length = 0
140- p .pendingSet &^= linux .SignalSetOf (sig )
148+ p .pendingSet . Store ( p . pendingSet . RacyLoad () &^ uint64 ( linux .SignalSetOf (sig )) )
141149}
0 commit comments