- #!-sb-thread (declare (ignore queue))
- #!-sb-thread (error "Not supported in unithread builds.")
- #!+sb-thread
- (let ((me *current-thread*))
- (setf (waitqueue-data queue) me)
- (futex-wake (waitqueue-data-address queue) (ash 1 30))))
+ (condition-notify queue most-positive-fixnum))
+
+;;;; semaphores
+
+(defstruct (semaphore (:constructor %make-semaphore))
+ #!+sb-doc
+ "Semaphore type."
+ (name nil :type (or null simple-string))
+ (count 0 :type (integer 0))
+ (mutex (make-mutex))
+ (queue (make-waitqueue)))
+
+(defun make-semaphore (&key name (count 0))
+ #!+sb-doc
+ "Create a semaphore with the supplied COUNT."
+ (%make-semaphore :name name :count count))
+
+(setf (sb!kernel:fdocumentation 'semaphore-name 'function)
+ "The name of the semaphore. Setfable.")
+
+(defun wait-on-semaphore (sem)
+ #!+sb-doc
+ "Decrement the count of SEM if the count would not be negative. Else
+block until the semaphore can be decremented."
+ ;; a more direct implementation based directly on futexes should be
+ ;; possible
+ (with-mutex ((semaphore-mutex sem))
+ (loop until (> (semaphore-count sem) 0)
+ do (condition-wait (semaphore-queue sem) (semaphore-mutex sem))
+ finally (decf (semaphore-count sem)))))
+
+(defun signal-semaphore (sem &optional (n 1))
+ #!+sb-doc
+ "Increment the count of SEM by N. If there are threads waiting on
+this semaphore, then N of them is woken up."
+ (declare (type (and fixnum (integer 1)) n))
+ (with-mutex ((semaphore-mutex sem))
+ (when (= n (incf (semaphore-count sem) n))
+ (condition-notify (semaphore-queue sem) n))))