diff --git a/src/header/semaphore/mod.rs b/src/header/semaphore/mod.rs
index 505d6eba6f934666fdc6eb09955e674125e372cd..5ad4c3c787f7d7438d8d4d1bfb9e361fa8d1f8dd 100644
--- a/src/header/semaphore/mod.rs
+++ b/src/header/semaphore/mod.rs
@@ -1,61 +1,72 @@
 use crate::platform::types::*;
 
+// TODO: Statically verify size and align
 #[repr(C)]
-#[derive(Copy)]
+#[derive(Clone, Copy)]
 pub union sem_t {
-    pub size: [c_char; 32usize],
+    pub size: [c_char; 4],
     pub align: c_long,
-    _bindgen_union_align: [u64; 4usize],
 }
-impl Clone for sem_t {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
-// #[no_mangle]
-pub extern "C" fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int {
-    unimplemented!();
+pub type RlctSempahore = crate::sync::Semaphore;
+
+#[no_mangle]
+pub unsafe extern "C" fn sem_init(sem: *mut sem_t, _pshared: c_int, value: c_uint) -> c_int {
+    sem.cast::<RlctSempahore>().write(RlctSempahore::new(value));
+
+    0
 }
 
-// #[no_mangle]
-pub extern "C" fn sem_destroy(sem: *mut sem_t) -> c_int {
-    unimplemented!();
+#[no_mangle]
+pub unsafe extern "C" fn sem_destroy(sem: *mut sem_t) -> c_int {
+    core::ptr::drop_in_place(sem.cast::<RlctSempahore>());
+    0
 }
 
-/*
- *#[no_mangle]
- *pub extern "C" fn sem_open(name: *const c_char,
- *                    oflag: c_int, ...) -> *mut sem_t {
- *    unimplemented!();
- *}
- */
 
+// TODO: va_list
 // #[no_mangle]
-pub extern "C" fn sem_close(sem: *mut sem_t) -> c_int {
-    unimplemented!();
+pub unsafe extern "C" fn sem_open(name: *const c_char, oflag: c_int, /* (va_list) value: c_uint */) -> *mut sem_t {
+    todo!("named semaphores")
 }
 
 // #[no_mangle]
-pub extern "C" fn sem_unlink(name: *const c_char) -> c_int {
-    unimplemented!();
+pub unsafe extern "C" fn sem_close(sem: *mut sem_t) -> c_int {
+    todo!("named semaphores")
 }
 
 // #[no_mangle]
-pub extern "C" fn sem_wait(sem: *mut sem_t) -> c_int {
-    unimplemented!();
+pub unsafe extern "C" fn sem_unlink(name: *const c_char) -> c_int {
+    todo!("named semaphores")
 }
 
-// #[no_mangle]
-pub extern "C" fn sem_trywait(sem: *mut sem_t) -> c_int {
-    unimplemented!();
+#[no_mangle]
+pub unsafe extern "C" fn sem_wait(sem: *mut sem_t) -> c_int {
+    get(sem).wait(None);
+
+    0
 }
 
-// #[no_mangle]
-pub extern "C" fn sem_post(sem: *mut sem_t) -> c_int {
-    unimplemented!();
+#[no_mangle]
+pub unsafe extern "C" fn sem_trywait(sem: *mut sem_t) -> c_int {
+    get(sem).try_wait();
+
+    0
 }
 
-// #[no_mangle]
-pub extern "C" fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int {
-    unimplemented!();
+#[no_mangle]
+pub unsafe extern "C" fn sem_post(sem: *mut sem_t) -> c_int {
+    get(sem).post(1);
+
+    0
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int {
+    sval.write(get(sem).value() as c_int);
+
+    0
+}
+
+unsafe fn get<'any>(sem: *mut sem_t) -> &'any RlctSempahore {
+    &*sem.cast()
 }
diff --git a/src/sync/semaphore.rs b/src/sync/semaphore.rs
index aa38929f1eef94d4fbb6818b89f85536a22fbc07..708acafca9ed919622cf58ca4ce211f37d99594d 100644
--- a/src/sync/semaphore.rs
+++ b/src/sync/semaphore.rs
@@ -7,43 +7,57 @@ use crate::{
     platform::{types::*, Pal, Sys},
 };
 
-use core::sync::atomic::Ordering;
+use core::sync::atomic::{AtomicU32, Ordering};
 
 pub struct Semaphore {
-    lock: AtomicLock,
+    count: AtomicU32,
 }
 
 impl Semaphore {
-    pub const fn new(value: c_int) -> Self {
+    pub const fn new(value: c_uint) -> Self {
         Self {
-            lock: AtomicLock::new(value),
+            count: AtomicU32::new(value),
         }
     }
 
-    pub fn post(&self, count: c_int) {
-        self.lock.fetch_add(count, Ordering::SeqCst);
-        self.lock.notify_all();
+    // TODO: Acquire-Release ordering?
+
+    pub fn post(&self, count: c_uint) {
+        self.count.fetch_add(count, Ordering::SeqCst);
+        // TODO: notify one?
+        crate::sync::futex_wake(&self.count, i32::MAX);
     }
 
-    pub fn wait(&self, timeout_opt: Option<&timespec>) -> Result<(), ()> {
+    pub fn try_wait(&self) -> u32 {
         loop {
-            let value = self.lock.load(Ordering::SeqCst);
-            if value > 0 {
-                match self.lock.compare_exchange(
-                    value,
-                    value - 1,
-                    Ordering::SeqCst,
-                    Ordering::SeqCst,
-                ) {
-                    Ok(_) => {
-                        // Acquired
-                        return Ok(());
-                    }
-                    Err(_) => (),
+            let value = self.count.load(Ordering::SeqCst);
+
+            if value == 0 { return 0 }
+
+            match self.count.compare_exchange_weak(
+                value,
+                value - 1,
+                Ordering::SeqCst,
+                Ordering::SeqCst,
+            ) {
+                Ok(_) => {
+                    // Acquired
+                    return value;
                 }
-                // Try again (as long as value > 0)
-                continue;
+                Err(_) => (),
             }
+            // Try again (as long as value > 0)
+        }
+    }
+
+    pub fn wait(&self, timeout_opt: Option<&timespec>) -> Result<(), ()> {
+        loop {
+            let value = self.try_wait();
+
+            if value == 0 {
+                return Ok(());
+            }
+
             if let Some(timeout) = timeout_opt {
                 let mut time = timespec::default();
                 clock_gettime(CLOCK_MONOTONIC, &mut time);
@@ -64,12 +78,16 @@ impl Semaphore {
                     }
                     relative.tv_sec -= time.tv_sec;
                     relative.tv_nsec -= time.tv_nsec;
-                    self.lock.wait_if(value, Some(&relative));
+
+                    crate::sync::futex_wait(&self.count, value, Some(&relative));
                 }
             } else {
                 // Use futex to wait for the next change, without a timeout
-                self.lock.wait_if(value, None);
+                crate::sync::futex_wait(&self.count, value, None);
             }
         }
     }
+    pub fn value(&self) -> c_uint {
+        self.count.load(Ordering::SeqCst)
+    }
 }