;;;; support for threads needed at cross-compile time ;;;; This software is part of the SBCL system. See the README file for ;;;; more information. ;;;; ;;;; This software is derived from the CMU CL system, which was ;;;; written at Carnegie Mellon University and released into the ;;;; public domain. The software is in the public domain and is ;;;; provided with absolutely no warranty. See the COPYING and CREDITS ;;;; files for more information. (in-package "SB!THREAD") (def!struct mutex #!+sb-doc "Mutex type." (name nil :type (or null simple-string)) (value nil) #!+(and sb-lutex sb-thread) (lutex (make-lutex))) (def!struct spinlock #!+sb-doc "Spinlock type." (name nil :type (or null simple-string)) (value nil)) (sb!xc:defmacro with-mutex ((mutex &key (value '*current-thread*) (wait-p t)) &body body) #!+sb-doc "Acquire MUTEX for the dynamic scope of BODY, setting it to NEW-VALUE or some suitable default value if NIL. If WAIT-P is non-NIL and the mutex is in use, sleep until it is available" `(call-with-mutex (lambda () ,@body) ,mutex ,value ,wait-p)) (sb!xc:defmacro with-recursive-lock ((mutex) &body body) #!+sb-doc "Acquires MUTEX for the dynamic scope of BODY. Within that scope further recursive lock attempts for the same mutex succeed. It is allowed to mix WITH-MUTEX and WITH-RECURSIVE-LOCK for the same mutex provided the default value is used for the mutex." `(call-with-recursive-lock (lambda () ,@body) ,mutex)) (sb!xc:defmacro with-recursive-spinlock ((spinlock) &body body) `(call-with-recursive-spinlock (lambda () ,@body) ,spinlock)) (sb!xc:defmacro with-spinlock ((spinlock) &body body) `(call-with-spinlock (lambda () ,@body) ,spinlock)) ;;; KLUDGE: this separate implementation for (NOT SB-THREAD) is not ;;; strictly necessary; GET-MUTEX and RELEASE-MUTEX are implemented. ;;; However, there would be a (possibly slight) performance hit in ;;; using them. #!-sb-thread (progn (defun call-with-system-mutex (function mutex &optional without-gcing-p) (declare (ignore mutex) (function function)) (if without-gcing-p (without-gcing (funcall function)) (without-interrupts (funcall function)))) (defun call-with-system-spinlock (function lock &optional without-gcing-p) (declare (ignore lock) (function function)) (if without-gcing-p (without-gcing (funcall function)) (without-interrupts (funcall function)))) (defun call-with-mutex (function mutex value waitp) (declare (ignore mutex value waitp) (function function)) (funcall function)) (defun call-with-recursive-lock (function mutex) (declare (ignore mutex) (function function)) (funcall function)) (defun call-with-spinlock (function spinlock) (declare (ignore spinlock) (function function)) (funcall function)) (defun call-with-recursive-spinlock (function spinlock) (declare (ignore spinlock) (function function)) (funcall function))) #!+sb-thread (progn (defun call-with-system-mutex (function mutex &optional without-gcing-p) (declare (function function)) (flet ((%call-with-system-mutex () (let (got-it) (unwind-protect (when (setf got-it (get-mutex mutex)) (funcall function)) (when got-it (release-mutex mutex)))))) (if without-gcing-p (without-gcing (%call-with-system-mutex)) (without-interrupts (%call-with-system-mutex))))) (defun call-with-recursive-system-spinlock (function lock &optional without-gcing-p) (declare (function function)) (flet ((%call-with-system-spinlock () (let ((inner-lock-p (eq *current-thread* (spinlock-value lock))) (got-it nil)) (unwind-protect (when (or inner-lock-p (setf got-it (get-spinlock lock))) (funcall function)) (when got-it (release-spinlock lock)))))) (if without-gcing-p (without-gcing (%call-with-system-spinlock)) (without-interrupts (%call-with-system-spinlock))))) (defun call-with-mutex (function mutex value waitp) (declare (function function)) (let ((got-it nil)) (without-interrupts (unwind-protect (when (setq got-it (allow-with-interrupts (get-mutex mutex value waitp))) (with-local-interrupts (funcall function))) (when got-it (release-mutex mutex)))))) (defun call-with-recursive-lock (function mutex) (declare (function function)) (let ((inner-lock-p (eq (mutex-value mutex) *current-thread*)) (got-it nil)) (without-interrupts (unwind-protect (when (or inner-lock-p (setf got-it (allow-with-interrupts (get-mutex mutex)))) (with-local-interrupts (funcall function))) (when got-it (release-mutex mutex)))))) (defun call-with-spinlock (function spinlock) (declare (function function)) (let ((got-it nil)) (without-interrupts (unwind-protect (when (setf got-it (allow-with-interrupts (get-spinlock spinlock))) (with-local-interrupts (funcall function))) (when got-it (release-spinlock spinlock)))))) (defun call-with-recursive-spinlock (function spinlock) (declare (function function)) (let ((inner-lock-p (eq (spinlock-value spinlock) *current-thread*)) (got-it nil)) (without-interrupts (unwind-protect (when (or inner-lock-p (setf got-it (allow-with-interrupts (get-spinlock spinlock)))) (with-local-interrupts (funcall function))) (when got-it (release-spinlock spinlock)))))))