xref: /relibc/src/sync/semaphore.rs (revision 1a0edd8eeb2e3aae407a91795696461f475b445e)
1 // From https://www.remlab.net/op/futex-misc.shtml
2 //TODO: improve implementation
3 
4 use crate::platform::{types::*, Pal, Sys};
5 use super::AtomicLock;
6 use core::sync::atomic::Ordering;
7 
8 pub struct Semaphore {
9     lock: AtomicLock,
10 }
11 
12 impl Semaphore {
13     pub const fn new(value: c_int) -> Self {
14         Self {
15             lock: AtomicLock::new(value),
16         }
17     }
18 
19     pub fn post(&self) {
20         self.lock.fetch_add(1, Ordering::Relaxed);
21         self.lock.notify_one();
22     }
23 
24     pub fn wait(&self) {
25         let mut value = 1;
26 
27         loop {
28             match self.lock.compare_exchange_weak(
29                 value,
30                 value - 1,
31                 Ordering::Acquire,
32                 Ordering::Relaxed
33             ) {
34                 Ok(ok) => return,
35                 Err(err) => {
36                     value = err;
37                 }
38             }
39 
40             if value == 0 {
41                 self.lock.wait_if(0);
42                 value = 1;
43             }
44         }
45     }
46 }
47