Skip to content

Commit 1620b10

Browse files
committed
wip
Signed-off-by: leongross <[email protected]>
1 parent 5a80fcf commit 1620b10

File tree

1 file changed

+51
-22
lines changed

1 file changed

+51
-22
lines changed

src/runtime/sync.go

+51-22
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
package runtime
66

77
import (
8+
"internal/task"
9+
"sync"
810
"sync/atomic"
9-
"unsafe"
1011
)
1112

1213
// This file contains stub implementations for internal/poll.
@@ -24,22 +25,35 @@ import (
2425
// This means we assume the following constant settings from the golang standard
2526
// library: lifo=false,profile=semaBlock,skipframe=0,reason=waitReasonSemaquire
2627

27-
type semaRoot struct {
28-
nwait atomic.Uint32
28+
// The global state of the semaphore table.
29+
// Semaphores are identified by their address.
30+
// The table maps the address to the task that is currently holding the semaphore.
31+
// The table is protected by a mutex.
32+
// When a task acquires a semaphore, the mapping is added to the map.
33+
// When a task releases a semaphore, the mapping is removed from the map.
34+
//
35+
// The table is used to implement the cansemacquire function.
36+
// The cansemacquire function is called by the semacquire function.
37+
// The cansemacquire function checks if the semaphore is available.
38+
// If the semaphore is available, the function returns true.
39+
// If the semaphore is not available, the function returns false.
40+
type semTable struct {
41+
table map[*uint32]*task.Task
42+
lock sync.Mutex
2943
}
3044

3145
var semtable semTable
3246

33-
// Prime to not correlate with any user patterns.
34-
const semTabSize = 251
47+
func init() {
48+
semtable.table = make(map[*uint32]*task.Task)
49+
}
3550

36-
type semTable [semTabSize]struct {
37-
root semaRoot
38-
pad [64 - unsafe.Sizeof(semaRoot{})]byte // only 64 x86_64, make this variable
51+
func (s *semTable) Lock() {
52+
s.lock.Lock()
3953
}
4054

41-
func (t *semTable) rootFor(addr *uint32) *semaRoot {
42-
return &t[(uintptr(unsafe.Pointer(addr))>>3)%semTabSize].root
55+
func (s *semTable) Unlock() {
56+
s.lock.Unlock()
4357
}
4458

4559
//go:linkname semacquire internal/poll.runtime_Semacquire
@@ -51,22 +65,37 @@ func semacquire(sema *uint32) {
5165

5266
// Copied from src/runtime/sema.go
5367
func cansemacquire(addr *uint32) bool {
54-
for {
55-
v := atomic.LoadUint32(addr)
56-
if v == 0 {
57-
return false
58-
}
59-
if atomic.CompareAndSwapUint32(addr, v, v-1) {
60-
return true
61-
}
68+
// Busy Looping until a lookup to the global semaphore table can be made
69+
semtable.Lock()
70+
71+
if _, ok := semtable.table[addr]; !ok {
72+
semtable.table[addr] = task.Current()
73+
semtable.Unlock()
74+
return true
75+
}
76+
77+
v := atomic.LoadUint32(addr)
78+
if v == 0 {
79+
semtable.Unlock()
80+
return false
81+
}
82+
if atomic.CompareAndSwapUint32(addr, v, v-1) {
83+
semtable.Unlock()
84+
return true
6285
}
86+
return true
6387
}
6488

6589
//go:linkname semrelease internal/poll.runtime_Semrelease
6690
func semrelease(sema *uint32) {
67-
root := semtable.rootFor(sema)
68-
atomic.AddUint32(sema, 1)
69-
if root.nwait.Load() == 0 {
70-
return
91+
// Check if the semaphore is in the table
92+
semtable.Lock()
93+
if _, ok := semtable.table[sema]; !ok {
94+
panic("invalid semaphore")
7195
}
96+
97+
atomic.AddUint32(sema, 1)
98+
semtable.Unlock()
99+
100+
Gosched()
72101
}

0 commit comments

Comments
 (0)