github.com/gopherjs/gopherjs@v1.19.0-beta1.0.20240506212314-27071a8796e4/compiler/natives/src/sync/sync.go (about) 1 //go:build js 2 // +build js 3 4 package sync 5 6 import ( 7 _ "unsafe" // For go:linkname 8 9 "github.com/gopherjs/gopherjs/js" 10 ) 11 12 var semWaiters = make(map[*uint32][]chan bool) 13 14 // semAwoken tracks the number of waiters awoken by runtime_Semrelease (`ch <- true`) 15 // that have not yet acquired the semaphore (`<-ch` in runtime_SemacquireMutex). 16 // 17 // This prevents a new call to runtime_SemacquireMutex to wrongly acquire the semaphore 18 // in between (because runtime_Semrelease has already incremented the semaphore while 19 // all the pending calls to runtime_SemacquireMutex have not yet received from the channel 20 // and thus decremented the semaphore). 21 // 22 // See https://github.com/gopherjs/gopherjs/issues/736. 23 var semAwoken = make(map[*uint32]uint32) 24 25 func runtime_Semacquire(s *uint32) { 26 runtime_SemacquireMutex(s, false, 1) 27 } 28 29 // SemacquireMutex is like Semacquire, but for profiling contended Mutexes. 30 // Mutex profiling is not supported, so just use the same implementation as runtime_Semacquire. 31 // TODO: Investigate this. If it's possible to implement, consider doing so, otherwise remove this comment. 32 func runtime_SemacquireMutex(s *uint32, lifo bool, skipframes int) { 33 if (*s - semAwoken[s]) == 0 { 34 ch := make(chan bool) 35 if lifo { 36 semWaiters[s] = append([]chan bool{ch}, semWaiters[s]...) 37 } else { 38 semWaiters[s] = append(semWaiters[s], ch) 39 } 40 <-ch 41 semAwoken[s] -= 1 42 if semAwoken[s] == 0 { 43 delete(semAwoken, s) 44 } 45 } 46 *s-- 47 } 48 49 func runtime_Semrelease(s *uint32, handoff bool, skipframes int) { 50 // TODO: Use handoff if needed/possible. 51 *s++ 52 53 w := semWaiters[s] 54 if len(w) == 0 { 55 return 56 } 57 58 ch := w[0] 59 w = w[1:] 60 semWaiters[s] = w 61 if len(w) == 0 { 62 delete(semWaiters, s) 63 } 64 65 semAwoken[s] += 1 66 67 ch <- true 68 } 69 70 func runtime_notifyListCheck(size uintptr) {} 71 72 func runtime_canSpin(i int) bool { 73 return false 74 } 75 76 //go:linkname runtime_nanotime runtime.nanotime 77 func runtime_nanotime() int64 78 79 // Implemented in runtime. 80 func throw(s string) { 81 js.Global.Call("$throwRuntimeError", s) 82 }