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