Index: libcfa/src/bits/locks.hfa
===================================================================
--- libcfa/src/bits/locks.hfa	(revision 793063833fbbe0b2e67a84a514b08d12dd6f84c6)
+++ libcfa/src/bits/locks.hfa	(revision f00b26d473acc916ee96e28fa1365688d9b3c2da)
@@ -164,3 +164,58 @@
 
 	#undef CHECKED
+
+	struct $thread;
+	extern void park( __cfaabi_dbg_ctx_param );
+	extern void unpark( struct $thread * this __cfaabi_dbg_ctx_param2 );
+	static inline struct $thread * active_thread ();
+
+	// Semaphore which only supports a single thread
+	struct single_sem {
+		struct $thread * volatile ptr;
+	};
+
+	static inline {
+		void  ?{}(single_sem & this) {
+			this.ptr = 0p;
+		}
+
+		void ^?{}(single_sem & this) {}
+
+		bool wait(single_sem & this) {
+			for() {
+				struct $thread * expected = this.ptr;
+				if(expected == 1p) {
+					if(__atomic_compare_exchange_n(&this.ptr, &expected, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
+						return false;
+					}
+				}
+				else {
+					/* paranoid */ verify( expected == 0p );
+					if(__atomic_compare_exchange_n(&this.ptr, &expected, active_thread(), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
+						park( __cfaabi_dbg_ctx );
+						return true;
+					}
+				}
+
+			}
+		}
+
+		bool post(single_sem & this) {
+			for() {
+				struct $thread * expected = this.ptr;
+				if(expected == 1p) return false;
+				if(expected == 0p) {
+					if(__atomic_compare_exchange_n(&this.ptr, &expected, 1p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
+						return false;
+					}
+				}
+				else {
+					if(__atomic_compare_exchange_n(&this.ptr, &expected, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
+						unpark( expected __cfaabi_dbg_ctx2 );
+						return true;
+					}
+				}
+			}
+		}
+	}
 #endif
