Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
Signed-off-by: leongross <leon.gross@9elements.com>
  • Loading branch information
leongross committed Nov 18, 2024
1 parent 5a80fcf commit 1620b10
Showing 1 changed file with 51 additions and 22 deletions.
73 changes: 51 additions & 22 deletions src/runtime/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
package runtime

import (
"internal/task"
"sync"
"sync/atomic"
"unsafe"
)

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

type semaRoot struct {
nwait atomic.Uint32
// The global state of the semaphore table.
// Semaphores are identified by their address.
// The table maps the address to the task that is currently holding the semaphore.
// The table is protected by a mutex.
// When a task acquires a semaphore, the mapping is added to the map.
// When a task releases a semaphore, the mapping is removed from the map.
//
// The table is used to implement the cansemacquire function.
// The cansemacquire function is called by the semacquire function.
// The cansemacquire function checks if the semaphore is available.
// If the semaphore is available, the function returns true.
// If the semaphore is not available, the function returns false.
type semTable struct {
table map[*uint32]*task.Task
lock sync.Mutex
}

var semtable semTable

// Prime to not correlate with any user patterns.
const semTabSize = 251
func init() {
semtable.table = make(map[*uint32]*task.Task)
}

type semTable [semTabSize]struct {
root semaRoot
pad [64 - unsafe.Sizeof(semaRoot{})]byte // only 64 x86_64, make this variable
func (s *semTable) Lock() {
s.lock.Lock()
}

func (t *semTable) rootFor(addr *uint32) *semaRoot {
return &t[(uintptr(unsafe.Pointer(addr))>>3)%semTabSize].root
func (s *semTable) Unlock() {
s.lock.Unlock()
}

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

// Copied from src/runtime/sema.go
func cansemacquire(addr *uint32) bool {
for {
v := atomic.LoadUint32(addr)
if v == 0 {
return false
}
if atomic.CompareAndSwapUint32(addr, v, v-1) {
return true
}
// Busy Looping until a lookup to the global semaphore table can be made
semtable.Lock()

if _, ok := semtable.table[addr]; !ok {
semtable.table[addr] = task.Current()
semtable.Unlock()
return true
}

v := atomic.LoadUint32(addr)
if v == 0 {
semtable.Unlock()
return false
}
if atomic.CompareAndSwapUint32(addr, v, v-1) {
semtable.Unlock()
return true
}
return true
}

//go:linkname semrelease internal/poll.runtime_Semrelease
func semrelease(sema *uint32) {
root := semtable.rootFor(sema)
atomic.AddUint32(sema, 1)
if root.nwait.Load() == 0 {
return
// Check if the semaphore is in the table
semtable.Lock()
if _, ok := semtable.table[sema]; !ok {
panic("invalid semaphore")
}

atomic.AddUint32(sema, 1)
semtable.Unlock()

Gosched()
}

0 comments on commit 1620b10

Please sign in to comment.