X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Fthread.lisp;h=01bbac7669ab8285067d35ea7e8f171ea71a3456;hb=975f1932acc3a8e90fb31d2b055bfbdde78ea927;hp=367b90dcf7e7e9c33a676cad82ec4af0d46cc166;hpb=776a2f1275624352bbba37b03dabea03ec13a9e5;p=sbcl.git diff --git a/src/code/thread.lisp b/src/code/thread.lisp index 367b90d..01bbac7 100644 --- a/src/code/thread.lisp +++ b/src/code/thread.lisp @@ -31,25 +31,19 @@ "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" - #!-sb-thread (declare (ignore mutex value wait-p)) - #!+sb-thread - (with-unique-names (got mutex1) - `(let ((,mutex1 ,mutex) - ,got) - (/show0 "WITH-MUTEX") - (unwind-protect - ;; FIXME: async unwind in SETQ form - (when (setq ,got (get-mutex ,mutex1 ,value ,wait-p)) - (locally - ,@body)) - (when ,got - (release-mutex ,mutex1))))) - ;; KLUDGE: this separate expansion 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 - `(locally ,@body)) + `(dx-flet ((with-mutex-thunk () ,@body)) + (call-with-mutex + #'with-mutex-thunk + ,mutex + ,value + ,wait-p))) + +(sb!xc:defmacro with-system-mutex ((mutex &key without-gcing) &body body) + `(dx-flet ((with-system-mutex-thunk () ,@body)) + (call-with-system-mutex + #'with-system-mutex-thunk + ,mutex + ,without-gcing))) (sb!xc:defmacro with-recursive-lock ((mutex) &body body) #!+sb-doc @@ -57,51 +51,178 @@ and the mutex is in use, sleep until it is available" 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." - #!-sb-thread - (declare (ignore mutex)) - #!+sb-thread - (with-unique-names (mutex1 inner-lock-p) - `(let* ((,mutex1 ,mutex) - (,inner-lock-p (eq (mutex-value ,mutex1) *current-thread*))) - (unwind-protect - (progn - (unless ,inner-lock-p - (get-mutex ,mutex1)) - (locally - ,@body)) - (unless ,inner-lock-p - (release-mutex ,mutex1))))) - #!-sb-thread - `(locally ,@body)) + `(dx-flet ((with-recursive-lock-thunk () ,@body)) + (call-with-recursive-lock + #'with-recursive-lock-thunk + ,mutex))) (sb!xc:defmacro with-recursive-spinlock ((spinlock) &body body) - #!-sb-thread - (declare (ignore spinlock)) - #!+sb-thread - (with-unique-names (lock inner-lock-p got-it) - `(let* ((,lock ,spinlock) - (,inner-lock-p (eq (spinlock-value ,lock) *current-thread*)) - (,got-it nil)) - (unwind-protect - (when (or ,inner-lock-p (setf ,got-it (get-spinlock ,lock))) - (locally ,@body)) - (when ,got-it - (release-spinlock ,lock))))) - #!-sb-thread - `(locally ,@body)) + `(dx-flet ((with-recursive-spinlock-thunk () ,@body)) + (call-with-recursive-spinlock + #'with-recursive-spinlock-thunk + ,spinlock))) + +(sb!xc:defmacro with-recursive-system-spinlock ((spinlock &key without-gcing) + &body body) + `(dx-flet ((with-recursive-system-spinlock-thunk () ,@body)) + (call-with-recursive-system-spinlock + #'with-recursive-system-spinlock-thunk + ,spinlock + ,without-gcing))) (sb!xc:defmacro with-spinlock ((spinlock) &body body) - #!-sb-thread - (declare (ignore spinlock)) - #!-sb-thread - `(locally ,@body) - #!+sb-thread - (with-unique-names (lock got-it) - `(let ((,lock ,spinlock) - (,got-it nil)) - (unwind-protect - (progn - (setf ,got-it (get-spinlock ,lock)) - (locally ,@body)) - (when ,got-it - (release-spinlock ,lock)))))) + `(dx-flet ((with-spinlock-thunk () ,@body)) + (call-with-spinlock + #'with-spinlock-thunk + ,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 + (allow-with-interrupts (funcall function))))) + + (defun call-with-system-spinlock (function spinlock &optional without-gcing-p) + (declare (ignore spinlock) + (function function)) + (if without-gcing-p + (without-gcing + (funcall function)) + (without-interrupts + (allow-with-interrupts (funcall function))))) + + (defun call-with-recursive-system-spinlock (function lock + &optional without-gcing-p) + (declare (ignore lock) + (function function)) + (if without-gcing-p + (without-gcing + (funcall function)) + (without-interrupts + (allow-with-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 +;;; KLUDGE: These need to use DX-LET, because the cleanup form that +;;; closes over GOT-IT causes a value-cell to be allocated for it -- and +;;; we prefer that to go on the stack since it can. +(progn + (defun call-with-system-mutex (function mutex &optional without-gcing-p) + (declare (function function)) + (flet ((%call-with-system-mutex () + (dx-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 + (allow-with-interrupts (%call-with-system-mutex)))))) + + (defun call-with-system-spinlock (function spinlock &optional without-gcing-p) + (declare (function function)) + (flet ((%call-with-system-spinlock () + (dx-let (got-it) + (unwind-protect + (when (setf got-it (get-spinlock spinlock)) + (funcall function)) + (when got-it + (release-spinlock spinlock)))))) + (if without-gcing-p + (without-gcing + (%call-with-system-spinlock)) + (without-interrupts + (allow-with-interrupts (%call-with-system-spinlock)))))) + + (defun call-with-recursive-system-spinlock (function lock + &optional without-gcing-p) + (declare (function function)) + (flet ((%call-with-system-spinlock () + (dx-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 + (allow-with-interrupts (%call-with-system-spinlock)))))) + + (defun call-with-spinlock (function spinlock) + (declare (function function)) + (dx-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-mutex (function mutex value waitp) + (declare (function function)) + (dx-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)) + (dx-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-recursive-spinlock (function spinlock) + (declare (function function)) + (dx-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)))))))