| #include <errno.h> | 
 | #include <locks.h> | 
 |  | 
 | namespace | 
 | { | 
 | 	constexpr uint32_t WaitersBit = 1 << 31; | 
 | } // namespace | 
 |  | 
 | int semaphore_get(Timeout *timeout, CountingSemaphoreState *semaphore) | 
 | { | 
 | 	do | 
 | 	{ | 
 | 		uint32_t value      = semaphore->count.load(); | 
 | 		uint32_t count      = value & ~WaitersBit; | 
 | 		bool     hasWaiters = value & WaitersBit; | 
 | 		// If the count is greater than zero, we should be able to just acquire | 
 | 		// a semaphore. | 
 | 		if (count > 0) | 
 | 		{ | 
 | 			if (semaphore->count.compare_exchange_strong(value, value - 1)) | 
 | 			{ | 
 | 				return 0; | 
 | 			} | 
 | 			continue; | 
 | 		} | 
 | 		// If there are no waiters, mark this as adding one. | 
 | 		if (!hasWaiters) | 
 | 		{ | 
 | 			// If we lost a race, retry. | 
 | 			if (!semaphore->count.compare_exchange_strong(value, | 
 | 			                                              value | WaitersBit)) | 
 | 			{ | 
 | 				continue; | 
 | 			} | 
 | 		} | 
 | 		// If we fail in the futex wait, return the error. | 
 | 		if (int ret = semaphore->count.wait(timeout, value | WaitersBit); | 
 | 		    ret != 0) | 
 | 		{ | 
 | 			return ret; | 
 | 		} | 
 | 	} while (true); | 
 | } | 
 |  | 
 | int semaphore_put(CountingSemaphoreState *semaphore) | 
 | { | 
 | 	do | 
 | 	{ | 
 | 		uint32_t value      = semaphore->count.load(); | 
 | 		uint32_t count      = value & ~WaitersBit; | 
 | 		bool     hasWaiters = value & WaitersBit; | 
 | 		if (count == semaphore->maxCount) | 
 | 		{ | 
 | 			return -EINVAL; | 
 | 		} | 
 | 		if (semaphore->count.compare_exchange_strong(value, count + 1)) | 
 | 		{ | 
 | 			// If there were waiters, wake them. | 
 | 			if (hasWaiters) | 
 | 			{ | 
 | 				semaphore->count.notify_all(); | 
 | 			} | 
 | 			return 0; | 
 | 		} | 
 | 	} while (true); | 
 | } |