@c Generated by the sb-manual contrib. Do not edit.

@node threading
@chapter Threading

@menu
* Threading Basics: threading basics.
* Special Variables: special variables.
* Atomic Operations: atomic operations.
* Mutex Support: mutex support.
* Semaphores: semaphores.
* Waitqueue/condition variables: waitqueue/condition variables.
* Barriers: barriers.
* Sessions/Debugging: sessions/debugging.
* Foreign threads: foreign threads.
* Implementation on Linux x86oids: implementation on linux x86oids.
@end menu

SBCL supports a fairly low-level threading interface that maps onto
the host operating system's concept of threads or lightweight
processes. This means that threads may take advantage of hardware
multiprocessing on machines that have more than one CPU, but it does
not allow Lisp control of the scheduler. This is found in the
@code{sb-thread} package.

Threads are part of the default build on x86[-64]/ARM64 Linux and
Windows.

They are also supported on: x86[-64] Darwin (Mac OS X), x86[-64]
FreeBSD, x86 SunOS (Solaris), PPC Linux, ARM64 Linux, RISC-V Linux.
On these platforms threads must be explicitly enabled at build-time,
see @code{install} for directions.

@node threading basics
@section Threading Basics

@menu
* Thread Objects: thread objects.
* Running Threads: running threads.
* Asynchronous Operations: asynchronous operations.
* Miscellaneous Operations: miscellaneous operations.
* Error Conditions: error conditions.
@end menu

@example
(make-thread (lambda () (write-line "Hello, world")))
@end example

@node thread objects
@subsection Thread Objects

@anchor{Structure sb-thread thread}
@ttindex @sortas{thread sb-thread} thread [sb-thread]
@deffn{Structure} sb-thread:thread
Thread type. Do not rely on threads being structs as it may change
in future versions.
@end deffn
@anchor{Variable sb-thread *current-thread*}
@vvindex @sortas{current-thread* sb-thread} *current-thread* [sb-thread]
@deffn{Variable} sb-thread:*current-thread*
Bound in each thread to the thread itself.
@end deffn
@anchor{Function sb-thread list-all-threads}
@ffindex @sortas{list-all-threads sb-thread} list-all-threads [sb-thread]
@deffn{Function} sb-thread:list-all-threads
Return a list of the live threads. Note that the return value is
potentially stale even before the function returns, as new threads may be
created and old ones may exit at any time.
@end deffn
@anchor{Function sb-thread thread-alive-p}
@ffindex @sortas{thread-alive-p sb-thread} thread-alive-p [sb-thread]
@deffn{Function} sb-thread:thread-alive-p thread
Return @code{t} if @code{thread} is still alive. Note that the return value is
potentially stale even before the function returns, as the thread may exit at
any time.
@end deffn
@anchor{Function sb-thread thread-name}
@ffindex @sortas{thread-name sb-thread} thread-name [sb-thread]
@deffn{Function} sb-thread:thread-name thread
Name of the thread. Can be assigned to using @code{setf}. A thread name must be
a simple-string (not necessarily unique) or @code{nil}.
@end deffn
@anchor{Function sb-thread main-thread-p}
@ffindex @sortas{main-thread-p sb-thread} main-thread-p [sb-thread]
@deffn{Function} sb-thread:main-thread-p &optional thread
True if @code{thread}, defaulting to current thread, is the main thread of the process.
@end deffn
@anchor{Function sb-thread main-thread}
@ffindex @sortas{main-thread sb-thread} main-thread [sb-thread]
@deffn{Function} sb-thread:main-thread
Returns the main thread of the process.
@end deffn
@node running threads
@subsection Running Threads

@anchor{Function sb-thread make-thread}
@ffindex @sortas{make-thread sb-thread} make-thread [sb-thread]
@deffn{Function} sb-thread:make-thread function &key name arguments
Create a new thread of @code{name} that runs @code{function} with the argument
list designator provided (defaults to no argument). Thread exits when
the function returns. The return values of @code{function} are kept around
and can be retrieved by @code{join-thread}.

Invoking the initial @code{abort} restart established by @code{make-thread}
terminates the thread.
@end deffn
@anchor{Macro sb-thread return-from-thread}
@ffindex @sortas{return-from-thread sb-thread} return-from-thread [sb-thread]
@deffn{Macro} sb-thread:return-from-thread values-form &key allow-exit
Unwinds from and terminates the current thread, with values from
@code{values-form} as the results visible to @code{join-thread}.

If current thread is the main thread of the process (see
@code{main-thread-p}), signals an error unless @code{allow-exit} is true, as
terminating the main thread would terminate the entire process. If
@code{allow-exit} is true, returning from the main thread is equivalent to
calling @code{sb-ext:exit} with @code{:code} 0 and @code{:abort} @code{nil}.
@end deffn
@anchor{Function sb-thread abort-thread}
@ffindex @sortas{abort-thread sb-thread} abort-thread [sb-thread]
@deffn{Function} sb-thread:abort-thread &key allow-exit
Unwinds from and terminates the current thread abnormally, causing
@code{join-thread} on current thread to signal an error unless a
default-value is provided.

If current thread is the main thread of the process (see
@code{main-thread-p}), signals an error unless @code{allow-exit} is true, as
terminating the main thread would terminate the entire process. If
@code{allow-exit} is true, aborting the main thread is equivalent to calling
@code{sb-ext:exit} code 1 and @code{:abort} @code{nil}.

Invoking the initial @code{abort} restart established by @code{make-thread} is
equivalent to calling @code{abort-thread} in other than main threads.
However, whereas @code{abort} restart may be rebound, @code{abort-thread} always
unwinds the entire thread. (Behaviour of the initial @code{abort} restart for
main thread depends on the @code{:toplevel} argument to
@code{sb-ext:save-lisp-and-die}.)
@end deffn
@anchor{Function sb-thread join-thread}
@ffindex @sortas{join-thread sb-thread} join-thread [sb-thread]
@deffn{Function} sb-thread:join-thread thread &key default timeout
Suspend current thread until @code{thread} exits. Return the result values
of the thread function.

If @code{thread} does not exit within @code{timeout} seconds and @code{default} is
supplied, return two values: 1) @code{default} 2) @code{:timeout}. If @code{default} is not
supplied, signal a @code{join-thread-error} with @code{join-thread-problem} equal
to @code{:timeout}.

If @code{thread} does not exit normally (i.e. aborted) and @code{default} is
supplied, return two values: 1) @code{default} 2) @code{:abort}. If @code{default} is not
supplied, signal a @code{join-thread-error} with @code{join-thread-problem} equal
to @code{:abort}.

If @code{thread} is the current thread, signal a @code{join-thread-error} with
@code{join-thread-problem} equal to @code{:self-join}.

Trying to join the main thread causes @code{join-thread} to block until
@code{timeout} occurs or the process exits: when the main thread exits, the
entire process exits.

Users should not rely on the ability to join a chosen @code{thread} from more
than one other thread simultaneously. Future changes to @code{join-thread} may
directly call the underlying thread library, and not all threading
implementations consider such usage to be well-defined.

@quotation
@emph{Note}: Return convention in case of a timeout is experimental and
subject to change.
@end quotation
@end deffn
@anchor{Function sb-thread thread-yield}
@ffindex @sortas{thread-yield sb-thread} thread-yield [sb-thread]
@deffn{Function} sb-thread:thread-yield
Yield the processor to other threads.
@end deffn
@node asynchronous operations
@subsection Asynchronous Operations

@anchor{Function sb-thread interrupt-thread}
@ffindex @sortas{interrupt-thread sb-thread} interrupt-thread [sb-thread]
@deffn{Function} sb-thread:interrupt-thread thread function
Interrupt @code{thread} and make it run @code{function}.

The interrupt is asynchronous, and can occur anywhere with the exception of
sections protected using @code{sb-sys:without-interrupts}.

@code{function} is called with interrupts disabled, under
@code{sb-sys:allow-with-interrupts}. Since functions such as @code{grab-mutex} may try to
enable interrupts internally, in most cases @code{function} should either enter
@code{sb-sys:with-interrupts} to allow nested interrupts, or
@code{sb-sys:without-interrupts} to prevent them completely.

When a thread receives multiple interrupts, they are executed in the order
they were sent -- first in, first out.

This means that a great degree of care is required to use @code{interrupt-thread}
safely and sanely in a production environment. The general recommendation is
to limit uses of @code{interrupt-thread} for interactive debugging, banning it
entirely from production environments -- it is simply exceedingly hard to use
correctly.

With those caveats in mind, what you need to know when using it:

@itemize
@item If calling @code{function} causes a non-local transfer of control (ie. an
  unwind), all normal cleanup forms will be executed.

However, if the interrupt occurs during cleanup forms of an
@code{unwind-protect}, it is just as if that had happened due to a
regular @code{go}, @code{throw}, or @code{return-from}: the interrupted cleanup form
and those following it in the same @code{unwind-protect} do not get
executed.

SBCL tries to keep its own internals asynch-unwind-safe, but this
is frankly an unreasonable expectation for third party libraries,
especially given that asynch-unwind-safety does not compose: a
function calling only asynch-unwind-safe function isn't
automatically asynch-unwind-safe.

This means that in order for an asynch unwind to be safe, the
entire callstack at the point of interruption needs to be
asynch-unwind-safe.

@item In addition to asynch-unwind-safety you must consider the issue of
  reentrancy. @code{interrupt-thread} can cause function that are never
  normally called recursively to be re-entered during their dynamic
  contour, which may cause them to misbehave. (Consider binding of
  special variables, values of global variables, etc.)
@end itemize

Taken together, these two restrict the "safe" things to do using
@code{interrupt-thread} to a fairly minimal set. One useful one -- exclusively for
interactive development use is using it to force entry to debugger to inspect
the state of a thread:

@example
(interrupt-thread thread #'break)
@end example

Short version: be careful out there.
@end deffn
@anchor{Function sb-thread terminate-thread}
@ffindex @sortas{terminate-thread sb-thread} terminate-thread [sb-thread]
@deffn{Function} sb-thread:terminate-thread thread
Terminate the thread identified by @code{thread}, by interrupting it and
causing it to call @code{sb-thread:abort-thread} with @code{:allow-exit} @code{t}.

The unwind caused by @code{terminate-thread} is asynchronous, meaning that
eg. thread executing

@example
(let (foo)
   (unwind-protect
       (progn
          (setf foo (get-foo))
          (work-on-foo foo))
     (when foo
       ;; An interrupt occurring inside the cleanup clause
       ;; will cause cleanups from the current UNWIND-PROTECT
       ;; to be dropped.
       (release-foo foo))))
@end example

might miss calling @code{release-foo} despite GET-FOO having returned true
if the interrupt occurs inside the cleanup clause, eg. during
execution of @code{release-foo}.

Thus, in order to write an asynch unwind safe @code{unwind-protect} you need
to use @code{without-interrupts}:

@example
(let (foo)
  (sb-sys:without-interrupts
    (unwind-protect
        (progn
          (setf foo (sb-sys:allow-with-interrupts
                      (get-foo)))
          (sb-sys:with-local-interrupts
            (work-on-foo foo)))
     (when foo
       (release-foo foo)))))
@end example

Since most libraries using @code{unwind-protect} do not do this, you should never
assume that unknown code can safely be terminated using @code{terminate-thread}.
@end deffn
@node miscellaneous operations
@subsection Miscellaneous Operations

@anchor{Function sb-thread symbol-value-in-thread}
@ffindex @sortas{symbol-value-in-thread sb-thread} symbol-value-in-thread [sb-thread]
@deffn{Function} sb-thread:symbol-value-in-thread symbol thread &optional errorp
Return the local value of @code{symbol} in @code{thread}, and a secondary value of @code{t}
on success.

If the value cannot be retrieved (because the thread has exited or because it
has no local binding for @code{name}) and @code{errorp} is true signals an error of type
@code{symbol-value-in-thread-error}; if @code{errorp} is false returns a primary value of
@code{nil}, and a secondary value of @code{nil}.

Can also be used with @code{setf} to change the thread-local value of @code{symbol}.

@code{symbol-value-in-thread} is primarily intended as a debugging tool, and not as a
mechanism for inter-thread communication.
@end deffn
@node error conditions
@subsection Error Conditions

@anchor{Condition sb-thread thread-error}
@ttindex @sortas{thread-error sb-thread} thread-error [sb-thread]
@deffn{Condition} sb-thread:thread-error
Conditions of type @code{thread-error} are signalled when thread operations fail.
The offending thread is initialized by the @code{:thread} initialization argument and
read by the function @code{thread-error-thread}.
@end deffn
@anchor{Function sb-thread thread-error-thread}
@ffindex @sortas{thread-error-thread sb-thread} thread-error-thread [sb-thread]
@deffn{Function} sb-thread:thread-error-thread condition
Return the offending thread that the @code{thread-error} pertains to.
@end deffn
@anchor{Condition sb-thread symbol-value-in-thread-error}
@ttindex @sortas{symbol-value-in-thread-error sb-thread} symbol-value-in-thread-error [sb-thread]
@deffn{Condition} sb-thread:symbol-value-in-thread-error
Signalled when @code{symbol-value-in-thread} or its @code{setf} version fails due to eg.
the symbol not having a thread-local value, or the target thread having
exited. The offending symbol can be accessed using @code{cell-error-name}, and the
offending thread using @code{thread-error-thread}.
@end deffn
@anchor{Condition sb-thread interrupt-thread-error}
@ttindex @sortas{interrupt-thread-error sb-thread} interrupt-thread-error [sb-thread]
@deffn{Condition} sb-thread:interrupt-thread-error
Signalled when interrupting a thread fails because the thread has already
exited. The offending thread can be accessed using @code{thread-error-thread}.
@end deffn
@anchor{Condition sb-thread join-thread-error}
@ttindex @sortas{join-thread-error sb-thread} join-thread-error [sb-thread]
@deffn{Condition} sb-thread:join-thread-error
Signalled when joining a thread fails due to abnormal exit of the thread
to be joined. The offending thread can be accessed using
@code{thread-error-thread}.
@end deffn
@node special variables
@section Special Variables

The interaction of special variables with multiple threads is mostly
as one would expect, with behaviour very similar to other
implementations.

@itemize
@item Global special values are visible across all threads.

@item Bindings (e.g. using @code{let}) are local to the thread.

@item Threads do not inherit dynamic bindings from the parent thread.
@end itemize

The last point means that

@example
(defparameter *x* 0)
(let ((*x* 1))
  (sb-thread:make-thread (lambda () (print *x*))))
@end example

prints @code{0} and not @code{1}.

Note, however, that there is a hard limit on the number of distinct
symbols that can be bound dynamically in threaded builds (see
@code{--tls-limit} in @ref{runtime options}). Exceeding this limit triggers
the low-level error @code{Thread local storage exhausted.}

@node atomic operations
@section Atomic Operations

Following atomic operations are particularly useful for implementing
lockless algorithms.

@anchor{Macro sb-ext atomic-decf}
@ffindex @sortas{atomic-decf sb-ext} atomic-decf [sb-ext]
@deffn{Macro} sb-ext:atomic-decf place &optional diff
Atomically decrements @code{place} by @code{diff}, and returns the value of @code{place} before
the decrement.

@code{place} must access one of the following:

@itemize
@item a @code{defstruct} slot with declared type @code{(unsigned-byte 64)} or @code{aref}
  of a @code{(simple-array (unsigned-byte 64) (*))} (the type
  @code{sb-ext:word} can be used for these purposes)

@item @code{car} or @code{cdr} (respectively @code{first} or @code{rest}) of a @code{cons},

@item a variable defined using @code{defglobal} with a proclaimed type of @code{fixnum}.
@end itemize

Macroexpansion is performed on @code{place} before expanding @code{atomic-decf}.

Decrementing is done using modular arithmetic,
which is well-defined over two different domains:

@itemize
@item For structures and arrays, the operation accepts and produces
   an (@code{unsigned-byte} 64), and @code{diff} must be of type @code{(signed-byte
   64)}. @code{atomic-decf} of @code{#x0} by one results in @code{#xFFFFFFFFFFFFFFFF} being stored in
   @code{place}.

@item For other places, the domain is @code{fixnum}, and @code{diff} must be a @code{fixnum}.
   @code{atomic-decf} of @code{#x-4000000000000000} by one results in @code{#x3FFFFFFFFFFFFFFF} being stored in
   @code{place}.
@end itemize

@code{diff} defaults to 1.

EXPERIMENTAL: Interface subject to change.
@end deffn
@anchor{Macro sb-ext atomic-incf}
@ffindex @sortas{atomic-incf sb-ext} atomic-incf [sb-ext]
@deffn{Macro} sb-ext:atomic-incf place &optional diff
Atomically increments @code{place} by @code{diff}, and returns the value of @code{place} before
the increment.

@code{place} must access one of the following:

@itemize
@item a @code{defstruct} slot with declared type (@code{unsigned-byte} 64)
  or @code{aref} of a (@code{simple-array} (@code{unsigned-byte} 64) (*))
  The type @code{sb-ext:word} can be used for these purposes.

@item @code{car} or @code{cdr} (respectively @code{first} or @code{rest}) of a @code{cons}.

@item a variable defined using @code{defglobal} with a proclaimed type of @code{fixnum}.
  Macroexpansion is performed on @code{place} before expanding @code{atomic-incf}.
@end itemize

Incrementing is done using modular arithmetic, which is well-defined
over two different domains:

@itemize
@item For structures and arrays, the operation accepts and produces
   an (@code{unsigned-byte} 64), and @code{diff} must be of type (@code{signed-byte} 64).
   @code{atomic-incf} of @code{#xFFFFFFFFFFFFFFFF} by one results in #x0 being stored in @code{place}.

@item For other places, the domain is @code{fixnum}, and @code{diff} must be a @code{fixnum}.
   @code{atomic-incf} of @code{#x3FFFFFFFFFFFFFFF} by one results in @code{#x-4000000000000000}
   being stored in @code{place}.
@end itemize

@code{diff} defaults to 1.

EXPERIMENTAL: Interface subject to change.
@end deffn
@anchor{Macro sb-ext atomic-pop}
@ffindex @sortas{atomic-pop sb-ext} atomic-pop [sb-ext]
@deffn{Macro} sb-ext:atomic-pop place
Like @code{pop}, but atomic. @code{place} may be read multiple times before
the operation completes -- the write does not occur until such time
that no other thread modified @code{place} between the read and the write.

Works on all @code{cas}able places.
@end deffn
@anchor{Macro sb-ext atomic-push}
@ffindex @sortas{atomic-push sb-ext} atomic-push [sb-ext]
@deffn{Macro} sb-ext:atomic-push obj place
Like @code{push}, but atomic. @code{place} may be read multiple times before
the operation completes -- the write does not occur until such time
that no other thread modified @code{place} between the read and the write.

Works on all @code{cas}able places.
@end deffn
@anchor{Macro sb-ext atomic-update}
@ffindex @sortas{atomic-update sb-ext} atomic-update [sb-ext]
@deffn{Macro} sb-ext:atomic-update place update-fn &rest arguments
Updates @code{place} atomically to the value returned by calling function
designated by @code{update-fn} with @code{arguments} and the previous value of @code{place}.

@code{place} may be read and @code{update-fn} evaluated and called multiple times before the
update succeeds: atomicity in this context means that the value of @code{place} did
not change between the time it was read, and the time it was replaced with the
computed value.

@code{place} can be any place supported by @code{sb-ext:compare-and-swap}.

Examples:

@example
;;; Conses T to the head of FOO-LIST.
(defstruct foo list)
(defvar *foo* (make-foo))
(atomic-update (foo-list *foo*) #'cons t)

(let ((x (cons :count 0)))
   (mapc #'sb-thread:join-thread
         (loop repeat 1000
               collect (sb-thread:make-thread
                        (lambda ()
                          (loop repeat 1000
                                do (atomic-update (cdr x) #'1+)
                                   (sleep 0.00001))))))
   ;; Guaranteed to be (:COUNT . 1000000) -- if you replace
   ;; atomic update with (INCF (CDR X)) above, the result becomes
   ;; unpredictable.
   x)
@end example
@end deffn
@anchor{Macro sb-ext compare-and-swap}
@ffindex @sortas{compare-and-swap sb-ext} compare-and-swap [sb-ext]
@deffn{Macro} sb-ext:compare-and-swap place old new
Atomically stores @code{new} in @code{place} if @code{old} matches the current value of @code{place}.
Two values are considered to match if they are @code{eq}. Returns the previous value
of @code{place}: if the returned value is @code{eq} to @code{old}, the swap was carried out.

@code{place} must be an @code{cas}-able place. Built-in @code{cas}-able places are accessor forms
whose @code{car} is one of the following:

 @code{car}, @code{cdr}, @code{first}, @code{rest}, @code{svref}, @code{symbol-plist}, @code{symbol-value}, @code{slot-value}
 @code{sb-mop:standard-instance-access}, @code{sb-mop:funcallable-standard-instance-access},

or the name of a @code{defstruct} created accessor for a slot whose storage type
is not raw. (Refer to the the "Efficiency" chapter of the manual
for the list of raw slot types.  Future extensions to this macro may allow
it to work on some raw slot types.)

In case of @code{slot-value}, if the slot is unbound, @code{slot-unbound} is called unless
@code{old} is @code{eq} to @code{sb-pcl:+slot-unbound+} in which case @code{sb-pcl:+slot-unbound+} is
returned and @code{new} is assigned to the slot. Additionally, the results are
unspecified if there is an applicable method on either
@code{sb-mop:slot-value-using-class}, (@code{setf} @code{sb-mop:slot-value-using-class}), or
@code{sb-mop:slot-boundp-using-class}.

Additionally, the @code{place} can be a anything for which a @code{cas}-function has
been defined.
@end deffn
Our @code{sb-ext:compare-and-swap} is user-extensible by defining functions
named @code{(cas <place>)}, allowing users to add CAS support to new
places.

@anchor{Macro sb-ext cas}
@ffindex @sortas{cas sb-ext} cas [sb-ext]
@deffn{Macro} sb-ext:cas place old new
Synonym for @code{compare-and-swap}.

Additionally @code{defun}, @code{defgeneric}, @code{defmethod}, @code{flet}, and @code{labels} can be also used to
define @code{cas}-functions analogously to @code{setf}-functions:

@example
(defvar *foo* nil)

(defun (cas foo) (old new)
  (cas (symbol-value '*foo*) old new))
@end example

First argument of a @code{cas} function is the expected old value, and the second
argument of is the new value. Note that the system provides no automatic
atomicity for @code{cas} functions, nor can it verify that they are atomic: it is up
to the implementor of a @code{cas} function to ensure its atomicity.

EXPERIMENTAL: Interface subject to change.
@end deffn
@anchor{Function sb-ext get-cas-expansion}
@ffindex @sortas{get-cas-expansion sb-ext} get-cas-expansion [sb-ext]
@deffn{Function} sb-ext:get-cas-expansion place &optional environment
Analogous to @code{get-setf-expansion}. Returns the following six values:

@itemize
@item list of temporary variables

@item list of value-forms whose results those variable must be bound

@item temporary variable for the old value of @code{place}

@item temporary variable for the new value of @code{place}

@item form using the aforementioned temporaries which performs the
  compare-and-swap operation on @code{place}

@item form using the aforementioned temporaries with which to perform a volatile
  read of @code{place}
@end itemize

Example:

@example
(get-cas-expansion '(car x))
; => (#:CONS871), (X), #:OLD872, #:NEW873,
;    (SB-KERNEL:%COMPARE-AND-SWAP-CAR #:CONS871 #:OLD872 :NEW873).
;    (CAR #:CONS871)

(defmacro my-atomic-incf (place &optional (delta 1) &environment env)
  (multiple-value-bind (vars vals old new cas-form read-form)
      (get-cas-expansion place env)
   (let ((delta-value (gensym "DELTA")))
     `(let* (,@@(mapcar 'list vars vals)
             (,old ,read-form)
             (,delta-value ,delta)
             (,new (+ ,old ,delta-value)))
        (loop until (eq ,old (setf ,old ,cas-form))
              do (setf ,new (+ ,old ,delta-value)))
        ,new))))
@end example

EXPERIMENTAL: Interface subject to change.
@end deffn
@node mutex support
@section Mutex Support

Mutexes are used for controlling access to a shared resource. One
thread is allowed to hold the mutex, others which attempt to take it
will be made to wait until it's free. Threads are woken in the order
that they go to sleep.

@example
(defpackage :demo (:use "CL" "SB-THREAD" "SB-EXT"))

(in-package :demo)

(defvar *a-mutex* (make-mutex :name "my lock"))

(defun thread-fn ()
  (format t "Thread ~A running ~%" *current-thread*)
  (with-mutex (*a-mutex*)
    (format t "Thread ~A got the lock~%" *current-thread*)
    (sleep (random 5)))
  (format t "Thread ~A dropped lock, dying now~%" *current-thread*))

(make-thread #'thread-fn)
(make-thread #'thread-fn)
@end example

@anchor{Structure sb-thread mutex}
@ttindex @sortas{mutex sb-thread} mutex [sb-thread]
@deffn{Structure} sb-thread:mutex
Mutex type.
@end deffn
@anchor{Macro sb-thread with-mutex}
@ffindex @sortas{with-mutex sb-thread} with-mutex [sb-thread]
@deffn{Macro} sb-thread:with-mutex (mutex &key wait-p timeout value) &body body
Acquire @code{mutex} for the dynamic scope of @code{body}. If @code{wait-p} is true (the default),
and the @code{mutex} is not immediately available, sleep until it is available.

If @code{timeout} is given, it specifies a relative timeout, in seconds, on how long
the system should try to acquire the lock in the contended case.

If the mutex isn't acquired successfully due to either @code{wait-p} or
@code{timeout}, @code{body} is not executed, and @code{with-mutex} returns @code{nil}.

Otherwise body is executed with the mutex held by current thread, and
@code{with-mutex} returns the values of @code{body}.

Historically @code{with-mutex} also accepted a @code{value} argument, which when provided
was used as the new owner of the mutex instead of the current thread. This is
no longer supported: if @code{value} is provided, it must be either @code{nil} or the
current thread.
@end deffn
@anchor{Macro sb-thread with-recursive-lock}
@ffindex @sortas{with-recursive-lock sb-thread} with-recursive-lock [sb-thread]
@deffn{Macro} sb-thread:with-recursive-lock (mutex &key wait-p timeout) &body body
Acquire @code{mutex} for the dynamic scope of @code{body}.

If @code{wait-p} is true (the default), and the @code{mutex} is not immediately available or
held by the current thread, sleep until it is available.

If @code{timeout} is given, it specifies a relative timeout, in seconds, on how long
the system should try to acquire the lock in the contended case.

If the mutex isn't acquired successfully due to either @code{wait-p} or
@code{timeout}, @code{body} is not executed, and @code{with-recursive-lock} returns @code{nil}.

Otherwise body is executed with the mutex held by current thread, and
@code{with-recursive-lock} returns the values of @code{body}.

Unlike @code{with-mutex}, which signals an error on attempt to re-acquire an already
held mutex, @code{with-recursive-lock} allows recursive lock attempts to succeed.
@end deffn
@anchor{Function sb-thread make-mutex}
@ffindex @sortas{make-mutex sb-thread} make-mutex [sb-thread]
@deffn{Function} sb-thread:make-mutex &key name
Create a @code{mutex}.
@end deffn
@anchor{Function sb-thread mutex-name}
@ffindex @sortas{mutex-name sb-thread} mutex-name [sb-thread]
@deffn{Function} sb-thread:mutex-name instance
The name of the @code{mutex}. @code{setf}able.
@end deffn
@anchor{Function sb-thread mutex-owner}
@ffindex @sortas{mutex-owner sb-thread} mutex-owner [sb-thread]
@deffn{Function} sb-thread:mutex-owner mutex
Current owner of @code{mutex}, @code{nil} if the mutex is free. Naturally,
this is racy by design (another thread may acquire the mutex after
this function returns), it is intended for informative purposes. For
testing whether the current thread is holding a mutex see
@code{holding-mutex-p}.
@end deffn
@anchor{Function sb-thread mutex-value}
@ffindex @sortas{mutex-value sb-thread} mutex-value [sb-thread]
@deffn{Function} sb-thread:mutex-value mutex
Current owner of @code{mutex}, @code{nil} if the mutex is free. May return a
stale value, use @code{mutex-owner} instead.
@end deffn
@anchor{Function sb-thread grab-mutex}
@ffindex @sortas{grab-mutex sb-thread} grab-mutex [sb-thread]
@deffn{Function} sb-thread:grab-mutex mutex &key waitp timeout
Acquire @code{mutex} for the current thread. If @code{waitp} is true (the default) and
the mutex is not immediately available, sleep until it is available.

If @code{timeout} is given, it specifies a relative timeout, in seconds, on how long
@code{grab-mutex} should try to acquire the lock in the contended case.

If @code{grab-mutex} returns @code{t}, the lock acquisition was successful. In case of @code{waitp}
being @code{nil}, or an expired @code{timeout}, @code{grab-mutex} may also return @code{nil} which denotes
that @code{grab-mutex} did -not- acquire the lock.

Notes:

@itemize
@item @code{grab-mutex} is not interrupt safe. The correct way to call it is:

@example
(without-interrupts
  ...
  (allow-with-interrupts (grab-mutex ...))
  ...)
@end example

    @code{without-interrupts} is necessary to avoid an interrupt unwinding the call
    while the mutex is in an inconsistent state while @code{allow-with-interrupts}
    allows the call to be interrupted from sleep.

@item @code{(grab-mutex <mutex> :timeout 0.0)} differs from
    @code{(grab-mutex <mutex> :waitp nil)} in that the former may signal a
    @code{deadline-timeout} if the global deadline was due already on
    entering @code{grab-mutex}.

    The exact interplay of @code{grab-mutex} and deadlines are reserved to change in
    future versions.

@item It is recommended that you use @code{with-mutex} instead of calling @code{grab-mutex}
    directly.
@end itemize
@end deffn
@anchor{Function sb-thread release-mutex}
@ffindex @sortas{release-mutex sb-thread} release-mutex [sb-thread]
@deffn{Function} sb-thread:release-mutex mutex &key if-not-owner
Release @code{mutex} and wake up any other thread waiting for it.

@code{release-mutex} is not interrupt safe: interrupts should be disabled
around calls to it.

The @code{if-not-owner} keyword dictates behavior when the current thread does not own the
mutex. Do nothing and silently return if @code{:punt}, signal a @code{warning} or @code{error} if @code{:warn}
or @code{:error} respectively, or release the mutex anyway if @code{:force}.
@end deffn
@node semaphores
@section Semaphores

Semaphores are among other things useful for keeping track of a
countable resource, e.g. messages in a queue, and sleep when the
resource is exhausted.

@anchor{Structure sb-thread semaphore}
@ttindex @sortas{semaphore sb-thread} semaphore [sb-thread]
@deffn{Structure} sb-thread:semaphore
Semaphore type. The fact that a @code{semaphore} is a @code{structure-object}
should be considered an implementation detail, and may change in the
future.
@end deffn
@anchor{Function sb-thread make-semaphore}
@ffindex @sortas{make-semaphore sb-thread} make-semaphore [sb-thread]
@deffn{Function} sb-thread:make-semaphore &key name count
Create a semaphore with the supplied @code{count} and @code{name}.
@end deffn
@anchor{Function sb-thread signal-semaphore}
@ffindex @sortas{signal-semaphore sb-thread} signal-semaphore [sb-thread]
@deffn{Function} sb-thread:signal-semaphore semaphore &optional n
Increment the count of @code{semaphore} by @code{n}. If there are threads waiting
on this semaphore, then @code{n} of them is woken up.
@end deffn
@anchor{Function sb-thread wait-on-semaphore}
@ffindex @sortas{wait-on-semaphore sb-thread} wait-on-semaphore [sb-thread]
@deffn{Function} sb-thread:wait-on-semaphore semaphore &key n timeout notification
Decrement the count of @code{semaphore} by @code{n} if the count would not be negative.

Else blocks until the semaphore can be decremented. Returns the new count of
@code{semaphore} on success.

If @code{timeout} is given, it is the maximum number of seconds to wait. If the count
cannot be decremented in that time, returns @code{nil} without decrementing the
count.

If @code{notification} is given, it must be a @code{semaphore-notification} object whose
@code{semaphore-notification-status} is @code{nil}. If @code{wait-on-semaphore} succeeds and
decrements the count, the status is set to @code{t}.
@end deffn
@anchor{Function sb-thread try-semaphore}
@ffindex @sortas{try-semaphore sb-thread} try-semaphore [sb-thread]
@deffn{Function} sb-thread:try-semaphore semaphore &optional n notification
Try to decrement the count of @code{semaphore} by @code{n}. If the count were to
become negative, punt and return @code{nil}, otherwise return the new count of
@code{semaphore}.

If @code{notification} is given it must be a semaphore notification object
with @code{semaphore-notification-status} of @code{nil}. If the count is decremented,
the status is set to @code{t}.
@end deffn
@anchor{Function sb-thread semaphore-count}
@ffindex @sortas{semaphore-count sb-thread} semaphore-count [sb-thread]
@deffn{Function} sb-thread:semaphore-count semaphore
Returns the current count of @code{semaphore}.
@end deffn
@anchor{Function sb-thread semaphore-name}
@ffindex @sortas{semaphore-name sb-thread} semaphore-name [sb-thread]
@deffn{Function} sb-thread:semaphore-name semaphore
The name of the semaphore @code{instance}. @code{setf}able.
@end deffn
@anchor{Structure sb-thread semaphore-notification}
@ttindex @sortas{semaphore-notification sb-thread} semaphore-notification [sb-thread]
@deffn{Structure} sb-thread:semaphore-notification
Semaphore notification object. Can be passed to @code{wait-on-semaphore} and
@code{try-semaphore} as the @code{:notification} argument. Consequences are undefined if
multiple threads are using the same notification object in parallel.
@end deffn
@anchor{Function sb-thread make-semaphore-notification}
@ffindex @sortas{make-semaphore-notification sb-thread} make-semaphore-notification [sb-thread]
@deffn{Function} sb-thread:make-semaphore-notification
Constructor for @code{semaphore-notification} objects. @code{semaphore-notification-status}
is initially @code{nil}.
@end deffn
@anchor{Function sb-thread semaphore-notification-status}
@ffindex @sortas{semaphore-notification-status sb-thread} semaphore-notification-status [sb-thread]
@deffn{Function} sb-thread:semaphore-notification-status semaphore-notification
Returns @code{t} if a @code{wait-on-semaphore} or @code{try-semaphore} using
@code{semaphore-notification} has succeeded since the notification object was created
or cleared.
@end deffn
@anchor{Function sb-thread clear-semaphore-notification}
@ffindex @sortas{clear-semaphore-notification sb-thread} clear-semaphore-notification [sb-thread]
@deffn{Function} sb-thread:clear-semaphore-notification semaphore-notification
Resets the @code{semaphore-notification} object for use with another call to
@code{wait-on-semaphore} or @code{try-semaphore}.
@end deffn
@node waitqueue/condition variables
@section Waitqueue/condition variables

These are based on the POSIX condition variable design, hence the
annoyingly CL-conflicting name. For use when you want to check a
condition and sleep until it's true. For example: you have a shared
queue, a writer process checking @emph{queue is empty} and one or more
readers that need to know when @emph{queue is not empty}. It sounds
simple but is astonishingly easy to deadlock if another process runs
when you weren't expecting it to.

There are three components:

@itemize
@item the condition itself (not represented in code)

@item the condition variable (a.k.a. waitqueue) which proxies for it

@item a lock to hold while testing the condition
@end itemize

Important stuff to be aware of:

@itemize
@item when calling condition-wait, you must hold the mutex.
  condition-wait will drop the mutex while it waits, and obtain it
  again before returning for whatever reason;

@item likewise, you must be holding the mutex around calls to
  @code{sb-thread:condition-notify};

@item a process may return from @code{sb-thread:condition-wait} in several
  circumstances: it is not guaranteed that the underlying condition
  has become true. You must check that the resource is ready for
  whatever you want to do to it.

@example
(defvar *buffer-queue* (make-waitqueue))
(defvar *buffer-lock* (make-mutex :name "buffer lock"))

(defvar *buffer* (list nil))

(defun reader ()
  (with-mutex (*buffer-lock*)
    (loop
     (condition-wait *buffer-queue* *buffer-lock*)
     (loop
      (unless *buffer* (return))
      (let ((head (car *buffer*)))
        (setf *buffer* (cdr *buffer*))
        (format t "reader ~A woke, read ~A~%"
                *current-thread* head))))))

(defun writer ()
  (loop
   (sleep (random 5))
   (with-mutex (*buffer-lock*)
     (let ((el (intern
                (string (code-char
                         (+ (char-code #A) (random 26)))))))
       (setf *buffer* (cons el *buffer*)))
     (condition-notify *buffer-queue*))))

(make-thread #'writer)
(make-thread #'reader)
(make-thread #'reader)
@end example
@end itemize

@anchor{Structure sb-thread waitqueue}
@ttindex @sortas{waitqueue sb-thread} waitqueue [sb-thread]
@deffn{Structure} sb-thread:waitqueue
Waitqueue type.
@end deffn
@anchor{Function sb-thread make-waitqueue}
@ffindex @sortas{make-waitqueue sb-thread} make-waitqueue [sb-thread]
@deffn{Function} sb-thread:make-waitqueue &key name
Create a @code{waitqueue}.
@end deffn
@anchor{Function sb-thread waitqueue-name}
@ffindex @sortas{waitqueue-name sb-thread} waitqueue-name [sb-thread]
@deffn{Function} sb-thread:waitqueue-name instance
The name of the waitqueue. @code{setf}able.
@end deffn
@anchor{Function sb-thread condition-wait}
@ffindex @sortas{condition-wait sb-thread} condition-wait [sb-thread]
@deffn{Function} sb-thread:condition-wait queue mutex &key timeout
Atomically release @code{mutex} and start waiting on @code{queue} until another thread
wakes us up using either @code{condition-notify} or @code{condition-broadcast} on
@code{queue}, at which point we re-acquire @code{mutex} and return @code{t}.

Spurious wakeups are possible.

If @code{timeout} is given, it is the maximum number of seconds to wait,
including both waiting for the wakeup and the time to re-acquire
@code{mutex}. When neither a wakeup nor a re-acquisition occurs within the
given time, returns @code{nil} without re-acquiring @code{mutex}.

If @code{condition-wait} unwinds, it may do so with or without @code{mutex} being
held.

Important: Since @code{condition-wait} may return without @code{condition-notify} or
@code{condition-broadcast} having occurred, the correct way to write code
that uses @code{condition-wait} is to loop around the call, checking the
associated data:

@example
(defvar *data* nil)
(defvar *queue* (make-waitqueue))
(defvar *lock* (make-mutex))

;; Consumer
(defun pop-data (&optional timeout)
  (with-mutex (*lock*)
    (loop until *data*
          do (or (condition-wait *queue* *lock* :timeout timeout)
                 ;; Lock not held, must unwind without touching *data*.
                 (return-from pop-data nil)))
    (pop *data*)))

;; Producer
(defun push-data (data)
  (with-mutex (*lock*)
    (push data *data*)
    (condition-notify *queue*)))
@end example
@end deffn
@anchor{Function sb-thread condition-notify}
@ffindex @sortas{condition-notify sb-thread} condition-notify [sb-thread]
@deffn{Function} sb-thread:condition-notify queue &optional n
Notify @code{n} threads waiting on @code{queue}.

IMPORTANT: The same mutex that is used in the corresponding @code{condition-wait}
must be held by this thread during this call.
@end deffn
@anchor{Function sb-thread condition-broadcast}
@ffindex @sortas{condition-broadcast sb-thread} condition-broadcast [sb-thread]
@deffn{Function} sb-thread:condition-broadcast queue
Notify all threads waiting on @code{queue}.

IMPORTANT: The same mutex that is used in the corresponding @code{condition-wait}
must be held by this thread during this call.
@end deffn
@node barriers
@section Barriers

These are based on the Linux kernel barrier design, which is in turn
based on the Alpha CPU memory model. They are presently implemented for
x86, x86-64, PPC, ARM64, and RISC-V systems, and behave as compiler
barriers on all other CPUs.

In addition to explicit use of the @code{sb-thread:barrier} macro, the
following functions and macros also serve as @code{:memory} barriers:

@itemize
@item @code{sb-ext:atomic-decf}, @code{sb-ext:atomic-incf}, @code{sb-ext:atomic-push},
  and @code{sb-ext:atomic-pop}

@item @code{sb-ext:compare-and-swap}

@item @code{sb-thread:grab-mutex}, @code{sb-thread:release-mutex},
  @code{sb-thread:with-mutex} and @code{sb-thread:with-recursive-lock}

@item @code{sb-thread:signal-semaphore}, @code{sb-thread:try-semaphore} and
  @code{sb-thread:wait-on-semaphore}

@item @code{sb-thread:condition-wait}, @code{sb-thread:condition-notify} and
  @code{sb-thread:condition-broadcast}.
@end itemize

@anchor{Macro sb-thread barrier}
@ffindex @sortas{barrier sb-thread} barrier [sb-thread]
@deffn{Macro} sb-thread:barrier (kind) &body forms
Insert a barrier in the code stream, preventing some sort of
reordering.

@code{kind} should be one of:

@itemize
@item @code{:compiler}: Prevent the compiler from reordering memory access across
  the barrier.

@item @code{:memory}: Prevent the CPU from reordering any memory access across
  the barrier.

@item @code{:read}: Prevent the CPU from reordering any read access across the
  barrier.

@item @code{:write}: Prevent the cpu from reordering any write access across the
  barrier.

@item @code{:data-dependency}: Prevent the cpu from reordering dependent memory
  reads across the barrier (requiring reads before the barrier to
  complete before any reads after the barrier that depend on them).
  This is a weaker form of the @code{:read} barrier.
@end itemize

@code{forms} is an implicit @code{progn}, evaluated before the barrier. @code{barrier}
returns the values of the last form in @code{forms}.

The file @code{memory-barriers.txt} in the Linux kernel documentation is
highly recommended reading for anyone programming at this level.
@end deffn
@node sessions/debugging
@section Sessions/Debugging

If the user has multiple views onto the same Lisp image (for example,
using multiple terminals, or a windowing system, or network access)
they are typically set up as multiple @emph{sessions} such that each view
has its own collection of foreground, background, and stopped
threads. A thread which wishes to create a new session can use
@code{sb-thread:with-new-session} to remove itself from the current
session (which it shares with its parent and siblings) and create a
fresh one.

@anchor{Macro sb-thread with-new-session}
@ffindex @sortas{with-new-session sb-thread} with-new-session [sb-thread]
@deffn{Macro} sb-thread:with-new-session args &body forms
@end deffn
@anchor{Function sb-thread make-listener-thread}
@ffindex @sortas{make-listener-thread sb-thread} make-listener-thread [sb-thread]
@deffn{Function} sb-thread:make-listener-thread tty-name
@end deffn
Within a single session, threads arbitrate between themselves for
the user's attention. A thread may be in one of three notional
states: foreground, background, or stopped. When a background
process attempts to print a repl prompt or to enter the debugger, it
will stop and print a message saying that it has stopped. The user
at his leisure may switch to that thread to find out what it needs.
If a background thread enters the debugger, selecting any restart
will put it back into the background before it resumes. Arbitration
for the input stream is managed by calls to
@code{sb-thread:get-foreground} (which may block) and
@code{sb-thread:release-foreground}.

@anchor{Function sb-thread get-foreground}
@ffindex @sortas{get-foreground sb-thread} get-foreground [sb-thread]
@deffn{Function} sb-thread:get-foreground
@end deffn
@anchor{Function sb-thread release-foreground}
@ffindex @sortas{release-foreground sb-thread} release-foreground [sb-thread]
@deffn{Function} sb-thread:release-foreground &optional next
Background this thread.  If @code{next} is supplied, arrange for it to
have the foreground next.
@end deffn
@node foreign threads
@section Foreign threads

Direct calls to @code{pthread_create(3)} (instead of @code{sb-thread:make-thread})
create threads that SBCL is not aware of, these are called foreign
threads. Currently, it is not possible to run Lisp code in such
threads. This means that the Lisp side signal handlers cannot work.
The best solution is to start foreign threads with signals blocked,
but since third party libraries may create threads, it is not always
feasible to do so. As a workaround, upon receiving a signal in a
foreign thread, SBCL changes the thread's sigmask to block all
signals that it wants to handle and resends the signal to the
current process which should land in a thread that does not block
it, that is, a Lisp thread.

The resignalling trick cannot work for synchronously triggered signals
(@code{sigsegv} and co), take care not to trigger any. Resignalling for
synchronously triggered signals in foreign threads is subject to
@code{--lose-on-corruption}, see @ref{runtime options}.

@node implementation on linux x86oids
@section Implementation on Linux x86oids

Threading is implemented using pthreads and some Linux specific bits
like futexes.

On x86, the per-thread local bindings for special variables is
achieved using the @code{%fs} segment register to point to a per-thread
storage area. This may cause interesting results if you link to
foreign code that expects threading or creates new threads, and the
thread library in question uses %fs in an incompatible way. On
x86-64 the r12 register has a similar role.

Queues require the @code{futex(2)} system call to be available: this is
the reason for the NPTL requirement. We test at runtime that this
system call exists.

Garbage collection is done with the existing Conservative
Generational GC. Allocation is done in small (typically 8k) regions:
each thread has its own region so this involves no stopping.
However, when a region fills, a lock must be obtained while another
is allocated, and when a collection is required, all processes are
stopped. This is achieved by sending them signals, which may make
for interesting behaviour if they are interrupted in system calls.
The streams interface is believed to handle the required system call
restarting correctly, but this may be a consideration when making
other blocking calls e.g. from foreign library code.

Large amounts of the SBCL library have not been inspected for
thread-safety.  Some of the obviously unsafe areas have large locks
around them, so compilation and fasl loading, for example, cannot be
parallelized.  Work is ongoing in this area.

A new thread by default is created in the same POSIX process group and
session as the thread it was created by.  This has an impact on
keyboard interrupt handling: pressing your terminal's intr key
(typically @code{Control-C}) will interrupt all processes in the
foreground process group, including Lisp threads that SBCL considers
to be notionally @emph{background}. This is undesirable, so background
threads are set to ignore the @code{sigint} signal.

@code{sb-thread:make-listener-thread} in addition to creating a new Lisp
session makes a new POSIX session, so that pressing @code{Control-C} in
one window will not interrupt another listener - this has been found
to be embarrassing.

