mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-09 05:23:40 +00:00
120d17c124
This is not a scheduler in the runtime, instead every goroutine is mapped to a single OS thread - meaning 1:1 scheduling. While this may not perform well (or at all) for large numbers of threads, it greatly simplifies many things in the runtime. For example, blocking syscalls can be called directly instead of having to use epoll or similar. Also, we don't need to do anything special to call C code - the default stack is all we need.
33 lines
816 B
Go
33 lines
816 B
Go
package task
|
|
|
|
// Barebones semaphore implementation.
|
|
// The main limitation is that if there are multiple waiters, a single Post()
|
|
// call won't do anything. Only when Post() has been called to awaken all
|
|
// waiters will the waiters proceed.
|
|
// This limitation is not a problem when there will only be a single waiter.
|
|
type Semaphore struct {
|
|
futex Futex
|
|
}
|
|
|
|
// Post (unlock) the semaphore, incrementing the value in the semaphore.
|
|
func (s *Semaphore) Post() {
|
|
newValue := s.futex.Add(1)
|
|
if newValue == 0 {
|
|
s.futex.WakeAll()
|
|
}
|
|
}
|
|
|
|
// Wait (lock) the semaphore, decrementing the value in the semaphore.
|
|
func (s *Semaphore) Wait() {
|
|
delta := int32(-1)
|
|
value := s.futex.Add(uint32(delta))
|
|
for {
|
|
if int32(value) >= 0 {
|
|
// Semaphore unlocked!
|
|
return
|
|
}
|
|
s.futex.Wait(value)
|
|
value = s.futex.Load()
|
|
}
|
|
}
|