github.com/goplusjs/gopherjs@v1.2.6-0.20211206034512-f187917453b8/compiler/natives/src/sync/go113_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, 0) 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, skipframes int) { 29 // TODO: Use skipframes if needed/possible. 30 if (*s - semAwoken[s]) == 0 { 31 ch := make(chan bool) 32 if lifo { 33 semWaiters[s] = append([]chan bool{ch}, semWaiters[s]...) 34 } else { 35 semWaiters[s] = append(semWaiters[s], ch) 36 } 37 <-ch 38 semAwoken[s] -= 1 39 if semAwoken[s] == 0 { 40 delete(semAwoken, s) 41 } 42 } 43 *s-- 44 } 45 46 func runtime_Semrelease(s *uint32, handoff bool, skipframes int) { 47 // TODO: Use handoff, skipframes if needed/possible. 48 *s++ 49 50 w := semWaiters[s] 51 if len(w) == 0 { 52 return 53 } 54 55 ch := w[0] 56 w = w[1:] 57 semWaiters[s] = w 58 if len(w) == 0 { 59 delete(semWaiters, s) 60 } 61 62 semAwoken[s] += 1 63 64 ch <- true 65 } 66 67 func runtime_notifyListCheck(size uintptr) {} 68 69 func runtime_canSpin(i int) bool { 70 return false 71 } 72 73 // Copy of time.runtimeNano. 74 func runtime_nanotime() int64 { 75 const millisecond = 1000000 76 return js.Global.Get("Date").New().Call("getTime").Int64() * millisecond 77 } 78 79 // Implemented in runtime. 80 func throw(s string) { 81 js.Global.Call("$throwRuntimeError", s) 82 }