diff --git a/src/sync/mod.rs b/src/sync/mod.rs
index 758365c7014f7c82e48179fdb529892814b08629..430abd5b783e341adeced608ac5d7f3c004077cc 100644
--- a/src/sync/mod.rs
+++ b/src/sync/mod.rs
@@ -1,9 +1,11 @@
 pub mod mutex;
 pub mod once;
+pub mod semaphore;
 
 pub use self::{
     mutex::{Mutex, MutexGuard},
     once::Once,
+    semaphore::Semaphore,
 };
 
 use crate::platform::{types::*, Pal, Sys};
diff --git a/src/sync/semaphore.rs b/src/sync/semaphore.rs
new file mode 100644
index 0000000000000000000000000000000000000000..7734c58a171bb0c8c8afecb94e30f792f8b189b3
--- /dev/null
+++ b/src/sync/semaphore.rs
@@ -0,0 +1,46 @@
+// From https://www.remlab.net/op/futex-misc.shtml
+//TODO: improve implementation
+
+use crate::platform::{types::*, Pal, Sys};
+use super::AtomicLock;
+use core::sync::atomic::Ordering;
+
+pub struct Semaphore {
+    lock: AtomicLock,
+}
+
+impl Semaphore {
+    pub const fn new(value: c_int) -> Self {
+        Self {
+            lock: AtomicLock::new(value),
+        }
+    }
+
+    pub fn post(&self) {
+        self.lock.fetch_add(1, Ordering::Relaxed);
+        self.lock.notify_one();
+    }
+
+    pub fn wait(&self) {
+        let mut value = 1;
+
+        loop {
+            match self.lock.compare_exchange_weak(
+                value,
+                value - 1,
+                Ordering::Acquire,
+                Ordering::Relaxed
+            ) {
+                Ok(ok) => return,
+                Err(err) => {
+                    value = err;
+                }
+            }
+
+            if value == 0 {
+                self.lock.wait_if(0);
+                value = 1;
+            }
+        }
+    }
+}