     This manual, for SBCL version 2.5.8, is part of the SBCL software
     system.  See the ‘README’ file for more information.

     This manual is largely derived from the manual for the CMUCL
     system, which was produced at Carnegie Mellon University and later
     released into the public domain.  This manual is in the public
     domain and is provided with absolutely no warranty.  See the
     ‘COPYING’ and ‘CREDITS’ files for more information.

9.7 Foreign Function Calls
==========================

The foreign function call interface allows a Lisp program to call many
functions written in languages that use the C calling convention.

   Lisp sets up various signal handling routines and other environment
information when it first starts up, and expects these to be in place at
all times.  The C functions called by Lisp should not change the
environment, especially the signal handlers: the signal handlers
installed by Lisp typically have interesting flags set (e.g to request
machine context information, or for signal delivery on an alternate
stack) which the Lisp runtime relies on for correct operation.  Precise
details of how this works may change without notice between versions;
the source, or the brain of a friendly SBCL developer, is the only
documentation.  Users of a Lisp built with the ‘:sb-thread’ feature
should also read the section about threads, see Threading.

9.7.1 The ‘alien-funcall’ Primitive
-----------------------------------

 -- Function: alien-funcall ALIEN-FUNCTION &rest ARGUMENTS

     The ‘alien-funcall’ function is the foreign function call
     primitive: ALIEN-FUNCTION is called with the supplied ARGUMENTS and
     its C return value is returned as a Lisp value.  The ALIEN-FUNCTION
     is an arbitrary run-time expression; to refer to a constant
     function, use ‘extern-alien’ or a value defined by
     ‘define-alien-routine’.

     The type of ‘alien-function’ must be ‘(alien (function ...))’ or
     ‘(alien (* (function ...)))’.  The function type is used to
     determine how to call the function (as though it was declared with
     a prototype.)  The type need not be known at compile time, but only
     known-type calls are efficiently compiled.  Limitations:

        • Structure type return values are not implemented.

        • Passing of structures by value is not implemented.

   Here is an example which allocates a ‘(struct foo)’, calls a foreign
function to initialize it, then returns a Lisp vector of all the ‘(*
(struct foo))’ objects filled in by the foreign call:

     ;; Allocate a foo on the stack.
     (with-alien ((f (struct foo)))
       ;; Call some C function to fill in foo fields.
       (alien-funcall (extern-alien "mangle_foo" (function void (* foo)))
                      (addr f))
       ;; Find how many foos to use by getting the A field.
       (let* ((num (slot f 'a))
              (result (make-array num)))
         ;; Get a pointer to the array so that we don't have to keep extracting it:
         (with-alien ((a (* (array (* (struct foo)) 100)) (addr (slot f 'b))))
           ;; Loop over the first N elements and stash them in the result vector.
           (dotimes (i num)
             (setf (svref result i) (deref (deref a) i)))
           ;; Voila.
           result)))

9.7.2 The ‘define-alien-routine’ Macro
--------------------------------------

 -- Macro: define-alien-routine NAME RESULT-TYPE &rest ARG-SPECIFIERS

     The ‘define-alien-routine’ macro is a convenience for automatically
     generating Lisp interfaces to simple foreign functions.  The
     primary feature is the parameter style specification, which
     translates the C pass-by-reference idiom into additional return
     values.

     NAME is usually a string external symbol, but may also be a symbol
     Lisp name or a list of the foreign name and the Lisp name.  If only
     one name is specified, the other is automatically derived as for
     ‘extern-alien’.  RESULT-TYPE is the alien type of the return value.

     Each element of the ARG-SPECIFIERS list specifies an argument to
     the foreign function, and is of the form
          (aname atype &optional style)

     ANAME is the symbol name of the argument to the constructed
     function (for documentation).  ATYPE is the alien type of
     corresponding foreign argument.  The semantics of the actual call
     are the same as for ‘alien-funcall’.  STYLE specifies how this
     argument should be handled at call and return time, and should be
     one of the following:

        • ‘:in’ specifies that the argument is passed by value.  This is
          the default.  ‘:in’ arguments have no corresponding return
          value from the Lisp function.

        • ‘:copy’ is similar to ‘:in’, but the argument is copied to a
          pre-allocated object and a pointer to this object is passed to
          the foreign routine.

        • ‘:out’ specifies a pass-by-reference output value.  The type
          of the argument must be a pointer to a fixed-sized object
          (such as an integer or pointer).  ‘:out’ and ‘:in-out’ style
          cannot be used with pointers to arrays, records or functions.
          An object of the correct size is allocated on the stack, and
          its address is passed to the foreign function.  When the
          function returns, the contents of this location are returned
          as one of the values of the Lisp function (and the location is
          automatically deallocated).

        • ‘:in-out’ is a combination of ‘:copy’ and ‘:out’.  The
          argument is copied to a pre-allocated object and a pointer to
          this object is passed to the foreign routine.  On return, the
          contents of this location is returned as an additional value.

          Note: Any efficiency-critical foreign interface function
          should be inline expanded, which can be done by preceding the
          ‘define-alien-routine’ call with:

               (declaim (inline lisp-name))

          In addition to avoiding the Lisp call overhead, this allows
          pointers, word-integers and floats to be passed using
          non-descriptor representations, avoiding consing.)

9.7.3 ‘define-alien-routine’ Example
------------------------------------

Consider the C function ‘cfoo’ with the following calling convention:

     void
     cfoo (str, a, i)
         char *str;
         char *a; /* update */
         int *i; /* out */
     {
       /* body of cfoo(...) */
     }

   This can be described by the following call to
‘define-alien-routine’:

     (define-alien-routine "cfoo" void
       (str c-string)
       (a char :in-out)
       (i int :out))

   The Lisp function ‘cfoo’ will have two arguments (STR and A) and two
return values (A and I).

9.8 Calling Lisp From C
=======================

SBCL supports the calling of Lisp functions using the C calling
convention.  This is useful for both defining callbacks and for creating
an interface for calling into Lisp as a shared library directly from C.

   The ‘define-alien-callable’ macro wraps Lisp code and creates a C
foreign function which can be called with the C calling convention.

 -- Macro: define-alien-callable name result-type typed-lambda-list
          &body body
     (define-alien-callable ‘name’ ‘result-type’ {(‘arg-name’
     ‘arg-type’)}* {doc-string} {decls}* {FORM}*)

     Define an alien function which can be called by alien code.  The
     alien function returned by (alien-callable-function ‘name’) expects
     alien arguments of the specified ARG-TYPEs and returns an alien of
     type ‘result-type’.

     If (alien-callable-function ‘name’) already exists, its value is
     not changed (though it is arranged that an updated version of the
     Lisp callable function will be called, provided that the new type
     and the existing type are compatible).  This feature allows for
     incremental redefinition of callable functions.

   The ‘alien-callable-function’ function returns the foreign callable
value associated with any name defined by ‘define-alien-callable’, so
that we can, for example, pass the callable value to C as a callback.

 -- Function: alien-callable-function name
     Return the alien callable function associated with ‘name’.

   The ‘with-alien-callable’ macro wraps Lisp code and establishes local
C foreign functions which can be called with the C calling convention.
This macro is handy for passing callbacks which close over Lisp values
into C.

 -- Macro: with-alien-callable definitions &body body
     Establish some local alien functions.  Each ‘definition’ is of the
     form: ‘name’ ‘result-type’ {(‘arg-name’ ‘arg-type’)}* {doc-string}
     {decls}* {FORM}*

     The resulting alien callable value has dynamic extent.

   Note that the garbage collector moves objects, and won't be able to
fix up any references in C variables.  There are three mechanisms for
coping with this:

  1. The ‘sb-ext:purify’ moves all live Lisp data into static or
     read-only areas such that it will never be moved (or freed) again
     in the life of the Lisp session

  2. ‘sb-sys:with-pinned-objects’ is a macro which arranges for some set
     of objects to be pinned in memory for the dynamic extent of its
     body forms.  On ports which use the generational garbage collector
     (most, as of this writing) this affects exactly the specified
     objects.  On other ports it is implemented by turning off GC for
     the duration (so could be said to have a whole-world granularity).

  3. Disable GC, using the ‘without-gcing’ macro.

9.8.1 Lisp as a Shared Library
------------------------------

SBCL supports the use of Lisp as a shared library that can be used by C
programs using the ‘define-alien-callable’ interface.  See the
‘:callable-exports’ keyword to ‘save-lisp-and-die’ for how to save the
Lisp image in a way that allows a C program to initialize the Lisp
runtime and the exported symbols.  When SBCL is built as a library, it
exposes the symbol ‘initialize_lisp’ which can be used in conjunction
with a core initializing global symbols to foreign callables as function
pointers and with object code allocating those symbols to initialize the
runtime properly.  The arguments to ‘initialize_lisp’ are the same as
the arguments to the main ‘sbcl’ program.

   Note: There is currently no way to run exit hooks or otherwise undo
Lisp initialization gracefully from C.

9.9 Step-By-Step Example of the Foreign Function Interface
==========================================================

This section presents a complete example of an interface to a somewhat
complicated C function.

   Suppose you have the following C function which you want to be able
to call from Lisp in the file ‘test.c’

     struct c_struct
     {
       int x;
       char *s;
     };

     struct c_struct *c_function (i, s, r, a)
         int i;
         char *s;
         struct c_struct *r;
         int a[10];
     {
       int j;
       struct c_struct *r2;

       printf("i = %d\n", i);
       printf("s = %s\n", s);
       printf("r->x = %d\n", r->x);
       printf("r->s = %s\n", r->s);
       for (j = 0; j < 10; j++) printf("a[%d] = %d.\n", j, a[j]);
       r2 = (struct c_struct *) malloc (sizeof(struct c_struct));
       r2->x = i + 5;
       r2->s = "a C string";
       return(r2);
     };

   It is possible to call this C function from Lisp using the file
‘test.lisp’ containing

     (cl:defpackage "TEST-C-CALL" (:use "CL" "SB-ALIEN" "SB-C-CALL"))
     (cl:in-package "TEST-C-CALL")

     ;;; Define the record C-STRUCT in Lisp.
     (define-alien-type nil
         (struct c-struct
                 (x int)
                 (s c-string)))

     ;;; Define the Lisp function interface to the C routine.  It returns a
     ;;; pointer to a record of type C-STRUCT.  It accepts four parameters:
     ;;; I, an int; S, a pointer to a string; R, a pointer to a C-STRUCT
     ;;; record; and A, a pointer to the array of 10 ints.
     ;;;
     ;;; The INLINE declaration eliminates some efficiency notes about heap
     ;;; allocation of alien values.
     (declaim (inline c-function))
     (define-alien-routine c-function
         (* (struct c-struct))
       (i int)
       (s c-string)
       (r (* (struct c-struct)))
       (a (array int 10)))

     ;;; a function which sets up the parameters to the C function and
     ;;; actually calls it
     (defun call-cfun ()
       (with-alien ((ar (array int 10))
                    (c-struct (struct c-struct)))
         (dotimes (i 10)                     ; Fill array.
           (setf (deref ar i) i))
         (setf (slot c-struct 'x) 20)
         (setf (slot c-struct 's) "a Lisp string")

         (with-alien ((res (* (struct c-struct))
                           (c-function 5 "another Lisp string" (addr c-struct) ar)))
           (format t "~&amp;back from C function~%")
           (multiple-value-prog1
               (values (slot res 'x)
                       (slot res 's))

             ;; Deallocate result. (after we are done referring to it:
             ;; "Pillage, *then* burn.")
             (free-alien res)))))

   To execute the above example, it is necessary to compile the C
routine, e.g.: ‘cc -c test.c && ld -shared -o test.so test.o’ (In order
to enable incremental loading with some linkers, you may need to say ‘cc
-G 0 -c test.c’)

   Once the C code has been compiled, you can start up Lisp and load it
in: ‘sbcl’.  Lisp should start up with its normal prompt.

   Within Lisp, compile the Lisp file.  (This step can be done
separately.  You don't have to recompile every time.)  ‘(compile-file
"test.lisp")’

   Within Lisp, load the foreign object file to define the necessary
symbols: ‘(load-shared-object "test.so")’.

   Now you can load the compiled Lisp ("fasl") file into Lisp: ‘(load
"test.fasl")’ And once the Lisp file is loaded, you can call the Lisp
routine that sets up the parameters and calls the C function:
‘(test-c-call::call-cfun)’

   The C routine should print the following information to standard
output:

     i = 5
     s = another Lisp string
     r->x = 20
     r->s = a Lisp string
     a[0] = 0.
     a[1] = 1.
     a[2] = 2.
     a[3] = 3.
     a[4] = 4.
     a[5] = 5.
     a[6] = 6.
     a[7] = 7.
     a[8] = 8.
     a[9] = 9.

   After return from the C function, the Lisp wrapper function should
print the following output:

     back from C function

   And upon return from the Lisp wrapper function, before the next
prompt is printed, the Lisp read-eval-print loop should print the
following return values:

     10
     "a C string"

10 Pathnames
************

10.1 Lisp Pathnames
===================

There are many aspects of ANSI Common Lisp's pathname support which are
implementation-defined and so need documentation.

10.1.1 Home Directory Specifiers
--------------------------------

SBCL accepts the keyword ‘:home’ and a list of the form ‘(:home
"username")’ as a directory component immediately following ‘:absolute’.

   ‘:home’ is represented in namestrings by ‘~/’ and ‘(:home "username"’
by ‘~username/’ at the start of the namestring.  Tilde-characters
elsewhere in namestrings represent themselves.

   Home directory specifiers are resolved to home directory of the
current or specified user by ‘native-namestring’, which is used by the
implementation to translate pathnames before passing them on to
operating system specific routines.

   Using ‘(:home "user")’ form on Windows signals an error.

10.1.2 The SYS Logical Pathname Host
------------------------------------

The logical pathname host named by ‘"SYS"’ exists in SBCL. Its
‘logical-pathname-translations’ may be set by the site or the user
applicable to point to the locations of the system's sources; in
particular, the core system's source files match the logical pathname
‘"SYS:SRC;**;*.*.*"’, and the contributed modules' source files match
‘"SYS:CONTRIB;**;*.*.*"’.

 -- Function: set-sbcl-source-location pathname
     Initialize the ‘sys’ logical host based on ‘pathname’, which should
     be the top-level directory of the ‘sbcl’ sources.  This will
     replace any existing translations for "SYS:SRC;", "SYS:CONTRIB;",
     and "SYS:OUTPUT;".  Other "SYS:" translations are preserved.

10.2 Native Filenames
=====================

In some circumstances, what is wanted is a Lisp pathname object which
corresponds to a string produced by the Operating System.  In this case,
some of the default parsing rules are inappropriate: most filesystems do
not have a native understanding of wild pathnames; such functionality is
often provided by shells above the OS, often in mutually-incompatible
ways.

   To allow the user to deal with this, the following functions are
provided: ‘parse-native-namestring’ and ‘native-pathname’ return the
closest equivalent Lisp pathname to a given string (appropriate for the
Operating System), while ‘native-namestring’ converts a non-wild
pathname designator to the equivalent native namestring, if possible.
Some Lisp pathname concepts (such as the ‘:back’ directory component)
have no direct equivalents in most Operating Systems; the behaviour of
‘native-namestring’ is unspecified if an inappropriate pathname
designator is passed to it.  Additionally, note that conversion from
pathname to native filename and back to pathname should not be expected
to preserve equivalence under ‘equal’.

 -- Function: parse-native-namestring thing &optional host defaults &key
          start end junk-allowed as-directory
     Convert ‘thing’ into a pathname, using the native conventions
     appropriate for the pathname host ‘host’, or if not specified the
     host of ‘defaults’.  If ‘thing’ is a string, the parse is bounded
     by ‘start’ and ‘end’, and error behaviour is controlled by
     ‘junk-allowed’, as with ‘parse-namestring’.  For file systems whose
     native conventions allow directories to be indicated as files, if
     ‘as-directory’ is true, return a pathname denoting ‘thing’ as a
     directory.
 -- Function: native-pathname pathspec
     Convert ‘pathspec’ (a pathname designator) into a pathname,
     assuming the operating system native pathname conventions.
 -- Function: native-namestring pathname &key as-file
     Construct the full native (name)string form of ‘pathname’.  For
     file systems whose native conventions allow directories to be
     indicated as files, if ‘as-file’ is true and the name, type, and
     version components of ‘pathname’ are all ‘nil’ or ‘:unspecific’,
     construct a string that names the directory according to the file
     system's syntax for files.

   Because some file systems permit the names of directories to be
expressed in multiple ways, it is occasionally necessary to parse a
native file name "as a directory name" or to produce a native file name
that names a directory "as a file".  For these cases,
‘parse-native-namestring’ accepts the keyword argument ‘as-directory’ to
force a filename to parse as a directory, and ‘native-namestring’
accepts the keyword argument ‘as-file’ to force a pathname to unparse as
a file.  For example,

     ; On Unix, the directory "/tmp/" can be denoted by "/tmp/" or "/tmp".
     ; Under the default rules for native filenames, these parse and
     ; unparse differently.
     (defvar *p*)
     (setf *p* (parse-native-namestring "/tmp/")) ⇒ #P"/tmp/"
     (pathname-name *p*) ⇒ NIL
     (pathname-directory *p*) ⇒ (:ABSOLUTE "tmp")
     (native-namestring *p*) ⇒ "/tmp/"

     (setf *p* (parse-native-namestring "/tmp")) ⇒ #P"/tmp"
     (pathname-name *p*) ⇒ "tmp"
     (pathname-directory *p*) ⇒ (:ABSOLUTE)
     (native-namestring *p*) ⇒ "/tmp"

     ; A non-NIL AS-DIRECTORY argument to PARSE-NATIVE-NAMESTRING forces
     ; both the second string to parse the way the first does.
     (setf *p* (parse-native-namestring "/tmp"
                                        nil *default-pathname-defaults*
                                        :as-directory t)) ⇒ #P"/tmp/"
     (pathname-name *p*) ⇒ NIL
     (pathname-directory *p*) ⇒ (:ABSOLUTE "tmp")

     ; A non-NIL AS-FILE argument to NATIVE-NAMESTRING forces the pathname
     ; parsed from the first string to unparse as the second string.
     (setf *p* (parse-native-namestring "/tmp/")) ⇒ #P"/tmp/"
     (native-namestring *p* :as-file t) ⇒ "/tmp"

11 Streams
**********

Streams which read or write Lisp character data from or to the outside
world - files, sockets or other external entities - require the
specification of a conversion between the external, binary data and the
Lisp characters.  In ANSI Common Lisp, this is done by specifying the
‘:external-format’ argument when the stream is created.  The major
information required is an _encoding_, specified by a keyword naming
that encoding; however, it is also possible to specify refinements to
that encoding as additional options to the external format designator.

   In addition, SBCL supports various extensions of ANSI Common Lisp
streams:

*Bivalent Streams*
     A type of stream that can read and write both ‘character’ and
     ‘(unsigned-byte 8)’ values.

*Gray Streams*
     User-overloadable CLOS classes whose instances can be used as Lisp
     streams (e.g.  passed as the first argument to ‘format’).

*Simple Streams*
     The bundled contrib module “sb-simple-streams” implements a subset
     of the Franz Allegro simple-streams proposal.

11.1 Stream External Formats
============================

The function ‘stream-external-format’ returns the canonical name of the
external format (See External Formats) used by the stream for
character-based input and/or output.

   When constructing file streams, for example using ‘open’ or
‘with-open-file’, the external format to use is specified via the
‘:external-format’ argument which accepts an external format designator
(See External Format Designators).

11.2 Bivalent Streams
=====================

A “bivalent stream” can be used to read and write both ‘character’ and
‘(unsigned-byte 8)’ values.  A bivalent stream is created by calling
‘open’ with the argument ‘:element-type :default’.  On such a stream,
both binary and character data can be read and written with the usual
input and output functions.

     Streams are _not_ created bivalent by default for performance
     reasons.  Bivalent streams are incompatible with ‘fast-read-char’,
     an internal optimization in SBCL's stream machinery that
     bulk-converts octets to characters and implements a fast path
     through ‘read-char’.

11.3 Gray Streams
=================

The Gray Streams interface is a widely supported extension that provides
for definition of CLOS-extensible stream classes.  Gray stream classes
are implemented by adding methods to generic functions analogous to
Common Lisp's standard I/O functions.  Instances of Gray stream classes
may be used with any I/O operation where a non-Gray stream can, provided
that all required methods have been implemented suitably.

11.3.1 Gray Streams classes
---------------------------

The defined Gray Stream classes are these:

 -- Class: fundamental-stream
     Class precedence list: ‘fundamental-stream’, ‘standard-object’,
     ‘stream’, ‘t’

     Base class for all Gray streams.
 -- Class: fundamental-input-stream
     Class precedence list: ‘fundamental-input-stream’,
     ‘fundamental-stream’, ‘standard-object’, ‘stream’, ‘t’

     Superclass of all Gray input streams.

The function input-stream-p will return true of any generalized instance
of fundamental-input-stream.

 -- Class: fundamental-output-stream
     Class precedence list: ‘fundamental-output-stream’,
     ‘fundamental-stream’, ‘standard-object’, ‘stream’, ‘t’

     Superclass of all Gray output streams.

The function output-stream-p will return true of any generalized
instance of fundamental-output-stream.

 -- Class: fundamental-binary-stream
     Class precedence list: ‘fundamental-binary-stream’,
     ‘fundamental-stream’, ‘standard-object’, ‘stream’, ‘t’

     Superclass of all Gray streams whose element-type is a subtype of
     unsigned-byte or signed-byte.

Note that instantiable subclasses of fundamental-binary-stream should
provide (or inherit) an applicable method for the generic function
stream-element-type.

 -- Class: fundamental-character-stream
     Class precedence list: ‘fundamental-character-stream’,
     ‘fundamental-stream’, ‘standard-object’, ‘stream’, ‘t’

     Superclass of all Gray streams whose element-type is a subtype of
     character.
 -- Class: fundamental-binary-input-stream
     Class precedence list: ‘fundamental-binary-input-stream’,
     ‘fundamental-input-stream’, ‘fundamental-binary-stream’,
     ‘fundamental-stream’, ‘standard-object’, ‘stream’, ‘t’

     Superclass of all Gray input streams whose element-type is a
     subtype of unsigned-byte or signed-byte.
 -- Class: fundamental-binary-output-stream
     Class precedence list: ‘fundamental-binary-output-stream’,
     ‘fundamental-output-stream’, ‘fundamental-binary-stream’,
     ‘fundamental-stream’, ‘standard-object’, ‘stream’, ‘t’

     Superclass of all Gray output streams whose element-type is a
     subtype of unsigned-byte or signed-byte.
 -- Class: fundamental-character-input-stream
     Class precedence list: ‘fundamental-character-input-stream’,
     ‘fundamental-input-stream’, ‘fundamental-character-stream’,
     ‘fundamental-stream’, ‘standard-object’, ‘stream’, ‘t’

     Superclass of all Gray input streams whose element-type is a
     subtype of character.
 -- Class: fundamental-character-output-stream
     Class precedence list: ‘fundamental-character-output-stream’,
     ‘fundamental-output-stream’, ‘fundamental-character-stream’,
     ‘fundamental-stream’, ‘standard-object’, ‘stream’, ‘t’

     Superclass of all Gray output streams whose element-type is a
     subtype of character.

11.3.2 Methods common to all streams
------------------------------------

These generic functions can be specialized on any generalized instance
of fundamental-stream.

 -- Generic Function: stream-element-type stream
     Return a type specifier for the kind of object returned by the
     ‘stream’.  The class ‘fundamental-character-stream’ provides a
     default method which returns ‘character’.
 -- Generic Function: close stream &key abort
     Close the given ‘stream’.  No more I/O may be performed, but
     inquiries may still be made.  If ‘:abort’ is true, an attempt is
     made to clean up the side effects of having created the stream.
 -- Generic Function: stream-file-position stream &optional
          position-spec
     Used by ‘file-position’.  Returns or changes the current position
     within ‘stream’.

11.3.3 Input stream methods
---------------------------

These generic functions may be specialized on any generalized instance
of fundamental-input-stream.

 -- Generic Function: stream-clear-input stream
     This is like ‘cl:clear-input’, but for Gray streams, returning
     ‘nil’.  The default method does nothing.
 -- Generic Function: stream-read-sequence stream seq &optional start
          end
     This is like ‘cl:read-sequence’, but for Gray streams.

11.3.4 Character input stream methods
-------------------------------------

These generic functions are used to implement subclasses of
fundamental-input-stream:

 -- Generic Function: stream-peek-char stream
     This is used to implement ‘peek-char’; this corresponds to
     ‘peek-type’ of ‘nil’.  It returns either a character or ‘:eof’.
     The default method calls ‘stream-read-char’ and
     ‘stream-unread-char’.
 -- Generic Function: stream-read-char-no-hang stream
     This is used to implement ‘read-char-no-hang’.  It returns either a
     character, or ‘nil’ if no input is currently available, or ‘:eof’
     if end-of-file is reached.  The default method provided by
     ‘fundamental-character-input-stream’ simply calls
     ‘stream-read-char’; this is sufficient for file streams, but
     interactive streams should define their own method.
 -- Generic Function: stream-read-char stream
     Read one character from the stream.  Return either a character
     object, or the symbol ‘:eof’ if the stream is at end-of-file.
     Every subclass of ‘fundamental-character-input-stream’ must define
     a method for this function.
 -- Generic Function: stream-read-line stream
     This is used by ‘read-line’.  A string is returned as the first
     value.  The second value is true if the string was terminated by
     end-of-file instead of the end of a line.  The default method uses
     repeated calls to ‘stream-read-char’.
 -- Generic Function: stream-listen stream
     This is used by ‘listen’.  It returns true or false.  The default
     method uses ‘stream-read-char-no-hang’ and ‘stream-unread-char’.
     Most streams should define their own method since it will usually
     be trivial and will always be more efficient than the default
     method.
 -- Generic Function: stream-unread-char stream character
     Undo the last call to ‘stream-read-char’, as in ‘unread-char’.
     Return ‘nil’.  Every subclass of
     ‘fundamental-character-input-stream’ must define a method for this
     function.

11.3.5 Output stream methods
----------------------------

These generic functions are used to implement subclasses of
fundamental-output-stream:

 -- Generic Function: stream-clear-output stream
     This is like ‘cl:clear-output’, but for Gray streams: clear the
     given output ‘stream’.  The default method does nothing.
 -- Generic Function: stream-finish-output stream
     Attempts to ensure that all output sent to the Stream has reached
     its destination, and only then returns false.  Implements
     ‘finish-output’.  The default method does nothing.
 -- Generic Function: stream-force-output stream
     Attempts to force any buffered output to be sent.  Implements
     ‘force-output’.  The default method does nothing.
 -- Generic Function: stream-write-sequence stream seq &optional start
          end
     This is like ‘cl:write-sequence’, but for Gray streams.

11.3.6 Character output stream methods
--------------------------------------

These generic functions are used to implement subclasses of
fundamental-character-output-stream:

 -- Generic Function: stream-advance-to-column stream column
     Write enough blank space so that the next character will be written
     at the specified column.  Returns true if the operation is
     successful, or ‘nil’ if it is not supported for this stream.  This
     is intended for use by by ‘pprint’ and ‘format’ ~T. The default
     method uses ‘stream-line-column’ and repeated calls to
     ‘stream-write-char’ with a ‘#space’ character; it returns ‘nil’ if
     ‘stream-line-column’ returns ‘nil’.
 -- Generic Function: stream-fresh-line stream
     Outputs a new line to the Stream if it is not positioned at the
     beginning of a line.  Returns ‘t’ if it output a new line, nil
     otherwise.  Used by ‘fresh-line’.  The default method uses
     ‘stream-start-line-p’ and ‘stream-terpri’.
 -- Generic Function: stream-line-column stream
     Return the column number where the next character will be written,
     or ‘nil’ if that is not meaningful for this stream.  The first
     column on a line is numbered 0.  This function is used in the
     implementation of ‘pprint’ and the ‘format’ ~T directive.  For
     every character output stream class that is defined, a method must
     be defined for this function, although it is permissible for it to
     always return ‘nil’.
 -- Generic Function: stream-line-length stream
     Return the stream line length or ‘nil’.
 -- Generic Function: stream-start-line-p stream
     Is ‘stream’ known to be positioned at the beginning of a line?  It
     is permissible for an implementation to always return ‘nil’.  This
     is used in the implementation of ‘fresh-line’.  Note that while a
     value of 0 from ‘stream-line-column’ also indicates the beginning
     of a line, there are cases where ‘stream-start-line-p’ can be
     meaningfully implemented although ‘stream-line-column’ can't be.
     For example, for a window using variable-width characters, the
     column number isn't very meaningful, but the beginning of the line
     does have a clear meaning.  The default method for
     ‘stream-start-line-p’ on class
     ‘fundamental-character-output-stream’ uses ‘stream-line-column’, so
     if that is defined to return ‘nil’, then a method should be
     provided for either ‘stream-start-line-p’ or ‘stream-fresh-line’.
 -- Generic Function: stream-terpri stream
     Writes an end of line, as for ‘terpri’.  Returns ‘nil’.  The
     default method does (‘stream-write-char’ stream ‘#newline’).
 -- Generic Function: stream-write-char stream character
     Write ‘character’ to ‘stream’ and return ‘character’.  Every
     subclass of ‘fundamental-character-output-stream’ must have a
     method defined for this function.
 -- Generic Function: stream-write-string stream string &optional start
          end
     This is used by ‘write-string’.  It writes the string to the
     stream, optionally delimited by start and end, which default to 0
     and ‘nil’.  The string argument is returned.  The default method
     provided by ‘fundamental-character-output-stream’ uses repeated
     calls to ‘stream-write-char’.

11.3.7 Binary stream methods
----------------------------

The following generic functions are available for subclasses of
fundamental-binary-stream:

 -- Generic Function: stream-read-byte stream
     Used by ‘read-byte’; returns either an integer, or the symbol
     ‘:eof’ if the stream is at end-of-file.
 -- Generic Function: stream-write-byte stream integer
     Implements ‘write-byte’; writes the integer to the stream and
     returns the integer as the result.

11.3.8 Gray Streams examples
----------------------------

Below are two classes of stream that can be conveniently defined as
wrappers for Common Lisp streams.  These are meant to serve as examples
of minimal implementations of the protocols that must be followed when
defining Gray streams.  Realistic uses of the Gray Streams API would
implement the various methods that can do I/O in batches, such as
‘stream-read-line’, ‘stream-write-string’, ‘stream-read-sequence’, and
‘stream-write-sequence’.

11.3.8.1 Character counting input stream
........................................

It is occasionally handy for programs that process input files to count
the number of characters and lines seen so far, and the number of
characters seen on the current line, so that useful messages may be
reported in case of parsing errors, etc.  Here is a character input
stream class that keeps track of these counts.  Note that all character
input streams must implement ‘stream-read-char’ and
‘stream-unread-char’.

     (defclass wrapped-stream (fundamental-stream)
       ((stream :initarg :stream :reader stream-of)))
     (defmethod stream-element-type ((stream wrapped-stream))
       (stream-element-type (stream-of stream)))
     (defmethod close ((stream wrapped-stream) &key abort)
       (close (stream-of stream) :abort abort))
     (defclass wrapped-character-input-stream
         (wrapped-stream fundamental-character-input-stream)
       ())
     (defmethod stream-read-char ((stream wrapped-character-input-stream))
       (read-char (stream-of stream) nil :eof))
     (defmethod stream-unread-char ((stream wrapped-character-input-stream)
                                    char)
       (unread-char char (stream-of stream)))
     (defclass counting-character-input-stream
         (wrapped-character-input-stream)
       ((char-count :initform 1 :accessor char-count-of)
        (line-count :initform 1 :accessor line-count-of)
        (col-count :initform 1 :accessor col-count-of)
        (prev-col-count :initform 1 :accessor prev-col-count-of)))
     (defmethod stream-read-char ((stream counting-character-input-stream))
       (with-accessors ((inner-stream stream-of) (chars char-count-of)
                        (lines line-count-of) (cols col-count-of)
                        (prev prev-col-count-of)) stream
           (let ((char (call-next-method)))
             (cond ((eql char :eof)
                    :eof)
                   ((char= char #\Newline)
                    (incf lines)
                    (incf chars)
                    (setf prev cols)
                    (setf cols 1)
                    char)
                   (t
                    (incf chars)
                    (incf cols)
                    char)))))
     (defmethod stream-unread-char ((stream counting-character-input-stream)
                                    char)
       (with-accessors ((inner-stream stream-of) (chars char-count-of)
                        (lines line-count-of) (cols col-count-of)
                        (prev prev-col-count-of)) stream
           (cond ((char= char #\Newline)
                  (decf lines)
                  (decf chars)
                  (setf cols prev))
                 (t
                  (decf chars)
                  (decf cols)
                  char))
           (call-next-method)))

   The default methods for ‘stream-read-char-no-hang’,
‘stream-peek-char’, ‘stream-listen’, ‘stream-clear-input’,
‘stream-read-line’, and ‘stream-read-sequence’ should be sufficient
(though the last two will probably be slower than methods that forwarded
directly).

   Here's a sample use of this class:

     (with-input-from-string (input "1 2
      3 :foo  ")
       (let ((counted-stream (make-instance 'counting-character-input-stream
                              :stream input)))
         (loop for thing = (read counted-stream) while thing
            unless (numberp thing) do
              (error "Non-number ~S (line ~D, column ~D)" thing
                     (line-count-of counted-stream)
                     (- (col-count-of counted-stream)
                        (length (format nil "~S" thing))))
            end
            do (print thing))))
     1
     2
     3
     Non-number :FOO (line 2, column 5)
       [Condition of type SIMPLE-ERROR]

11.3.8.2 Output prefixing character stream
..........................................

One use for a wrapped output stream might be to prefix each line of text
with a timestamp, e.g., for a logging stream.  Here's a simple stream
that does this, though without any fancy line-wrapping.  Note that all
character output stream classes must implement ‘stream-write-char’ and
‘stream-line-column’.

     (defclass wrapped-stream (fundamental-stream)
       ((stream :initarg :stream :reader stream-of)))
     (defmethod stream-element-type ((stream wrapped-stream))
       (stream-element-type (stream-of stream)))
     (defmethod close ((stream wrapped-stream) &key abort)
       (close (stream-of stream) :abort abort))
     (defclass wrapped-character-output-stream
         (wrapped-stream fundamental-character-output-stream)
       ((col-index :initform 0 :accessor col-index-of)))
     (defmethod stream-line-column ((stream wrapped-character-output-stream))
       (col-index-of stream))
     (defmethod stream-write-char ((stream wrapped-character-output-stream)
                                   char)
       (with-accessors ((inner-stream stream-of) (cols col-index-of)) stream
         (write-char char inner-stream)
         (if (char= char #\Newline)
             (setf cols 0)
             (incf cols))))
     (defclass prefixed-character-output-stream
         (wrapped-character-output-stream)
       ((prefix :initarg :prefix :reader prefix-of)))
     (defgeneric write-prefix (prefix stream)
       (:method ((prefix string) stream) (write-string prefix stream))
       (:method ((prefix function) stream) (funcall prefix stream)))
     (defmethod stream-write-char ((stream prefixed-character-output-stream)
                                   char)
       (with-accessors ((inner-stream stream-of) (cols col-index-of)
                        (prefix prefix-of)) stream
         (when (zerop cols)
           (write-prefix prefix inner-stream))
         (call-next-method)))

   As with the example input stream, this implements only the minimal
protocol.  A production implementation should also provide methods for
at least ‘stream-write-line’, ‘stream-write-sequence’.

   And here's a sample use of this class:

     (flet ((format-timestamp (stream)
              (apply #'format stream "[~2@*~2,' D:~1@*~2,'0D:~0@*~2,'0D] "
                     (multiple-value-list (get-decoded-time)))))
       (let ((output (make-instance 'prefixed-character-output-stream
                                    :stream *standard-output*
                                    :prefix #'format-timestamp)))
         (loop for string in '("abc" "def" "ghi") do
              (write-line string output)
              (sleep 1))))
     [ 0:30:05] abc
     [ 0:30:06] def
     [ 0:30:07] ghi
     NIL

11.4 Simple Streams
===================

Simple streams are an extensible streams protocol that avoids some
problems with Gray streams.

   Documentation about simple streams is available at:

   <http://www.franz.com/support/documentation/6.2/doc/streams.htm>

   The implementation should be considered Alpha-quality; the basic
framework is there, but many classes are just stubs at the moment.

   See ‘SYS:CONTRIB;SB-SIMPLE-STREAMS;SIMPLE-STREAM-TEST.LISP’ for
things that should work.

   Known differences to the ACL behaviour:

   • ‘open’ not return a simple-stream by default.  This can be
     adjusted; see default-open-class in the file cl.lisp

   • ‘write-vector’ is unimplemented.

12 Package Locks
****************

None of the following sections apply to SBCL built without package
locking support.

     warning: The interface described here is experimental: incompatible
     changes in future SBCL releases are possible, even expected: the
     concept of "implementation packages" and the associated operators
     may be renamed; more operations (such as naming restarts or catch
     tags) may be added to the list of operations violating package
     locks.

12.1 Package Lock Concepts
==========================

12.1.1 Package Locking Overview
-------------------------------

Package locks protect against unintentional modifications of a package:
they provide similar protection to user packages as is mandated to
‘common-lisp’ package by the ANSI specification.  They are not, and
should not be used as, a security measure.

   Newly created packages are by default unlocked (see the ‘:lock’
option to ‘defpackage’).

   The package ‘common-lisp’ and SBCL internal implementation packages
are locked by default, including ‘sb-ext’.

   It may be beneficial to lock ‘common-lisp-user’ as well, to ensure
that various libraries don't pollute it without asking, but this is not
currently done by default.

12.1.2 Implementation Packages
------------------------------

Each package has a list of associated implementation packages.  A locked
package, and the symbols whose home package it is, can be modified
without violating package locks only when ‘*package*’ is bound to one of
the implementation packages of the locked package.

   Unless explicitly altered by ‘defpackage’,
‘sb-ext:add-implementation-package’, or
‘sb-ext:remove-implementation-package’ each package is its own (only)
implementation package.

12.1.3 Package Lock Violations
------------------------------

12.1.3.1 Lexical Bindings and Declarations
..........................................

Lexical bindings or declarations that violate package locks cause a
compile-time warning, and a runtime ‘program-error’ when the form that
violates package locks would be executed.

   A complete listing of operators affect by this is: ‘let’, ‘let*’,
‘flet’, ‘labels’, ‘macrolet’, and ‘symbol-macrolet’, ‘declare’.

   Package locks affecting both lexical bindings and declarations can be
disabled locally with ‘sb-ext:disable-package-locks’ declaration, and
re-enabled with ‘sb-ext:enable-package-locks’ declaration.

   Example:

     (in-package :locked)

     (defun foo () ...)

     (defmacro with-foo (&body body)
       `(locally (declare (disable-package-locks locked:foo))
          (flet ((foo () ...))
            (declare (enable-package-locks locked:foo)) ; re-enable for body
            ,@body)))

12.1.3.2 Other Operations
.........................

If an non-lexical operation violates a package lock, a continuable error
that is of a subtype of ‘sb-ext:package-lock-violation’ (subtype of
‘package-error’) is signalled when the operation is attempted.

   Additional restarts may be established for continuable package lock
violations for interactive use.

   The actual type of the error depends on circumstances that caused the
violation: operations on packages signal errors of type
‘sb-ext:package-locked-error’, and operations on symbols signal errors
of type ‘sb-ext:symbol-package-locked-error’.

12.1.4 Package Locks in Compiled Code
-------------------------------------

12.1.4.1 Interned Symbols
.........................

If file-compiled code contains interned symbols, then loading that code
into an image without the said symbols will not cause a package lock
violation, even if the packages in question are locked.

12.1.4.2 Other Limitations on Compiled Code
...........................................

With the exception of interned symbols, behaviour is unspecified if
package locks affecting compiled code are not the same during loading of
the code or execution.

   Specifically, code compiled with packages unlocked may or may not
fail to signal package-lock-violations even if the packages are locked
at runtime, and code compiled with packages locked may or may not signal
spurious package-lock-violations at runtime even if the packages are
unlocked.

   In practice all this means that package-locks have a negligible
performance penalty in compiled code as long as they are not violated.

12.1.5 Operations Violating Package Locks
-----------------------------------------

12.1.5.1 Operations on Packages
...............................

The following actions cause a package lock violation if the package
operated on is locked, and ‘*package*’ is not an implementation package
of that package, and the action would cause a change in the state of the
package (so e.g.  exporting already external symbols is never a
violation).  Package lock violations caused by these operations signal
errors of type ‘sb-ext:package-locked-error’.

  1. Shadowing a symbol in a package.

  2. Importing a symbol to a package.

  3. Uninterning a symbol from a package.

  4. Exporting a symbol from a package.

  5. Unexporting a symbol from a package.

  6. Changing the packages used by a package.

  7. Renaming a package.

  8. Deleting a package.

  9. Adding a new package local nickname to a package.

  10. Removing an existing package local nickname to a package.

12.1.5.2 Operations on Symbols
..............................

Following actions cause a package lock violation if the home package of
the symbol operated on is locked, and ‘*package*’ is not an
implementation package of that package.  Package lock violations caused
by these action signal errors of type
‘sb-ext:symbol-package-locked-error’.

   These actions cause only one package lock violation per lexically
apparent violated package.

   Example:

     ;;; Packages FOO and BAR are locked.
     ;;;
     ;;; Two lexically apparent violated packages: exactly two
     ;;; package-locked-errors will be signalled.

     (defclass foo:point ()
       ((x :accessor bar:x)
        (y :accessor bar:y)))

  1. Binding or altering its value lexically or dynamically, or
     establishing it as a symbol-macro.

     Exceptions:

        − If the symbol is not defined as a constant, global
          symbol-macro or a global dynamic variable, it may be lexically
          bound or established as a local symbol macro.

        − If the symbol is defined as a global dynamic variable, it may
          be assigned or bound.

  2. Defining, undefining, or binding it, or its setf name as a
     function.

     Exceptions:

        − If the symbol is not defined as a function, macro, or special
          operator it and its setf name may be lexically bound as a
          function.

  3. Defining, undefining, or binding it as a macro or compiler macro.

     Exceptions:

        − If the symbol is not defined as a function, macro, or special
          operator it may be lexically bound as a macro.

  4. Defining it as a type specifier or structure.

  5. Defining it as a declaration with a declaration proclamation.

  6. Declaring or proclaiming it special.

  7. Declaring or proclaiming its type or ftype.

     Exceptions:

        − If the symbol may be lexically bound, the type of that binding
          may be declared.

        − If the symbol may be lexically bound as a function, the ftype
          of that binding may be declared.

  8. Defining a setf expander for it.

  9. Defining it as a method combination type.

  10. Using it as the class-name argument to setf of find-class.

  11. Defining it as a hash table test using
     ‘sb-ext:define-hash-table-test’.

12.2 Package Lock Dictionary
============================

 -- Declaration: disable-package-locks

     Syntax: ‘(sb-ext:disable-package-locks symbol*)’

     Disables package locks affecting the named symbols during
     compilation in the lexical scope of the declaration.  Disabling
     locks on symbols whose home package is unlocked, or disabling an
     already disabled lock, has no effect.

 -- Declaration: enable-package-locks

     Syntax: ‘(sb-ext:enable-package-locks symbol*)’

     Re-enables package locks affecting the named symbols during
     compilation in the lexical scope of the declaration.  Enabling
     locks that were not first disabled with
     ‘sb-ext:disable-package-locks’ declaration, or enabling locks that
     are already enabled has no effect.

 -- Condition: package-lock-violation
     Class precedence list: ‘package-lock-violation’, ‘package-error’,
     ‘error’, ‘serious-condition’, ‘condition’, ‘t’

     Subtype of ‘cl:package-error’.  A subtype of this error is
     signalled when a package-lock is violated.
 -- Condition: package-locked-error
     Class precedence list: ‘package-locked-error’,
     ‘package-lock-violation’, ‘package-error’, ‘error’,
     ‘serious-condition’, ‘condition’, ‘t’

     Subtype of ‘sb-ext:package-lock-violation’.  An error of this type
     is signalled when an operation on a package violates a package
     lock.
 -- Condition: symbol-package-locked-error
     Class precedence list: ‘symbol-package-locked-error’,
     ‘package-lock-violation’, ‘package-error’, ‘error’,
     ‘serious-condition’, ‘condition’, ‘t’

     Subtype of ‘sb-ext:package-lock-violation’.  An error of this type
     is signalled when an operation on a symbol violates a package lock.
     The symbol that caused the violation is accessed by the function
     ‘sb-ext:package-locked-error-symbol’.

 -- Function: package-locked-error-symbol symbol-package-locked-error

     Returns the symbol that caused the ‘symbol-package-locked-error’
     condition.

 -- Function: package-locked-p package
     Returns ‘t’ when ‘package’ is locked, ‘nil’ otherwise.  Signals an
     error if ‘package’ doesn't designate a valid package.
 -- Function: lock-package package
     Locks ‘package’ and returns ‘t’.  Has no effect if ‘package’ was
     already locked.  Signals an error if ‘package’ is not a valid
     package designator
 -- Function: unlock-package package
     Unlocks ‘package’ and returns ‘t’.  Has no effect if ‘package’ was
     already unlocked.  Signals an error if ‘package’ is not a valid
     package designator.
 -- Function: package-implemented-by-list package
     Returns a list containing the implementation packages of ‘package’.
     Signals an error if ‘package’ is not a valid package designator.
 -- Function: package-implements-list package
     Returns the packages that ‘package’ is an implementation package
     of.  Signals an error if ‘package’ is not a valid package
     designator.
 -- Function: add-implementation-package packages-to-add &optional
          package
     Adds ‘packages-to-add’ as implementation packages of ‘package’.
     Signals an error if ‘package’ or any of the ‘packages-to-add’ is
     not a valid package designator.
 -- Function: remove-implementation-package packages-to-remove &optional
          package
     Removes ‘packages-to-remove’ from the implementation packages of
     ‘package’.  Signals an error if ‘package’ or any of the
     ‘packages-to-remove’ is not a valid package designator.
 -- Macro: without-package-locks &body body
     Ignores all runtime package lock violations during the execution of
     body.  Body can begin with declarations.
 -- Macro: with-unlocked-packages (&rest packages) &body forms
     Unlocks ‘packages’ for the dynamic scope of the body.  Signals an
     error if any of ‘packages’ is not a valid package designator.

 -- Macro: defpackage name [[option]]* ⇒ package

     Options are extended to include the following:

        • ‘:lock’ BOOLEAN

          If the argument to ‘:lock’ is ‘t’, the package is initially
          locked.  If ‘:lock’ is not provided it defaults to ‘nil’.

        • ‘:implement’ PACKAGE-DESIGNATOR*

          The package is added as an implementation package to the
          packages named.  If ‘:implement’ is not provided, it defaults
          to the package itself.

     Example:

          (defpackage "FOO" (:export "BAR") (:lock t) (:implement))
          (defpackage "FOO-INT" (:use "FOO") (:implement "FOO" "FOO-INT"))

          ;;; is equivalent to

          (defpackage "FOO") (:export "BAR"))
          (lock-package "FOO")
          (remove-implementation-package "FOO" "FOO")
          (defpackage "FOO-INT" (:use "BAR"))
          (add-implementation-package "FOO-INT" "FOO")

13 Threading
************

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 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
‘INSTALL’ for directions.

13.1 Threading basics
=====================

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

13.1.1 Thread Objects
---------------------

 -- Structure: thread
     Class precedence list: ‘thread’, ‘structure-object’, ‘t’

     Thread type.  Do not rely on threads being structs as it may change
     in future versions.
 -- Variable: *current-thread*
     Bound in each thread to the thread itself.
 -- Function: 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.
 -- Function: thread-alive-p thread
     Return ‘t’ if ‘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.
 -- Function: thread-name thread
     Name of the thread.  Can be assigned to using ‘setf’.  A thread
     name must be a simple-string (not necessarily unique) or ‘nil’.
 -- Function: main-thread-p &optional thread
     True if ‘thread’, defaulting to current thread, is the main thread
     of the process.
 -- Function: main-thread
     Returns the main thread of the process.

13.1.2 Making, Returning From, Joining, and Yielding Threads
------------------------------------------------------------

 -- Function: make-thread function &key name arguments
     Create a new thread of ‘name’ that runs ‘function’ with the
     argument list designator provided (defaults to no argument).
     Thread exits when the function returns.  The return values of
     ‘function’ are kept around and can be retrieved by ‘join-thread’.

     Invoking the initial ‘abort’ restart established by ‘make-thread’
     terminates the thread.

     See also: ‘return-from-thread’, ‘abort-thread’.
 -- Macro: return-from-thread values-form &key allow-exit
     Unwinds from and terminates the current thread, with values from
     ‘values-form’ as the results visible to ‘join-thread’.

     If current thread is the main thread of the process (see
     ‘main-thread-p’), signals an error unless ‘allow-exit’ is true, as
     terminating the main thread would terminate the entire process.  If
     ‘allow-exit’ is true, returning from the main thread is equivalent
     to calling ‘sb-ext:exit’ with ‘:code’ 0 and ‘:abort’ ‘nil’.

     See also: ‘abort-thread’ and ‘sb-ext:exit’.
 -- Function: abort-thread &key allow-exit
     Unwinds from and terminates the current thread abnormally, causing
     ‘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
     ‘main-thread-p’), signals an error unless ‘allow-exit’ is true, as
     terminating the main thread would terminate the entire process.  If
     ‘allow-exit’ is true, aborting the main thread is equivalent to
     calling ‘sb-ext:exit’ code 1 and ‘:abort’ ‘nil’.

     Invoking the initial ‘abort’ restart established by ‘make-thread’
     is equivalent to calling ‘abort-thread’ in other than main threads.
     However, whereas ‘abort’ restart may be rebound, ‘abort-thread’
     always unwinds the entire thread.  (Behaviour of the initial
     ‘abort’ restart for main thread depends on the ‘:toplevel’ argument
     to ‘sb-ext:save-lisp-and-die’.)

     See also: ‘return-from-thread’ and ‘sb-ext:exit’.
 -- Function: join-thread thread &key default timeout
     Suspend current thread until ‘thread’ exits.  Return the result
     values of the thread function.

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

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

     If ‘thread’ is the current thread, signal a ‘join-thread-error’
     with ‘join-thread-problem’ equal to ‘:self-join’.

     Trying to join the main thread causes ‘join-thread’ to block until
     ‘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 ‘thread’ from
     more than one other thread simultaneously.  Future changes to
     ‘join-thread’ may directly call the underlying thread library, and
     not all threading implementations consider such usage to be
     well-defined.

     ‘note:’ Return convention in case of a timeout is experimental and
     subject to change.
 -- Function: thread-yield
     Yield the processor to other threads.

13.1.3 Asynchronous Operations
------------------------------

 -- Function: interrupt-thread thread function
     Interrupt ‘thread’ and make it run ‘function’.

     The interrupt is asynchronous, and can occur anywhere with the
     exception of sections protected using ‘sb-sys:without-interrupts’.

     ‘function’ is called with interrupts disabled, under
     ‘sb-sys:allow-with-interrupts’.  Since functions such as
     ‘grab-mutex’ may try to enable interrupts internally, in most cases
     ‘function’ should either enter ‘sb-sys:with-interrupts’ to allow
     nested interrupts, or ‘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
     ‘interrupt-thread’ safely and sanely in a production environment.
     The general recommendation is to limit uses of ‘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:

        • If calling ‘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
          ‘unwind-protect’, it is just as if that had happened due to a
          regular ‘go’, ‘throw’, or ‘return-from:’ the interrupted
          cleanup form and those following it in the same
          ‘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.

        • In addition to asynch-unwind-safety you must consider the
          issue of reentrancy.  ‘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.)

     Taken together, these two restrict the "safe" things to do using
     ‘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:

            (interrupt-thread thread #'break)

     Short version: be careful out there.
 -- Function: terminate-thread thread
     Terminate the thread identified by ‘thread’, by interrupting it and
     causing it to call ‘sb-ext:abort-thread’ with ‘:allow-exit’ ‘t’.

     The unwind caused by ‘terminate-thread’ is asynchronous, meaning
     that eg.  thread executing

            (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))))

     might miss calling ‘release-foo’ despite ‘get-foo’ having returned
     true if the interrupt occurs inside the cleanup clause, eg.  during
     execution of ‘release-foo’.

     Thus, in order to write an asynch unwind safe ‘unwind-protect’ you
     need to use ‘without-interrupts:’

            (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)))))

     Since most libraries using ‘unwind-protect’ do not do this, you
     should never assume that unknown code can safely be terminated
     using ‘terminate-thread’.

13.1.4 Miscellaneous Operations
-------------------------------

 -- Function: symbol-value-in-thread symbol thread &optional errorp
     Return the local value of ‘symbol’ in ‘thread’, and a secondary
     value of ‘t’ on success.

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

     Can also be used with ‘setf’ to change the thread-local value of
     ‘symbol’.

     ‘symbol-value-in-thread’ is primarily intended as a debugging tool,
     and not as a mechanism for inter-thread communication.

13.1.5 Error Conditions
-----------------------

 -- Condition: thread-error
     Class precedence list: ‘thread-error’, ‘error’,
     ‘serious-condition’, ‘condition’, ‘t’

     Conditions of type ‘thread-error’ are signalled when thread
     operations fail.  The offending thread is initialized by the
     ‘:thread’ initialization argument and read by the function
     ‘thread-error-thread’.
 -- Function: thread-error-thread condition
     Return the offending thread that the ‘thread-error’ pertains to.

 -- Condition: interrupt-thread-error
     Class precedence list: ‘interrupt-thread-error’, ‘thread-error’,
     ‘error’, ‘serious-condition’, ‘condition’, ‘t’

     Signalled when interrupting a thread fails because the thread has
     already exited.  The offending thread can be accessed using
     ‘thread-error-thread’.
 -- Condition: join-thread-error
     Class precedence list: ‘join-thread-error’, ‘thread-error’,
     ‘error’, ‘serious-condition’, ‘condition’, ‘t’

     Signalled when joining a thread fails due to abnormal exit of the
     thread to be joined.  The offending thread can be accessed using
     ‘thread-error-thread’.

13.2 Special Variables
======================

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

   • global special values are visible across all threads;
   • bindings (e.g.  using LET) are local to the thread;
   • threads do not inherit dynamic bindings from the parent thread

   The last point means that

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

   prints ‘0’ and not ‘1’ as of 0.9.6.

13.3 Atomic Operations
======================

Following atomic operations are particularly useful for implementing
lockless algorithms.

 -- Macro: atomic-decf place &optional diff
     Atomically decrements ‘place’ by ‘diff’, and returns the value of
     ‘place’ before the decrement.

     ‘place’ must access one of the following:
        • a ‘defstruct’ slot with declared type (‘unsigned-byte’ 64) or
          ‘aref’ of a (‘simple-array’ (‘unsigned-byte’ 64) (‘*’)) The
          type ‘sb-ext:word’ can be used for these purposes.
        • ‘car’ or ‘cdr’ (respectively ‘first’ or ‘rest’) of a ‘cons’.
        • a variable defined using ‘defglobal’ with a proclaimed type of
          ‘fixnum’.
     Macroexpansion is performed on ‘place’ before expanding
     ‘atomic-decf’.

     Decrementing is done using modular arithmetic, which is
     well-defined over two different domains:
        • For structures and arrays, the operation accepts and produces
          an (‘unsigned-byte’ 64), and ‘diff’ must be of type
          (‘signed-byte’ 64).  ‘atomic-decf’ of #x0 by one results in
          #xFFFFFFFFFFFFFFFF being stored in ‘place’.
        • For other places, the domain is ‘fixnum’, and ‘diff’ must be a
          ‘fixnum’.  ‘atomic-decf’ of #x-4000000000000000 by one results
          in #x3FFFFFFFFFFFFFFF being stored in ‘place’.

     ‘diff’ defaults to 1.

     ‘experimental:’ Interface subject to change.
 -- Macro: atomic-incf place &optional diff
     Atomically increments ‘place’ by ‘diff’, and returns the value of
     ‘place’ before the increment.

     ‘place’ must access one of the following:
        • a ‘defstruct’ slot with declared type (‘unsigned-byte’ 64) or
          ‘aref’ of a (‘simple-array’ (‘unsigned-byte’ 64) (‘*’)) The
          type ‘sb-ext:word’ can be used for these purposes.
        • ‘car’ or ‘cdr’ (respectively ‘first’ or ‘rest’) of a ‘cons’.
        • a variable defined using ‘defglobal’ with a proclaimed type of
          ‘fixnum’.
     Macroexpansion is performed on ‘place’ before expanding
     ‘atomic-incf’.

     Incrementing is done using modular arithmetic, which is
     well-defined over two different domains:
        • For structures and arrays, the operation accepts and produces
          an (‘unsigned-byte’ 64), and ‘diff’ must be of type
          (‘signed-byte’ 64).  ‘atomic-incf’ of #xFFFFFFFFFFFFFFFF by
          one results in #x0 being stored in ‘place’.
        • For other places, the domain is ‘fixnum’, and ‘diff’ must be a
          ‘fixnum’.  ‘atomic-incf’ of #x3FFFFFFFFFFFFFFF by one results
          in #x-4000000000000000 being stored in ‘place’.

     ‘diff’ defaults to 1.

     ‘experimental:’ Interface subject to change.
 -- Macro: atomic-pop place
     Like ‘pop’, but atomic.  ‘place’ may be read multiple times before
     the operation completes ‘--’ the write does not occur until such
     time that no other thread modified ‘place’ between the read and the
     write.

     Works on all CASable places.
 -- Macro: atomic-push obj place
     Like ‘push’, but atomic.  ‘place’ may be read multiple times before
     the operation completes ‘--’ the write does not occur until such
     time that no other thread modified ‘place’ between the read and the
     write.

     Works on all CASable places.
 -- Macro: atomic-update place update-fn &rest arguments
     Updates ‘place’ atomically to the value returned by calling
     function designated by ‘update-fn’ with ‘arguments’ and the
     previous value of ‘place’.

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

     ‘place’ can be any place supported by ‘sb-ext:compare-and-swap’.

     Examples:

            ;;; 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)
 -- Macro: compare-and-swap place old new
     Atomically stores ‘new’ in ‘place’ if ‘old’ matches the current
     value of ‘place’.  Two values are considered to match if they are
     ‘eq’.  Returns the previous value of ‘place:’ if the returned value
     is ‘eq’ to ‘old’, the swap was carried out.

     ‘place’ must be an CAS-able place.  Built-in CAS-able places are
     accessor forms whose ‘car’ is one of the following:

     ‘car’, ‘cdr’, ‘first’, ‘rest’, ‘svref’, ‘symbol-plist’,
     ‘symbol-value’, ‘slot-value’ ‘sb-mop:standard-instance-access’,
     ‘sb-mop:funcallable-standard-instance-access’,

     or the name of a ‘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 ‘slot-value’, if the slot is unbound, ‘slot-unbound’ is
     called unless ‘old’ is ‘eq’ to ‘sb-pcl:+slot-unbound+’ in which
     case ‘sb-pcl:+slot-unbound+’ is returned and ‘new’ is assigned to
     the slot.  Additionally, the results are unspecified if there is an
     applicable method on either ‘sb-mop:slot-value-using-class’,
     (‘setf’ ‘sb-mop:slot-value-using-class’), or
     ‘sb-mop:slot-boundp-using-class’.

     Additionally, the ‘place’ can be a anything for which a
     CAS-function has been defined.  (See ‘sb-ext:cas’ for more
     information.)

CAS Protocol
------------

Our ‘compare-and-swap’ is user-extensible by defining functions named
(CAS place), allowing users to add CAS support to new places.

 -- Macro: cas place old new
     Synonym for ‘compare-and-swap’.

     Additionally ‘defun’, ‘defgeneric’, ‘defmethod’, ‘flet’, and
     ‘labels’ can be also used to define CAS-functions analogously to
     SETF-functions:

            (defvar *foo* nil)

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

     First argument of a ‘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 ‘cas’ functions, nor can it
     verify that they are atomic: it is up to the implementor of a ‘cas’
     function to ensure its atomicity.

     ‘experimental:’ Interface subject to change.

13.4 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.

     (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)

 -- Structure: mutex
     Class precedence list: ‘mutex’, ‘structure-object’, ‘t’

     Mutex type.

 -- Macro: with-mutex (mutex &key wait-p timeout value) &body body
     Acquire ‘mutex’ for the dynamic scope of ‘body’.  If ‘wait-p’ is
     true (the default), and the ‘mutex’ is not immediately available,
     sleep until it is available.

     If ‘timeout’ is given, it specifies a relative timeout, in seconds,
     on how long the system should try to acquire the lock in the
     contested case.

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

     Otherwise body is executed with the mutex held by current thread,
     and ‘with-mutex’ returns the values of ‘body’.

     Historically ‘with-mutex’ also accepted a ‘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 ‘value’ is
     provided, it must be either ‘nil’ or the current thread.
 -- Macro: with-recursive-lock (mutex &key wait-p timeout) &body body
     Acquire ‘mutex’ for the dynamic scope of ‘body’.

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

     If ‘timeout’ is given, it specifies a relative timeout, in seconds,
     on how long the system should try to acquire the lock in the
     contested case.

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

     Otherwise body is executed with the mutex held by current thread,
     and ‘with-recursive-lock’ returns the values of ‘body’.

     Unlike ‘with-mutex’, which signals an error on attempt to
     re-acquire an already held mutex, ‘with-recursive-lock’ allows
     recursive lock attempts to succeed.

 -- Function: make-mutex &key name
     Create a mutex.
 -- Function: mutex-name instance
     The name of the mutex.  Setfable.
 -- Function: mutex-owner mutex
     Current owner of the mutex, ‘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
     ‘holding-mutex-p’.
 -- Function: mutex-value mutex
     Current owner of the mutex, ‘nil’ if the mutex is free.  May return
     a stale value, use ‘mutex-owner’ instead.
 -- Function: grab-mutex mutex &key waitp timeout
     Acquire ‘mutex’ for the current thread.  If ‘waitp’ is true (the
     default) and the mutex is not immediately available, sleep until it
     is available.

     If ‘timeout’ is given, it specifies a relative timeout, in seconds,
     on how long ‘grab-mutex’ should try to acquire the lock in the
     contested case.

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

     Notes:

        • ‘grab-mutex’ is not interrupt safe.  The correct way to call
          it is:

          (‘without-interrupts’ ...  (‘allow-with-interrupts’
          (‘grab-mutex’ ...))  ...)

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

        • (‘grab-mutex’ <mutex> :timeout 0.0) differs from (‘grab-mutex’
          <mutex> :waitp nil) in that the former may signal a
          ‘deadline-timeout’ if the global deadline was due already on
          entering ‘grab-mutex’.

          The exact interplay of ‘grab-mutex’ and deadlines are reserved
          to change in future versions.

        • It is recommended that you use ‘with-mutex’ instead of calling
          ‘grab-mutex’ directly.
 -- Function: release-mutex mutex &key if-not-owner
     Release ‘mutex’ by setting it to ‘nil’.  Wake up threads waiting
     for this mutex.

     ‘release-mutex’ is not interrupt safe: interrupts should be
     disabled around calls to it.

     If the current thread is not the owner of the mutex then it
     silently returns without doing anything (if ‘if-not-owner’ is
     ‘:punt’), signals a ‘warning’ (if ‘if-not-owner’ is ‘:warn’), or
     releases the mutex anyway (if ‘if-not-owner’ is ‘:force’).

13.5 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.

 -- Structure: semaphore
     Class precedence list: ‘semaphore’, ‘structure-object’, ‘t’

     Semaphore type.  The fact that a ‘semaphore’ is a
     ‘structure-object’ should be considered an implementation detail,
     and may change in the future.
 -- Function: make-semaphore &key name count
     Create a semaphore with the supplied ‘count’ and ‘name’.
 -- Function: signal-semaphore semaphore &optional n
     Increment the count of ‘semaphore’ by ‘n’.  If there are threads
     waiting on this semaphore, then ‘n’ of them is woken up.
 -- Function: wait-on-semaphore semaphore &key n timeout notification
     Decrement the count of ‘semaphore’ by ‘n’ if the count would not be
     negative.

     Else blocks until the semaphore can be decremented.  Returns the
     new count of ‘semaphore’ on success.

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

     If ‘notification’ is given, it must be a ‘semaphore-notification’
     object whose ‘semaphore-notification-status’ is ‘nil’.  If
     ‘wait-on-semaphore’ succeeds and decrements the count, the status
     is set to ‘t’.
 -- Function: try-semaphore semaphore &optional n notification
     Try to decrement the count of ‘semaphore’ by ‘n’.  If the count
     were to become negative, punt and return ‘nil’, otherwise return
     the new count of ‘semaphore’.

     If ‘notification’ is given it must be a semaphore notification
     object with ‘semaphore-notification-status’ of ‘nil’.  If the count
     is decremented, the status is set to ‘t’.
 -- Function: semaphore-count instance
     Returns the current count of the semaphore ‘instance’.
 -- Function: semaphore-name semaphore
     The name of the semaphore ‘instance’.  Setfable.

 -- Structure: semaphore-notification
     Class precedence list: ‘semaphore-notification’,
     ‘structure-object’, ‘t’

     Semaphore notification object.  Can be passed to
     ‘wait-on-semaphore’ and ‘try-semaphore’ as the ‘:notification’
     argument.  Consequences are undefined if multiple threads are using
     the same notification object in parallel.
 -- Function: make-semaphore-notification
     Constructor for ‘semaphore-notification’ objects.
     ‘semaphore-notification-status’ is initially ‘nil’.
 -- Function: semaphore-notification-status semaphore-notification
     Returns ‘t’ if a ‘wait-on-semaphore’ or ‘try-semaphore’ using
     ‘semaphore-notification’ has succeeded since the notification
     object was created or cleared.
 -- Function: clear-semaphore-notification semaphore-notification
     Resets the ‘semaphore-notification’ object for use with another
     call to ‘wait-on-semaphore’ or ‘try-semaphore’.

13.6 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 "queue is empty" and one or more
readers that need to know when "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:

   • the condition itself (not represented in code)

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

   • a lock to hold while testing the condition

   Important stuff to be aware of:

   • 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;

   • likewise, you must be holding the mutex around calls to
     condition-notify;

   • a process may return from 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.

     (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)

 -- Structure: waitqueue
     Class precedence list: ‘waitqueue’, ‘structure-object’, ‘t’

     Waitqueue type.
 -- Function: make-waitqueue &key name
     Create a waitqueue.
 -- Function: waitqueue-name instance
     The name of the waitqueue.  Setfable.
 -- Function: condition-wait queue mutex &key timeout
     Atomically release ‘mutex’ and start waiting on ‘queue’ until
     another thread wakes us up using either ‘condition-notify’ or
     ‘condition-broadcast’ on ‘queue’, at which point we re-acquire
     ‘mutex’ and return ‘t’.

     Spurious wakeups are possible.

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

     If ‘condition-wait’ unwinds, it may do so with or without ‘mutex’
     being held.

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

            (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*)))
 -- Function: condition-notify queue &optional n
     Notify ‘n’ threads waiting on ‘queue’.

     ‘important:’ The same mutex that is used in the corresponding
     ‘condition-wait’ must be held by this thread during this call.
 -- Function: condition-broadcast queue
     Notify all threads waiting on ‘queue’.

     ‘important:’ The same mutex that is used in the corresponding
     ‘condition-wait’ must be held by this thread during this call.

13.7 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 ‘sb-thread:barrier’ macro, the
following functions and macros also serve as ‘:memory’ barriers:

   • ‘sb-ext:atomic-decf’, ‘sb-ext:atomic-incf’, ‘sb-ext:atomic-push’,
     and ‘sb-ext:atomic-pop’.
   • ‘sb-ext:compare-and-swap’.
   • ‘sb-thread:grab-mutex’, ‘sb-thread:release-mutex’,
     ‘sb-thread:with-mutex’ and ‘sb-thread:with-recursive-lock’.
   • ‘sb-thread:signal-semaphore’, ‘sb-thread:try-semaphore’ and
     ‘sb-thread:wait-on-semaphore’.
   • ‘sb-thread:condition-wait’, ‘sb-thread:condition-notify’ and
     ‘sb-thread:condition-broadcast’.

 -- Macro: barrier (kind) &body forms
     Insert a barrier in the code stream, preventing some sort of
     reordering.

     ‘kind’ should be one of:

     _‘:compiler’_
          Prevent the compiler from reordering memory access across the
          barrier.

     _‘:memory’_
          Prevent the cpu from reordering any memory access across the
          barrier.

     _‘:read’_
          Prevent the cpu from reordering any read access across the
          barrier.

     _‘:write’_
          Prevent the cpu from reordering any write access across the
          barrier.

     _‘: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 ‘:read’ barrier.

     ‘forms’ is an implicit ‘progn’, evaluated before the barrier.
     ‘barrier’ returns the values of the last form in ‘forms’.

     The file "memory-barriers.txt" in the Linux kernel documentation is
     highly recommended reading for anyone programming at this level.

13.8 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 “sessions” such that each view has its
own collection of foreground/background/stopped threads.  A thread which
wishes to create a new session can use ‘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.  # See also
‘sb-thread:make-listener-thread’.

   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 ‘sb-thread:get-foreground’ (which may block) and
‘sb-thread:release-foreground’.

13.9 Foreign threads
====================

Direct calls to ‘pthread_create’ (instead of ‘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 (SIGSEGV and co), take care not to trigger any.  Resignalling
for synchronously triggered signals in foreign threads is subject to
‘--lose-on-corruption’, see Runtime Options.

13.10 Implementation (Linux x86/x86-64)
=======================================

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 %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 ‘sys_futex()’ 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 ‘Control-C’) will interrupt all processes in the foreground
process group, including Lisp threads that SBCL considers to be
notionally 'background'.  This is undesirable, so background threads are
set to ignore the SIGINT signal.

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

14 Timers
*********

SBCL supports a system-wide event scheduler implemented on top of
‘setitimer’ that also works with threads but does not require a separate
scheduler thread.

   The following example schedules a timer that writes "Hello, world"
after two seconds.

     (schedule-timer (make-timer (lambda ()
                                   (write-line "Hello, world")
                                   (force-output)))
                     2)

   It should be noted that writing timer functions requires special
care, as the dynamic environment in which they run is unpredictable:
dynamic variable bindings, locks held, etc, all depend on whatever code
was running when the timer fired.  The following example should serve as
a cautionary tale:

     (defvar *foo* nil)

     (defun show-foo ()
       (format t "~&foo=~S~%" *foo*)
       (force-output t))

     (defun demo ()
       (schedule-timer (make-timer #'show-foo) 0.5)
       (schedule-timer (make-timer #'show-foo) 1.5)
       (let ((*foo* t))
         (sleep 1.0))
       (let ((*foo* :surprise!))
         (sleep 2.0)))

14.1 Timer Dictionary
=====================

 -- Structure: timer
     Class precedence list: ‘timer’, ‘structure-object’, ‘t’

     Timer type.  Do not rely on timers being structs as it may change
     in future versions.
 -- Function: make-timer function &key name thread
     Create a timer that runs ‘function’ when triggered.

     If a ‘thread’ is supplied, ‘function’ is run in that thread.  If
     ‘thread’ is ‘t’, a new thread is created for ‘function’ each time
     the timer is triggered.  If ‘thread’ is ‘nil’, ‘function’ is run in
     an unspecified thread.

     When ‘thread’ is not ‘t’, ‘interrupt-thread’ is used to run
     ‘function’ and the ordering guarantees of ‘interrupt-thread’ apply.
     In that case, ‘function’ runs with interrupts disabled but
     ‘with-interrupts’ is allowed.
 -- Function: timer-name timer
     Return the name of ‘timer’.
 -- Function: timer-scheduled-p timer &key delta
     See if ‘timer’ will still need to be triggered after ‘delta’
     seconds from now.  For timers with a repeat interval it returns
     true.
 -- Function: schedule-timer timer time &key repeat-interval absolute-p
          catch-up
     Schedule ‘timer’ to be triggered at ‘time’.  If ‘absolute-p’ then
     ‘time’ is universal time, but non-integral values are also allowed,
     else ‘time’ is measured as the number of seconds from the current
     time.

     If ‘repeat-interval’ is given, ‘timer’ is automatically rescheduled
     upon expiry.

     If ‘repeat-interval’ is non-NIL, the Boolean ‘catch-up’ controls
     whether ‘timer’ will "catch up" by repeatedly calling its function
     without delay in case calls are missed because of a clock
     discontinuity such as a suspend and resume cycle of the computer.
     The default is ‘nil’, i.e.  do not catch up.
 -- Function: unschedule-timer timer
     Cancel ‘timer’.  Once this function returns it is guaranteed that
     ‘timer’ shall not be triggered again and there are no unfinished
     triggers.
 -- Function: list-all-timers
     Return a list of all timers in the system.

15 Networking
*************

The ‘sb-bsd-sockets’ module provides a thinly disguised BSD socket API
for SBCL. Ideas have been stolen from the BSD socket API for C and
Graham Barr's IO::Socket classes for Perl.

   Sockets are represented as CLOS objects, and the API naming
conventions attempt to balance between the BSD names and good lisp
style.

15.1 Sockets Overview
=====================

Most of the functions are modelled on the BSD socket API. BSD sockets
are widely supported, portably _("portable" by Unix standards, at
least)_ available on a variety of systems, and documented.  There are
some differences in approach where we have taken advantage of some of
the more useful features of Common Lisp - briefly:

   • Where the C API would typically return -1 and set ‘errno’,
     ‘sb-bsd-sockets’ signals an error.  All the errors are subclasses
     of ‘sb-bsd-sockets:socket-condition’ and generally correspond one
     for one with possible ‘errno’ values.

   • We use multiple return values in many places where the C API would
     use pass-by-reference values.

   • We can often avoid supplying an explicit _length_ argument to
     functions because we already know how long the argument is.

   • IP addresses and ports are represented in slightly friendlier
     fashion than "network-endian integers".

15.2 General Sockets
====================

 -- Class: socket
     Class precedence list: ‘socket’, ‘standard-object’, ‘t’

     Slots:
        • ‘protocol’ -- initarg: ‘:protocol’; reader:
          ‘sb-bsd-sockets:socket-protocol’

          Protocol used by the socket.  If a keyword, the symbol-name of
          the keyword will be passed to ‘get-protocol-by-name’
          downcased, and the returned value used as protocol.  Other
          values are used as-is.
        • ‘type’ -- initarg: ‘:type’; reader:
          ‘sb-bsd-sockets:socket-type’

          Type of the socket: ‘:stream’ or ‘:datagram’.

     Common superclass of all sockets, not meant to be directly
     instantiated.

 -- Generic Function: socket-bind socket &rest address
     Bind ‘socket’ to ‘address’, which may vary according to socket
     family.  For the ‘inet’ family, pass ‘address’ and ‘port’ as two
     arguments; for ‘file’ address family sockets, pass the filename
     string.  See also bind(2)

 -- Generic Function: socket-accept socket
     Perform the accept(2) call, returning a newly-created connected
     socket and the peer address as multiple values

 -- Generic Function: socket-connect socket &rest address
     Perform the connect(2) call to connect ‘socket’ to a remote ‘peer’.
     No useful return value.

 -- Generic Function: socket-peername socket
     Return SOCKET's peer; depending on the address family this may
     return multiple values

 -- Generic Function: socket-name socket
     Return the address (as vector of bytes) and port that ‘socket’ is
     bound to, as multiple values.

 -- Generic Function: socket-receive socket buffer length &key oob peek
          waitall dontwait element-type
     Read ‘length’ octets from ‘socket’ into ‘buffer’ (or a
     freshly-consed buffer if ‘nil’), using recvfrom(2).  If ‘length’ is
     ‘nil’, the length of ‘buffer’ is used, so at least one of these two
     arguments must be non-NIL. If ‘buffer’ is supplied, it had better
     be of an element type one octet wide.  Returns the buffer, its
     length, and the address of the peer that sent it, as multiple
     values.  On datagram sockets, sets MSG_TRUNC so that the actual
     packet length is returned even if the buffer was too small.

 -- Generic Function: socket-send socket buffer length &key address
          external-format oob eor dontroute dontwait nosignal confirm
          more
     Send ‘length’ octets from ‘buffer’ into ‘socket’, using sendto(2).
     If ‘buffer’ is a string, it will converted to octets according to
     ‘external-format’.  If ‘length’ is ‘nil’, the length of the octet
     buffer is used.  The format of ‘address’ depends on the socket type
     (for example for ‘inet’ domain sockets it would be a list of an
     ‘ip’ address and a port).  If no socket address is provided,
     send(2) will be called instead.  Returns the number of octets
     written.

 -- Generic Function: socket-listen socket backlog
     Mark ‘socket’ as willing to accept incoming connections.  The
     integer ‘backlog’ defines the maximum length that the queue of
     pending connections may grow to before new connection attempts are
     refused.  See also listen(2)

 -- Generic Function: socket-open-p socket
     Return true if ‘socket’ is open; otherwise, return false.

 -- Generic Function: socket-close socket &key abort
     Close ‘socket’, unless it was already closed.

     If ‘socket-make-stream’ has been called, calls ‘close’ using
     ‘abort’ on that stream.  Otherwise closes the socket file
     descriptor using close(2).

 -- Generic Function: socket-shutdown socket &key direction
     Indicate that no communication in ‘direction’ will be performed on
     ‘socket’.

     ‘direction’ has to be one of ‘:input’, ‘:output’ or ‘:io’.

     After a shutdown, no input and/or output of the indicated
     ‘direction’ can be performed on ‘socket’.

 -- Generic Function: socket-make-stream socket &key input output
          element-type external-format buffering timeout auto-close
          serve-events
     Find or create a ‘stream’ that can be used for ‘io’ on ‘socket’
     (which must be connected).  Specify whether the stream is for
     ‘input’, ‘output’, or both (it is an error to specify neither).

     ‘element-type’ and ‘external-format’ are as per ‘open’.

     ‘timeout’ specifies a read timeout for the stream.
 -- Method: socket-make-stream (socket socket) &key input output
          (element-type (quote character)) (buffering full)
          (external-format default) timeout auto-close serve-events
     Default method for ‘socket’ objects.

     ‘element-type’ defaults to ‘character’, to construct a bivalent
     stream, capable of both binary and character ‘io’ use ‘:default’.

     Acceptable values for ‘buffering’ are ‘:full’, ‘:line’ and ‘:none’,
     default is ‘:full’, ie.  output is buffered till it is explicitly
     flushed using ‘close’ or ‘finish-output’.  (‘force-output’ forces
     some output to be flushed: to ensure all buffered output is flused
     use ‘finish-output’.)

     Streams have no ‘timeout’ by default.  If one is provided, it is
     the number of seconds the system will at most wait for input to
     appear on the socket stream when trying to read from it.

     If ‘auto-close’ is true, the underlying ‘os’ socket is
     automatically closed after the stream and the socket have been
     garbage collected.  Default is false.

     If ‘serve-events’ is true, blocking ‘io’ on the socket will
     dispatch to the recursive event loop.  Default is false.

     The stream for ‘socket’ will be cached, and a second invocation of
     this method will return the same stream.  This may lead to oddities
     if this function is invoked with inconsistent arguments (e.g., one
     might request an input stream and get an output stream in
     response).

 -- Function: socket-error where &optional errno
     Signal an appropriate error for syscall ‘where’ and ‘errno’.

     ‘where’ should be a string naming the failed function.

     When supplied, ‘errno’ should be the ‘unix’ error number associated
     to the failed call.  The default behavior is to use the current
     value of the errno variable.

 -- Generic Function: non-blocking-mode socket
     Is ‘socket’ in non-blocking mode?

15.3 Socket Options
===================

A subset of socket options are supported, using a fairly general
framework which should make it simple to add more as required - see
‘SYS:CONTRIB;SB-BSD-SOCKETS:SOCKOPT.LISP’ for details.  The name mapping
from C is fairly straightforward: ‘SO_RCVLOWAT’ becomes
‘sockopt-receive-low-water’ and ‘(setf sockopt-receive-low-water)’.

 -- Function: sockopt-reuse-address socket
     Return the value of the ‘so-reuseaddr’ socket option for ‘socket’.
     This can also be updated with ‘setf’.

 -- Function: sockopt-keep-alive socket
     Return the value of the ‘so-keepalive’ socket option for ‘socket’.
     This can also be updated with ‘setf’.

 -- Function: sockopt-oob-inline socket
     Return the value of the ‘so-oobinline’ socket option for ‘socket’.
     This can also be updated with ‘setf’.

 -- Function: sockopt-bsd-compatible socket
     Return the value of the ‘so-bsdcompat’ socket option for ‘socket’.
     This can also be updated with ‘setf’.  Available only on Linux.

 -- Function: sockopt-pass-credentials socket
     Return the value of the ‘so-passcred’ socket option for ‘socket’.
     This can also be updated with ‘setf’.  Available only on Linux.

 -- Function: sockopt-debug socket
     Return the value of the ‘so-debug’ socket option for ‘socket’.
     This can also be updated with ‘setf’.

 -- Function: sockopt-dont-route socket
     Return the value of the ‘so-dontroute’ socket option for ‘socket’.
     This can also be updated with ‘setf’.

 -- Function: sockopt-broadcast socket
     Return the value of the ‘so-broadcast’ socket option for ‘socket’.
     This can also be updated with ‘setf’.

 -- Function: sockopt-tcp-nodelay socket
     Return the value of the ‘tcp-nodelay’ socket option for ‘socket’.
     This can also be updated with ‘setf’.

15.4 INET Domain Sockets
========================

The TCP and UDP sockets that you know and love.  Some representation
issues:

   • IPv4 Internet addresses are represented by vectors of
     ‘(unsigned-byte 8)’ - viz.  ‘#(127 0 0 1)’.  Ports are just
     integers: 6010.  No conversion between network- and host-order data
     is needed from the user of this package.

   • IPv6 Internet addresses are represented by vectors of 16
     ‘(unsigned-byte 8)’ - viz.  ‘#(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1)’.
     Ports are just integers.  As for IPv4 addresses, no conversion
     between network- and host-order data is needed from the user of
     this package.

   • Socket addresses are represented by the two values for address and
     port, so for example, ‘(socket-connect socket #(192 168 1 1) 80)’
     for IPv4 and ‘(socket-connect socket #(0 0 0 0 0 0 0 0 0 0 0 0 0 0
     0 1) 80)’ for IPv6.

 -- Class: inet-socket
     Class precedence list: ‘inet-socket’, ‘socket’, ‘standard-object’,
     ‘t’

     Class representing ‘tcp’ and ‘udp’ over IPv4 sockets.

     Examples:

           (make-instance 'sb-bsd-sockets:inet-socket :type :stream :protocol :tcp)

           (make-instance 'sb-bsd-sockets:inet-socket :type :datagram :protocol :udp)

 -- Class: inet6-socket
     Class precedence list: ‘inet6-socket’, ‘socket’, ‘standard-object’,
     ‘t’

     Class representing ‘tcp’ and ‘udp’ over IPv6 sockets.

     Examples:

           (make-instance 'sb-bsd-sockets:inet6-socket :type :stream :protocol :tcp)

           (make-instance 'sb-bsd-sockets:inet6-socket :type :datagram :protocol :udp)

 -- Function: make-inet-address dotted-quads
     Return a vector of octets given a string ‘dotted-quads’ in the
     format "127.0.0.1".  Signals an error if the string is malformed.

 -- Function: make-inet6-address colon-separated-integers
     Return a vector of octets given a string representation of an IPv6
     address ‘colon-separated-integers’.  Signal an error if the string
     is malformed.

 -- Function: get-protocol-by-name name
     Given a protocol name, return the protocol number, the protocol
     name, and a list of protocol aliases

15.5 Local (Unix) Domain Sockets
================================

Local domain (‘AF_LOCAL’) sockets are also known as Unix-domain sockets,
but were renamed by POSIX presumably on the basis that they may be
available on other systems too.

   A local socket address is a string, which is used to create a node in
the local filesystem.  This means of course that they cannot be used
across a network.

 -- Class: local-socket
     Class precedence list: ‘local-socket’, ‘socket’, ‘standard-object’,
     ‘t’

     Class representing local domain (AF_LOCAL) sockets, also known as
     unix-domain sockets.

   A local abstract socket address is also a string the scope of which
is the local machine.  However, in contrast to a local socket address,
there is no corresponding filesystem node.

 -- Class: local-abstract-socket
     Class precedence list: ‘local-abstract-socket’, ‘local-socket’,
     ‘socket’, ‘standard-object’, ‘t’

     Class representing local domain (AF_LOCAL) sockets with addresses
     in the abstract namespace.

15.6 Name Service
=================

Presently name service is implemented by calling out to the
‘getaddrinfo(3)’ and ‘gethostinfo(3)’, or to ‘gethostbyname(3)’
‘gethostbyaddr(3)’ on platforms where the preferred functions are not
available.  The exact details of the name resolving process (for example
the choice of whether DNS or a hosts file is used for lookup) are
platform dependent.

 -- Class: host-ent
     Class precedence list: ‘host-ent’, ‘standard-object’, ‘t’

     Slots:
        • ‘name’ -- initarg: ‘:name’; reader:
          ‘sb-bsd-sockets:host-ent-name’

          The name of the host
        • ‘addresses’ -- initarg: ‘:addresses’; reader:
          ‘sb-bsd-sockets:host-ent-addresses’

          A list of addresses for this host.

     This class represents the results of an address lookup.

 -- Function: get-host-by-name host-name
     Returns a ‘host-ent’ instance for ‘host-name’ or signals a
     ‘name-service-error’.

     Another ‘host-ent’ instance containing zero, one or more IPv6
     addresses may be returned as a second return value.

     ‘host-name’ may also be an ‘ip’ address in dotted quad notation or
     some other weird stuff ‘-’ see getaddrinfo(3) for the details.

 -- Function: get-host-by-address address
     Returns a ‘host-ent’ instance for ‘address’, which should be a
     vector of (integer 0 255) with 4 elements in case of an IPv4
     address and 16 elements in case of an IPv6 address, or signals a
     ‘name-service-error’.  See gethostbyaddr(3) for details.

 -- Generic Function: host-ent-address host-ent
     Return some valid address for ‘host-ent’.

16 Profiling
************

SBCL includes both a deterministic profiler, that can collect statistics
on individual functions, and a more "modern" statistical profiler.

   Inlined functions do not appear in the results reported by either.

16.1 Deterministic Profiler
===========================

The package ‘sb-profile’ provides a classic, per-function-call profiler.

     note: When profiling code executed by multiple threads in parallel,
     the consing attributed to each function is inaccurate.

 -- Macro: profile &rest names
     ‘profile’ Name*

     If no names are supplied, return the list of profiled functions.

     If names are supplied, wrap profiling code around the named
     functions.  As in ‘trace’, the names are not evaluated.  A symbol
     names a function.  A string names all the functions named by
     symbols in the named package.  If a function is already profiled,
     then unprofile and reprofile (useful to notice function
     redefinition.)  If a name is undefined, then we give a warning and
     ignore it.  See also ‘unprofile’, ‘report’ and ‘reset’.
 -- Macro: unprofile &rest names
     Unwrap any profiling code around the named functions, or if no
     names are given, unprofile all profiled functions.  A symbol names
     a function.  A string names all the functions named by symbols in
     the named package.  ‘names’ defaults to the list of names of all
     currently profiled functions.
 -- Function: report &key limit print-no-call-list
     Report results from profiling.  The results are approximately
     adjusted for profiling overhead.  The compensation may be rather
     inaccurate when bignums are involved in runtime calculation, as in
     a very-long-running Lisp process.

     If ‘limit’ is set to an integer, only the top ‘limit’ results are
     reported.  If ‘print-no-call-list’ is ‘t’ (the default) then a list
     of uncalled profiled functions are listed.
 -- Function: reset
     Reset the counters for all profiled functions.

16.2 Statistical Profiler
=========================

The ‘sb-sprof’ module, loadable by
     (require :sb-sprof)
   provides an alternate profiler which works by taking samples of the
program execution at regular intervals, instead of instrumenting
functions like ‘sb-profile:profile’ does.  You might find ‘sb-sprof’
more useful than the deterministic profiler when profiling functions in
the ‘common-lisp’-package, SBCL internals, or code where the
instrumenting overhead is excessive.

   Additionally ‘sb-sprof’ includes a limited deterministic profiler
which can be used for reporting the amounts of calls to some functions
during

16.2.1 Example Usage
--------------------

     (in-package :cl-user)

     (require :sb-sprof)

     (declaim (optimize speed))

     (defun cpu-test-inner (a i)
       (logxor a
               (* i 5)
               (+ a i)))

     (defun cpu-test (n)
       (let ((a 0))
         (dotimes (i (expt 2 n) a)
           (setf a (cpu-test-inner a i)))))

     ;;;; CPU profiling

     ;;; Take up to 1000 samples of running (CPU-TEST 26), and give a flat
     ;;; table report at the end. Profiling will end one the body has been
     ;;; evaluated once, whether or not 1000 samples have been taken.
     (sb-sprof:with-profiling (:max-samples 1000
                               :report :flat
                               :loop nil)
       (cpu-test 26))

     ;;; Record call counts for functions defined on symbols in the CL-USER
     ;;; package.
     (sb-sprof:profile-call-counts "CL-USER")

     ;;; Take 1000 samples of running (CPU-TEST 24), and give a flat
     ;;; table report at the end. The body will be re-evaluated in a loop
     ;;; until 1000 samples have been taken. A sample count will be printed
     ;;; after each iteration.
     (sb-sprof:with-profiling (:max-samples 1000
                               :report :flat
                               :loop t
                               :show-progress t)
       (cpu-test 24))

     ;;;; Allocation profiling

     (defun foo (&rest args)
       (mapcar (lambda (x) (float x 1d0)) args))

     (defun bar (n)
       (declare (fixnum n))
       (apply #'foo (loop repeat n collect n)))

     (sb-sprof:with-profiling (:max-samples 10000
                               :mode :alloc
                               :report :flat)
       (bar 1000))

16.2.2 Output
-------------

The flat report format will show a table of all functions that the
profiler encountered on the call stack during sampling, ordered by the
number of samples taken while executing that function.

                Self        Total        Cumul
       Nr  Count     %  Count     %  Count     %    Calls  Function
     ------------------------------------------------------------------------
        1     69  24.4     97  34.3     69  24.4 67108864  CPU-TEST-INNER
        2     64  22.6     64  22.6    133  47.0        -  SB-VM::GENERIC-+
        3     39  13.8    256  90.5    172  60.8        1  CPU-TEST
        4     31  11.0     31  11.0    203  71.7        -  SB-KERNEL:TWO-ARG-XOR

   For each function, the table will show three absolute and relative
sample counts.  The Self column shows samples taken while directly
executing that function.  The Total column shows samples taken while
executing that function or functions called from it (sampled to a
platform-specific depth).  The Cumul column shows the sum of all Self
columns up to and including that line in the table.

   Additionally the Calls column will record the amount of calls that
were made to the function during the profiling run.  This value will
only be reported for functions that have been explicitly marked for call
counting with ‘profile-call-counts’.

   The profiler also hooks into the disassembler such that instructions
which have been sampled are annotated with their relative frequency of
sampling.  This information is not stored across different sampling
runs.

     ;      6CF:       702E             JO L4              ; 6/242 samples
     ;      6D1:       D1E3             SHL EBX, 1
     ;      6D3:       702A             JO L4
     ;      6D5: L2:   F6C303           TEST BL, 3         ; 2/242 samples
     ;      6D8:       756D             JNE L8
     ;      6DA:       8BC3             MOV EAX, EBX       ; 5/242 samples
     ;      6DC: L3:   83F900           CMP ECX, 0         ; 4/242 samples

16.2.3 Platform support
-----------------------

Allocation profiling is only supported on SBCL builds that use the
generational garbage collector.  Tracking of call stacks at a depth of
more than two levels is only supported on x86 and x86-64.

16.2.4 Macros
-------------

 -- Macro: with-profiling (&key sample-interval alloc-interval
          max-samples reset mode loop max-depth show-progress threads
          report) &body body
     Evaluate ‘body’ with statistical profiling turned on.  If ‘loop’ is
     true, loop around the ‘body’ until a sufficient number of samples
     has been collected.  Returns the values from the last evaluation of
     ‘body’.

     The following keyword args are recognized:

     _‘:sample-interval’ <n>_
          Take a sample every <n> seconds.  Default is
          ‘*sample-interval*’.

     _‘:mode’ <mode>_
          If ‘:cpu’, run the profiler in ‘cpu’ profiling mode.  If
          ‘:alloc’, run the profiler in allocation profiling mode.  If
          ‘:time’, run the profiler in wallclock profiling mode.

     _‘:max-samples’ <max>_
          If ‘:loop’ is ‘nil’ (the default), collect no more than <max>
          samples.  If ‘:loop’ is ‘t’, repeat evaluating body until
          <max> samples are taken.  Default is ‘*max-samples*’.

     _‘:report’ <type>_
          If specified, call ‘report’ with ‘:type’ <type> at the end.

     _‘:reset’ <bool>_
          If true, call ‘reset’ at the beginning.

     _‘:threads’ <list-form>_
          Form that evaluates to the list threads to profile, or ‘:all’
          to indicate that all threads should be profiled.  Defaults to
          all threads.

          ‘:threads’ has no effect on call-counting at the moment.

          On some platforms (eg.  Darwin) the signals used by the
          profiler are not properly delivered to threads in proportion
          to their ‘cpu’ usage when doing ‘:cpu’ profiling.  If you see
          empty call graphs, or are obviously missing several samples
          from certain threads, you may be falling afoul of this.  In
          this case using ‘:mode’ ‘:time’ is likely to work better.

     _‘:loop’ <bool>_
          If false (the default), evaluate ‘body’ only once.  If true
          repeatedly evaluate ‘body’.

 -- Macro: with-sampling (&optional on) &body body
     Evaluate body with statistical sampling turned on or off in the
     current thread.

16.2.5 Functions
----------------

 -- Function: map-traces function samples
     Call ‘function’ on each trace in ‘samples’

     The signature of ‘function’ must be compatible with (thread trace).

     ‘function’ is called once for each trace where ‘thread’ is the
     ‘sb-thread:tread’ instance which was sampled to produce ‘trace’,
     and ‘trace’ is an opaque object to be passed to
     ‘map-trace-pc-locs’.

     ‘experimental:’ Interface subject to change.

 -- Function: sample-pc info pc-or-offset
     Extract and return program counter from ‘info’ and ‘pc-or-offset’.

     Can be applied to the arguments passed by ‘map-trace-pc-locs’ and
     ‘map-all-pc-locs’.

     ‘experimental:’ Interface subject to change.

 -- Function: report &key type max min-percent call-graph sort-by
          sort-order stream show-progress
     Report statistical profiling results.  The following keyword args
     are recognized:

     _‘:type’ <type>_
          Specifies the type of report to generate.  If ‘:flat’, show
          flat report, if ‘:graph’ show a call graph and a flat report.
          If nil, don't print out a report.

     _‘:stream’ <stream>_
          Specify a stream to print the report on.  Default is
          ‘*standard-output*’.

     _‘:max’ <max>_
          Don't show more than <max> entries in the flat report.

     _‘:min-percent’ <min-percent>_
          Don't show functions taking less than <min-percent> of the
          total time in the flat report.

     _‘:sort-by’ <column>_
          If ‘:samples’, sort flat report by number of samples taken.
          If ‘:cumulative-samples’, sort flat report by cumulative
          number of samples taken (shows how much time each function
          spent on stack.)  Default is ‘*report-sort-by*’.

     _‘:sort-order’ <order>_
          If ‘:descending’, sort flat report in descending order.  If
          ‘:ascending’, sort flat report in ascending order.  Default is
          ‘*report-sort-order*’.

     _‘:show-progress’ <bool>_
          If true, print progress messages while generating the call
          graph.

     _‘:call-graph’ <graph>_
          Print a report from <graph> instead of the latest profiling
          results.

     Value of this function is a ‘call-graph’ object representing the
     resulting call-graph, or ‘nil’ if there are no samples (eg.  right
     after calling ‘reset’.)

     Profiling is stopped before the call graph is generated.

 -- Function: reset
     Reset the profiler.

 -- Function: start-profiling &key max-samples mode sample-interval
          alloc-interval max-depth threads
     Start profiling statistically in the current thread if not already
     profiling.  The following keyword args are recognized:

     _‘:sample-interval’ <n>_
          Take a sample every <n> seconds.  Default is
          ‘*sample-interval*’.

     _‘:mode’ <mode>_
          If ‘:cpu’, run the profiler in ‘cpu’ profiling mode.  If
          ‘:alloc’, run the profiler in allocation profiling mode.  If
          ‘:time’, run the profiler in wallclock profiling mode.

     _‘:max-samples’ <max>_
          Maximum number of stack traces to collect.  Default is
          ‘*max-samples*’.

     _‘:threads’ <list>_
          List threads to profile, or ‘:all’ to indicate that all
          threads should be profiled.  Defaults to ‘:all’.

          ‘:threads’ has no effect on call-counting at the moment.

          On some platforms (eg.  Darwin) the signals used by the
          profiler are not properly delivered to threads in proportion
          to their ‘cpu’ usage when doing ‘:cpu’ profiling.  If you see
          empty call graphs, or are obviously missing several samples
          from certain threads, you may be falling afoul of this.

 -- Function: stop-profiling
     Stop profiling if profiling.

 -- Function: profile-call-counts &rest names
     Mark the functions named by ‘names’ as being subject to call
     counting during statistical profiling.  If a string is used as a
     name, it will be interpreted as a package name.  In this case call
     counting will be done for all functions with names like ‘x’ or
     (‘setf’ ‘x’), where ‘x’ is a symbol with the package as its home
     package.

 -- Function: unprofile-call-counts
     Clear all call counting information.  Call counting will be done
     for no functions during statistical profiling.

16.2.6 Variables
----------------

 -- Variable: *max-samples*
     Default maximum number of stack traces collected.

 -- Variable: *sample-interval*
     Default number of seconds between samples.

16.2.7 Credits
--------------

‘sb-sprof’ is an SBCL port, with enhancements, of Gerd Moellmann's
statistical profiler for CMUCL.

17 Contributed Modules
**********************

SBCL comes with a number of modules that are not part of the core
system.  These are loaded via ‘(require :MODULENAME)’ (see
Customization Hooks for Users).  This section contains documentation
(or pointers to documentation) for some of the contributed modules.

17.1 sb-aclrepl
===============

The ‘sb-aclrepl’ module offers an Allegro CL-style Read-Eval-Print Loop
for SBCL, with integrated inspector.  Adding a debugger interface is
planned.

17.1.1 Usage
------------

To start ‘sb-aclrepl’ as your read-eval-print loop, put the form
     (require 'sb-aclrepl)

   in your ‘~/.sbclrc’ initialization file.

17.1.2 Customization
--------------------

The following customization variables are available:

 -- Variable: *command-char*
     Prefix character for a top-level command
 -- Variable: *prompt*
     The current prompt string or formatter function.
 -- Variable: *exit-on-eof*
     If ‘t’, then exit when the ‘eof’ character is entered.
 -- Variable: *use-short-package-name*
     when ‘t’, use the shortnest package nickname in a prompt
 -- Variable: *max-history*
     Maximum number of history commands to remember

17.1.3 Example Initialization
-----------------------------

Here's a longer example of a ‘~/.sbclrc’ file that shows off some of the
features of ‘sb-aclrepl’:

     (ignore-errors (require 'sb-aclrepl))

     (when (find-package 'sb-aclrepl)
       (push :aclrepl cl:*features*))
     #+aclrepl
     (progn
       (setq sb-aclrepl:*max-history* 100)
       (setf (sb-aclrepl:alias "asdc")
            #'(lambda (sys) (asdf:operate 'asdf:compile-op sys)))
       (sb-aclrepl:alias "l" (sys) (asdf:operate 'asdf:load-op sys))
       (sb-aclrepl:alias "t" (sys) (asdf:operate 'asdf:test-op sys))
       ;; The 1 below means that two characaters ("up") are required
       (sb-aclrepl:alias ("up" 1 "Use package") (package) (use-package package))
       ;; The 0 below means only the first letter ("r") is required,
       ;; such as ":r base64"
       (sb-aclrepl:alias ("require" 0 "Require module") (sys) (require sys))
       (setq cl:*features* (delete :aclrepl cl:*features*)))

   Questions, comments, or bug reports should be sent to Kevin Rosenberg
(<kevin@rosenberg.net>).

17.1.4 Credits
--------------

Allegro CL is a registered trademark of Franz Inc.

17.2 sb-concurrency
===================

Additional data structures, synchronization primitives and tools for
concurrent programming.  Similiar to Java's ‘java.util.concurrent’
package.

17.2.1 Queue
------------

‘sb-concurrency:queue’ is a lock-free, thread-safe FIFO queue datatype.

The implementation is based on ‘An Optimistic Approach to Lock-Free FIFO
Queues’ by Edya Ladan-Mozes and Nir Shavit.

Before SBCL 1.0.38, this implementation resided in its own contrib
(see sb-queue) which is still provided for backwards-compatibility
but which has since been deprecated.

 -- Structure: queue
     Class precedence list: ‘queue’, ‘structure-object’, ‘t’

     Lock-free thread safe ‘fifo’ queue.

     Use ‘enqueue’ to add objects to the queue, and ‘dequeue’ to remove
     them.

 -- Function: dequeue queue
     Retrieves the oldest value in ‘queue’ and returns it as the primary
     value, and ‘t’ as secondary value.  If the queue is empty, returns
     ‘nil’ as both primary and secondary value.
 -- Function: enqueue value queue
     Adds ‘value’ to the end of ‘queue’.  Returns ‘value’.
 -- Function: list-queue-contents queue
     Returns the contents of ‘queue’ as a list without removing them
     from the ‘queue’.  Mainly useful for manual examination of queue
     state, as the list may be out of date by the time it is returned,
     and concurrent dequeue operations may in the worse case force the
     queue-traversal to be restarted several times.
 -- Function: make-queue &key name initial-contents
     Returns a new ‘queue’ with ‘name’ and contents of the
     ‘initial-contents’ sequence enqueued.
 -- Function: queue-count queue
     Returns the number of objects in ‘queue’.  Mainly useful for manual
     examination of queue state, and in ‘print-object’ methods:
     inefficient as it must walk the entire queue.
 -- Function: queue-empty-p queue
     Returns ‘t’ if ‘queue’ is empty, ‘nil’ otherwise.
 -- Function: queue-name instance
     Name of a ‘queue’.  Can be assigned to using ‘setf’.  Queue names
     can be arbitrary printable objects, and need not be unique.
 -- Function: queuep object
     Returns true if argument is a ‘queue’, ‘nil’ otherwise.

17.2.2 Mailbox (lock-free)
--------------------------

‘sb-concurrency:mailbox’ is a lock-free message queue where one or
multiple ends can send messages to one or multiple receivers.  The
difference to queues is that the
receiving end may block until a message arrives.

Built on top of the queue
implementation.

 -- Structure: mailbox
     Class precedence list: ‘mailbox’, ‘structure-object’, ‘t’

     Mailbox aka message queue.

     ‘send-message’ adds a message to the mailbox, ‘receive-message’
     waits till a message becomes available, whereas
     ‘receive-message-no-hang’ is a non-blocking variant, and
     ‘receive-pending-messages’ empties the entire mailbox in one go.

     Messages can be arbitrary objects

 -- Function: list-mailbox-messages mailbox
     Returns a fresh list containing all the messages in the mailbox.
     Does not remove messages from the mailbox.
 -- Function: mailbox-count mailbox
     Returns the number of messages currently in the mailbox.
 -- Function: mailbox-empty-p mailbox
     Returns true if ‘mailbox’ is currently empty, ‘nil’ otherwise.
 -- Function: mailbox-name instance
     Name of a ‘mailbox’.  SETFable.
 -- Function: mailboxp object
     Returns true if argument is a ‘mailbox’, ‘nil’ otherwise.
 -- Function: make-mailbox &key name initial-contents
     Returns a new ‘mailbox’ with messages in ‘initial-contents’
     enqueued.
 -- Function: receive-message mailbox &key timeout
     Removes the oldest message from ‘mailbox’ and returns it as the
     primary value, and a secondary value of ‘t’.  If ‘mailbox’ is empty
     waits until a message arrives.

     If ‘timeout’ is provided, and no message arrives within the
     specified interval, returns primary and secondary value of ‘nil’.
 -- Function: receive-message-no-hang mailbox
     The non-blocking variant of ‘receive-message’.  Returns two values,
     the message removed from ‘mailbox’, and a flag specifying whether a
     message could be received.
 -- Function: receive-pending-messages mailbox &optional n
     Removes and returns all (or at most ‘n’) currently pending messages
     from ‘mailbox’, or returns ‘nil’ if no messages are pending.

     Note: Concurrent threads may be snarfing messages during the run of
     this function, so even though ‘x’,‘y’ appear right next to each
     other in the result, does not necessarily mean that ‘y’ was the
     message sent right after ‘x’.
 -- Function: send-message mailbox message
     Adds a ‘message’ to ‘mailbox’.  Message can be any object.

17.2.3 Gates
------------

‘sb-concurrency:gate’ is a synchronization object suitable for when
multiple threads must wait for a single event before proceeding.

 -- Structure: gate
     Class precedence list: ‘gate’, ‘structure-object’, ‘t’

     ‘gate’ type.  Gates are synchronization constructs suitable for
     making multiple threads wait for single event before proceeding.

     Use ‘wait-on-gate’ to wait for a gate to open, ‘open-gate’ to open
     one, and ‘close-gate’ to close an open gate.  ‘gate-open-p’ can be
     used to test the state of a gate without blocking.

 -- Function: close-gate gate
     Closes ‘gate’.  Returns ‘t’ if the gate was previously open, and
     ‘nil’ if the gate was already closed.
 -- Function: gate-name instance
     Name of a ‘gate’.  SETFable.
 -- Function: gate-open-p gate
     Returns true if ‘gate’ is open.
 -- Function: gatep object
     Returns true if the argument is a ‘gate’.
 -- Function: make-gate &key name open
     Makes a new gate.  Gate will be initially open if ‘open’ is true,
     and closed if ‘open’ is ‘nil’ (the default.)  ‘name’, if provided,
     is the name of the gate, used when printing the gate.
 -- Function: open-gate gate
     Opens ‘gate’.  Returns ‘t’ if the gate was previously closed, and
     ‘nil’ if the gate was already open.
 -- Function: wait-on-gate gate &key timeout
     Waits for ‘gate’ to open, or ‘timeout’ seconds to pass.  Returns
     ‘t’ if the gate was opened in time, and ‘nil’ otherwise.

17.2.4 Frlocks, aka Fast Read Locks
-----------------------------------

 -- Structure: frlock
     Class precedence list: ‘frlock’, ‘structure-object’, ‘t’

     FRlock, aka Fast Read Lock.

     Fast Read Locks allow multiple readers and one potential writer to
     operate in parallel while providing for consistency for readers and
     mutual exclusion for writers.

     Readers gain entry to protected regions without waiting, but need
     to retry if a writer operated inside the region while they were
     reading.  This makes frlocks very efficient when readers are much
     more common than writers.

     FRlocks are ‘not’ suitable when it is not safe at all for readers
     and writers to operate on the same data in parallel: they provide
     consistency, not exclusion between readers and writers.  Hence
     using an frlock to eg.  protect an ‘sbcl’ hash-table is unsafe.  If
     multiple readers operating in parallel with a writer would be safe
     but inconsistent without a lock, frlocks are suitable.

     The recommended interface to use is ‘frlock-read’ and
     ‘frlock-write’, but those needing it can also use a lower-level
     interface.

     Example:

            ;; Values returned by FOO are always consistent so that
            ;; the third value is the sum of the two first ones.
            (let ((a 0)
                  (b 0)
                  (c 0)
                  (lk (make-frlock)))
              (defun foo ()
                 (frlock-read (lk) a b c))
              (defun bar (x y)
                 (frlock-write (lk)
                   (setf a x
                         b y
                         c (+ x y)))))

 -- Macro: frlock-read (frlock) &body value-forms
     Evaluates ‘value-forms’ under ‘frlock’ till it obtains a consistent
     set, and returns that as multiple values.
 -- Macro: frlock-write (frlock &key wait-p timeout) &body body
     Executes ‘body’ while holding ‘frlock’ for writing.

 -- Function: make-frlock &key name
     Returns a new ‘frlock’ with ‘name’.
 -- Function: frlock-name instance
     Name of an ‘frlock’.  SETFable.

 -- Function: frlock-read-begin frlock
     Start a read sequence on ‘frlock’.  Returns a read-token and an
     epoch to be validated later.

     Using ‘frlock-read’ instead is recommended.
 -- Function: frlock-read-end frlock
     Ends a read sequence on ‘frlock’.  Returns a token and an epoch.
     If the token and epoch are ‘eql’ to the read-token and epoch
     returned by ‘frlock-read-begin’, the values read under the ‘frlock’
     are consistent and can be used: if the values differ, the values
     are inconsistent and the read must be restated.

     Using ‘frlock-read’ instead is recommended.

     Example:

            (multiple-value-bind (t0 e0) (frlock-read-begin *fr*)
              (let ((a (get-a))
                    (b (get-b)))
                (multiple-value-bind (t1 e1) (frlock-read-end *fr*)
                  (if (and (eql t0 t1) (eql e0 e1))
                      (list :a a :b b)
                      :aborted))))
 -- Function: grab-frlock-write-lock frlock &key wait-p timeout
     Acquires ‘frlock’ for writing, invalidating existing and future
     read-tokens for the duration.  Returns ‘t’ on success, and ‘nil’ if
     the lock wasn't acquired due to eg.  a timeout.  Using
     ‘frlock-write’ instead is recommended.
 -- Function: release-frlock-write-lock frlock
     Releases ‘frlock’ after writing, allowing valid read-tokens to be
     acquired again.  Signals an error if the current thread doesn't
     hold ‘frlock’ for writing.  Using ‘frlock-write’ instead is
     recommended.

17.3 sb-cover
=============

The ‘sb-cover’ module provides a code coverage tool for SBCL. The tool
has support for expression coverage, and for some branch coverage.
Coverage reports are only generated for code compiled using
‘compile-file’ with the value of the ‘sb-cover:store-coverage-data’
optimization quality set to 3.

   As of SBCL 1.0.6 ‘sb-cover’ is still experimental, and the interfaces
documented here might change in later versions.

17.3.1 Example Usage
--------------------

     ;;; Load SB-COVER
     (require :sb-cover)

     ;;; Turn on generation of code coverage instrumentation in the compiler
     (declaim (optimize sb-cover:store-coverage-data))

     ;;; Load some code, ensuring that it's recompiled with the new optimization
     ;;; policy.
     (asdf:oos 'asdf:load-op :cl-ppcre-test :force t)

     ;;; Run the test suite.
     (cl-ppcre-test:test)

     ;;; Produce a coverage report
     (sb-cover:report "/tmp/report/")

     ;;; Turn off instrumentation
     (declaim (optimize (sb-cover:store-coverage-data 0)))

17.3.2 Functions
----------------

 -- Function: report directory &key form-mode if-matches external-format
     Print a code coverage report of all instrumented files into
     ‘directory’.  If ‘directory’ does not exist, it will be created.
     The main report will be printed to the file cover-index.html.  The
     external format of the source files can be specified with the
     ‘external-format’ parameter.

     If the keyword argument ‘form-mode’ has the value ‘:car’, the
     annotations in the coverage report will be placed on the CARs of
     any cons-forms, while if it has the value ‘:whole’ the whole form
     will be annotated (the default).  The former mode shows explicitly
     which forms were instrumented, while the latter mode is generally
     easier to read.

     The keyword argument ‘if-matches’ should be a designator for a
     function of one argument, called for the namestring of each file
     with code coverage info.  If it returns true, the file's info is
     included in the report, otherwise ignored.  The default value is
     ‘cl:identity’.

 -- Function: reset-coverage &optional object
     Reset all coverage data back to the 'Not executed' state.

 -- Function: clear-coverage
     Clear all files from the coverage database.  The files will be
     re-entered into the database when the ‘fasl’ files (produced by
     compiling ‘store-coverage-data’ optimization policy set to 3) are
     loaded again into the image.

 -- Function: save-coverage
     Returns an opaque representation of the current code coverage
     state.  The only operation that may be done on the state is passing
     it to ‘restore-coverage’.  The representation is guaranteed to be
     readably printable.  A representation that has been printed and
     read back will work identically in ‘restore-coverage’.

 -- Function: save-coverage-in-file pathname
     Call ‘save-coverage’ and write the results of that operation into
     the file designated by ‘pathname’.

 -- Function: restore-coverage coverage-state
     Restore the code coverage data back to an earlier state produced by
     ‘save-coverage’.

 -- Function: restore-coverage-from-file pathname
     ‘read’ the contents of the file designated by ‘pathname’ and pass
     the result to ‘restore-coverage’.

17.4 sb-grovel
==============

The ‘sb-grovel’ module helps in generation of foreign function
interfaces.  It aids in extracting constants' values from the C compiler
and in generating SB-ALIEN structure and union types, see Defining Foreign Types.

   The ASDF(<http://www.cliki.net/ASDF>) component type
GROVEL-CONSTANTS-FILE has its PERFORM operation defined to write out a C
source file, compile it, and run it.  The output from this program is
Lisp, which is then itself compiled and loaded.

   sb-grovel is used in a few contributed modules, and it is currently
compatible only to SBCL. However, if you want to use it, here are a few
directions.

17.4.1 Using sb-grovel in your own ASDF system
----------------------------------------------

  1. Create a Lisp package for the foreign constants/functions to go
     into.

  2. Make your system depend on the 'sb-grovel system.

  3. Create a grovel-constants data file - for an example, see
     example-constants.lisp in the contrib/sb-grovel/ directory in the
     SBCL source distribution.

  4. Add it as a component in your system.  e.g.

          (eval-when (:compile-toplevel :load-toplevel :execute)
            (require :sb-grovel))

          (defpackage :example-package.system
                      (:use :cl :asdf :sb-grovel :sb-alien))

          (in-package :example-package.system)

          (defsystem example-system
              :depends-on (sb-grovel)
              :components
              ((:module "sbcl"
                        :components
                        ((:file "defpackage")
                         (grovel-constants-file "example-constants"
                                                :package :example-package)))))

     Make sure to specify the package you chose in step 1

  5. Build stuff.

17.4.2 Contents of a grovel-constants-file
------------------------------------------

The grovel-constants-file, typically named ‘constants.lisp’, comprises
lisp expressions describing the foreign things that you want to grovel
for.  A ‘constants.lisp’ file contains two sections:

   • a list of headers to include in the C program, for example:
          ("sys/types.h" "sys/socket.h" "sys/stat.h" "unistd.h" "sys/un.h"
           "netinet/in.h" "netinet/in_systm.h" "netinet/ip.h" "net/if.h"
           "netdb.h" "errno.h" "netinet/tcp.h" "fcntl.h" "signal.h" )

   • A list of sb-grovel clauses describing the things you want to
     grovel from the C compiler, for example:
          ((:integer af-local
                     #+(or sunos solaris) "AF_UNIX"
                     #-(or sunos solaris) "AF_LOCAL"
                     "Local to host (pipes and file-domain).")
           (:structure stat ("struct stat"
                             (integer dev "dev_t" "st_dev")
                             (integer atime "time_t" "st_atime")))
           (:function getpid ("getpid" int )))

   There are two types of things that sb-grovel can sensibly extract
from the C compiler: constant integers and structure layouts.  It is
also possible to define foreign functions in the constants.lisp file,
but these definitions don't use any information from the C program; they
expand directly to ‘sb-alien:define-alien-routine’ (see The define-alien-routine Macro)
forms.

   Here's how to use the grovel clauses:

   • ‘:integer’ - constant expressions in C. Used in this form:
           (:integer lisp-variable-name "C expression" &optional doc export)

     ‘"C expression"’ will be typically be the name of a constant.  But
     other forms are possible.

   • ‘:enum’
           (:enum lisp-type-name ((lisp-enumerated-name c-enumerated-name) ...)))

     An ‘sb-alien:enum’ type with name ‘lisp-type-name’ will be defined.
     The symbols are the ‘lisp-enumerated-name’s, and the values are
     grovelled from the ‘c-enumerated-name’s.

   • ‘:structure’ - alien structure definitions look like this:
           (:structure lisp-struct-name ("struct c_structure"
                                         (type-designator lisp-element-name
                                          "c_element_type" "c_element_name"
                                          :distrust-length nil)
                                         ; ...
                                         ))

     ‘type-designator’ is a reference to a type whose size (and type
     constraints) will be groveled for.  sb-grovel accepts a form of
     type designator that doesn't quite conform to either lisp nor
     sb-alien's type specifiers.  Here's a list of type designators that
     sb-grovel currently accepts:
        • ‘integer’ - a C integral type; sb-grovel will infer the exact
          type from size information extracted from the C program.  All
          common C integer types can be grovelled for with this type
          designator, but it is not possible to grovel for bit fields
          yet.

        • ‘(unsigned n)’ - an unsigned integer variable that is ‘n’
          bytes long.  No size information from the C program will be
          used.
        • ‘(signed n)’ - an signed integer variable that is ‘n’ bytes
          long.  No size information from the C program will be used.

        • ‘c-string’ - an array of ‘char’ in the structure.  sb-grovel
          will use the array's length from the C program, unless you
          pass it the ‘:distrust-length’ keyword argument with non-‘nil’
          value (this might be required for structures such as solaris's
          ‘struct dirent’).

        • ‘c-string-pointer’ - a pointer to a C string, corresponding to
          the ‘sb-alien:c-string’ type (see Foreign Type Specifiers).
        • ‘(array alien-type)’ - An array of the previously-declared
          alien type.  The array's size will be determined from the
          output of the C program and the alien type's size.
        • ‘(array alien-type n)’ - An array of the previously-declared
          alien type.  The array's size will be assumed as being ‘n’.

     Note that ‘c-string’ and ‘c-string-pointer’ do not have the same
     meaning.  If you declare that an element is of type ‘c-string’, it
     will be treated as if the string is a part of the structure,
     whereas if you declare that the element is of type
     ‘c-string-pointer’, a _pointer to a string_ will be the structure
     member.

   • ‘:function’ - alien function definitions are similar to
     ‘define-alien-routine’ definitions, because they expand to such
     forms when the lisp program is loaded.  See Foreign Function Calls.

          (:function lisp-function-name ("alien_function_name" alien-return-type
                                                               (argument alien-type)
                                                               (argument2 alien-type)))

17.4.3 Programming with sb-grovel's structure types
---------------------------------------------------

Let us assume that you have a grovelled structure definition:
      (:structure mystruct ("struct my_structure"
                            (integer myint "int" "st_int")
                            (c-string mystring "char[]" "st_str")))

   What can you do with it?  Here's a short interface document:

   • Creating and destroying objects:
        • Function ‘(allocate-mystruct)’ - allocates an object of type
          ‘mystruct’and returns a system area pointer to it.
        • Macro ‘(with-mystruct var ((member init) [...]) &body body)’ -
          allocates an object of type ‘mystruct’ that is valid in BODY.
          If BODY terminates or control unwinds out of BODY, the object
          pointed to by VAR will be deallocated.

   • Accessing structure members:
        • ‘(mystruct-myint var)’ and ‘(mystruct-mystring var)’ return
          the value of the respective fields in ‘mystruct’.
        • ‘(setf (mystruct-myint var) new-val)’ and ‘(setf
          (mystruct-mystring var) new-val)’ sets the value of the
          respective structure member to the value of NEW-VAL.  Notice
          that in ‘(setf (mystruct-mystring var) new-val)’'s case,
          new-val is a lisp string.

17.4.3.1 Traps and Pitfalls
...........................

Basically, you can treat functions and data structure definitions that
sb-grovel spits out as if they were alien routines and types.  This has
a few implications that might not be immediately obvious (especially if
you have programmed in a previous version of sb-grovel that didn't use
alien types):

   • You must take care of grovel-allocated structures yourself.  They
     are alien types, so the garbage collector will not collect them
     when you drop the last reference.

   • If you use the ‘with-mystruct’ macro, be sure that no references to
     the variable thus allocated leaks out.  It will be deallocated when
     the block exits.

17.5 sb-md5
===========

The ‘sb-md5’ module implements the RFC1321 MD5 Message Digest Algorithm.
[FIXME cite]

 -- Function: md5sum-file pathname
     Calculate the MD5 message-digest of the file specified by
     'pathname'.

 -- Function: md5sum-sequence sequence &key start end
     Calculate the MD5 message-digest of data in 'sequence', which
     should be a 1d simple-array with element type (unsigned-byte 8).
     On ‘cmu’ ‘cl’ and ‘sbcl’ non-simple and non-1d arrays with this
     element-type are also supported.

 -- Function: md5sum-stream stream
     Calculate an MD5 message-digest of the contents of 'stream'.  Its
     element-type has to be (unsigned-byte 8).  Use on character streams
     is ‘deprecated’, as this will not work correctly on implementations
     with 'char-code-limit' > 256 and ignores character coding issues.

 -- Function: md5sum-string string &key external-format start end
     Calculate the MD5 message-digest of the binary representation of
     'string' (as octets) in the external format specified by
     'external-format'.  The boundaries 'start' and 'end' refer to
     character positions in the string, not to octets in the resulting
     binary representation.  The permissible external format specifiers
     are determined by the underlying implementation.

17.5.1 Credits
--------------

The implementation for CMUCL was largely done by Pierre Mai, with help
from members of the ‘cmucl-help’ mailing list.  Since CMUCL and SBCL are
similar in many respects, it was not too difficult to extend the
low-level implementation optimizations for CMUCL to SBCL. Following
this, SBCL's compiler was extended to implement efficient compilation of
modular arithmetic (see Modular arithmetic), which enabled the
implementation to be expressed in portable arithmetical terms, apart
from the use of ‘rotate-byte’ for bitwise rotation.

17.6 sb-posix
=============

Sb-posix is the supported interface for calling out to the operating
system.(1)

   The scope of this interface is "operating system calls on a typical
Unixlike platform".  This is section 2 of the Unix manual, plus section
3 calls that are (a) typically found in libc, but (b) not part of the C
standard.  For example, we intend to provide support for ‘opendir()’ and
‘readdir()’, but not for ‘printf()’.  That said, if your favourite
system call is not included yet, you are encouraged to submit a patch to
the SBCL mailing list.

   Some facilities are omitted where they offer absolutely no additional
use over some portable function, or would be actively dangerous to the
consistency of Lisp.  Not all functions are available on all platforms.

   Sb-posix functions do not implicitly take measures to provide
thread-safety or reentrancy beyond whatever the underlying C library
does, except in cases where doing so is necessary to maintain the
consistency of the Lisp image.  For example, the bindings to the user
and group database accessing functions are neither thread-safe nor
reentrant unless the underlying libc happens to make them so (but
Extensions to POSIX).

   ---------- Footnotes ----------

   (1) The functionality contained in the package ‘SB-UNIX’ is for SBCL
internal use only; its contents are likely to change from version to
version.

17.6.1 Lisp names for C names
-----------------------------

All symbols are in the ‘SB-POSIX’ package.  This package contains a Lisp
function for each supported Unix system call or function, a variable or
constant for each supported Unix constant, an object type for each
supported Unix structure type, and a slot name for each supported Unix
structure member.  A symbol name is derived from the C binding's name,
by (a) uppercasing, then (b) removing leading underscores (‘#\_’) then
replacing remaining underscore characters with the hyphen (‘#\-’).  The
requirement to uppercase is so that in a standard upcasing reader the
user may write ‘sb-posix:creat’ instead of ‘sb-posix:|creat|’ as would
otherise be required.

   No other changes to "Lispify" symbol names are made, so ‘creat()’
becomes ‘CREAT’, not ‘CREATE’.

   The user is encouraged not to ‘(USE-PACKAGE :SB-POSIX)’ but instead
to use the ‘SB-POSIX:’ prefix on all references, as some of the symbols
symbols contained in the SB-POSIX package have the same name as CL
symbols (‘OPEN’, ‘CLOSE’, ‘SIGNAL’ etc).

17.6.2 Types
------------

Generally, marshalling between Lisp and C data types is done using
SBCL's FFI. See Foreign Function Interface.

   Some functions accept objects such as filenames or file descriptors.
In the C binding to POSIX these are represented as strings and small
integers respectively.  For the Lisp programmer's convenience we
introduce designators such that CL pathnames or open streams can be
passed to these functions.  For example, ‘rename’ accepts both pathnames
and strings as its arguments.

17.6.2.1 File-descriptors
.........................

 -- Type: file-descriptor
     A ‘fixnum’ designating a native file descriptor.

     ‘sb-sys:make-fd-stream’ can be used to construct a ‘file-stream’
     associated with a native file descriptor.

     Note that mixing I/O operations on a ‘file-stream’ with operations
     directly on its descriptor may produce unexpected results if the
     stream is buffered.
 -- Type: file-descriptor-designator
     Designator for a ‘file-descriptor:’ either a fixnum designating
     itself, or a ‘file-stream’ designating the underlying
     file-descriptor.
 -- Function: file-descriptor file-descriptor
     Converts ‘file-descriptor-designator’ into a ‘file-descriptor’.

17.6.2.2 Filenames
..................

 -- Type: filename
     A ‘string’ designating a filename in native namestring syntax.

     Note that native namestring syntax is distinct from Lisp namestring
     syntax:

            (pathname "/foo*/bar")

     is a wild pathname with a pattern-matching directory component.
     ‘sb-ext:parse-native-namestring’ may be used to construct Lisp
     pathnames that denote ‘posix’ filenames as understood by system
     calls, and ‘sb-ext:native-namestring’ can be used to coerce them
     into strings in the native namestring syntax.

     Note also that ‘posix’ filename syntax does not distinguish the
     names of files from the names of directories: in order to parse the
     name of a directory in ‘posix’ filename syntax into a pathname
     ‘my-defaults’ for which

            (merge-pathnames (make-pathname :name "FOO" :case :common)
                              my-defaults)

     returns a pathname that denotes a file in the directory, supply a
     true ‘:as-directory’ argument to ‘sb-ext:parse-native-namestring’.
     Likewise, to supply the name of a directory to a ‘posix’ function
     in non-directory syntax, supply a true ‘:as-file’ argument to
     ‘sb-ext:native-namestring’.
 -- Type: filename-designator
     Designator for a ‘filename:’ a ‘string’ designating itself, or a
     designator for a ‘pathname’ designating the corresponding native
     namestring.
 -- Function: filename filename
     Converts ‘filename-designator’ into a ‘filename’.

17.6.3 Function Parameters
--------------------------

The calling convention is modelled after that of CMUCL's ‘UNIX’ package:
in particular, it's like the C interface except that:

  a. Length arguments are omitted or optional where the sensible value
     is obvious.  For example, ‘read’ would be defined this way:

          (read fd buffer &optional (length (length buffer))) => bytes-read

  b. Where C simulates "out" parameters using pointers (for instance, in
     ‘pipe()’ or ‘socketpair()’) these may be optional or omitted in the
     Lisp interface: if not provided, appropriate objects will be
     allocated and returned (using multiple return values if necessary).

  c. Some functions accept objects such as filenames or file
     descriptors.  Wherever these are specified as such in the C
     bindings, the Lisp interface accepts designators for them as
     specified in the 'Types' section above.

  d. A few functions have been included in sb-posix that do not
     correspond exactly with their C counterparts.  These are described
     in Functions with idiosyncratic bindings.

17.6.4 Function Return Values
-----------------------------

The return value is usually the same as for the C binding, except in
error cases: where the C function is defined as returning some sentinel
value and setting ‘errno’ on error, we instead signal an error of type
‘SYSCALL-ERROR’.  The actual error value (‘errno’) is stored in this
condition and can be accessed with ‘SYSCALL-ERRNO’.

   We do not automatically translate the returned value into "Lispy"
objects - for example, ‘SB-POSIX:OPEN’ returns a small integer, not a
stream.  Exception: boolean-returning functions (or, more commonly,
macros) do not return a C integer, but instead a Lisp boolean.

17.6.5 Lisp objects and C structures
------------------------------------

Sb-posix provides various Lisp object types to stand in for C structures
in the POSIX library.  Lisp bindings to C functions that accept,
manipulate, or return C structures accept, manipulate, or return
instances of these Lisp types instead of instances of alien types.

   The names of the Lisp types are chosen according to the general rules
described above.  For example Lisp objects of type ‘STAT’ stand in for C
structures of type ‘struct stat’.

   Accessors are provided for each standard field in the structure.
These are named ‘STRUCTURE-NAME-FIELD-NAME’ where the two components are
chosen according to the general name conversion rules, with the
exception that in cases where all fields in a given structure have a
common prefix, that prefix is omitted.  For example, ‘stat.st_dev’ in C
becomes ‘STAT-DEV’ in Lisp.

   Because sb-posix might not support all semi-standard or
implementation-dependent members of all structure types on your system
(patches welcome), here is an enumeration of all supported Lisp objects
corresponding to supported POSIX structures, and the supported slots for
those structures.

   • flock
      -- Class: flock
          Class precedence list: ‘flock’, ‘standard-object’, ‘t’

          Slots:
             • ‘type’ -- initarg: ‘:type’; reader:
               ‘sb-posix:flock-type’; writer:
               ‘(setf sb-posix:flock-type)’

               Type of lock; F_RDLCK, F_WRLCK, F_UNLCK.
             • ‘whence’ -- initarg: ‘:whence’; reader:
               ‘sb-posix:flock-whence’; writer:
               ‘(setf sb-posix:flock-whence)’

               Flag for starting offset.
             • ‘start’ -- initarg: ‘:start’; reader:
               ‘sb-posix:flock-start’; writer:
               ‘(setf sb-posix:flock-start)’

               Relative offset in bytes.
             • ‘len’ -- initarg: ‘:len’; reader: ‘sb-posix:flock-len’;
               writer: ‘(setf sb-posix:flock-len)’

               Size; if 0 then until ‘eof’.
             • ‘pid’ -- reader: ‘sb-posix:flock-pid’

               Process ‘id’ of the process holding the lock; returned
               with F_GETLK.

          Class representing locks used in fcntl(2).

   • passwd
      -- Class: passwd
          Class precedence list: ‘passwd’, ‘standard-object’, ‘t’

          Slots:
             • ‘name’ -- initarg: ‘:name’; reader:
               ‘sb-posix:passwd-name’; writer:
               ‘(setf sb-posix:passwd-name)’

               User's login name.
             • ‘passwd’ -- initarg: ‘:passwd’; reader:
               ‘sb-posix:passwd-passwd’; writer:
               ‘(setf sb-posix:passwd-passwd)’

               The account's encrypted password.
             • ‘uid’ -- initarg: ‘:uid’; reader: ‘sb-posix:passwd-uid’;
               writer: ‘(setf sb-posix:passwd-uid)’

               Numerical user ‘id’.
             • ‘gid’ -- initarg: ‘:gid’; reader: ‘sb-posix:passwd-gid’;
               writer: ‘(setf sb-posix:passwd-gid)’

               Numerical group ‘id’.
             • ‘gecos’ -- initarg: ‘:gecos’; reader:
               ‘sb-posix:passwd-gecos’; writer:
               ‘(setf sb-posix:passwd-gecos)’

               User's name or comment field.
             • ‘dir’ -- initarg: ‘:dir’; reader: ‘sb-posix:passwd-dir’;
               writer: ‘(setf sb-posix:passwd-dir)’

               Initial working directory.
             • ‘shell’ -- initarg: ‘:shell’; reader:
               ‘sb-posix:passwd-shell’; writer:
               ‘(setf sb-posix:passwd-shell)’

               Program to use as shell.

          Instances of this class represent entries in the system's user
          database.

   • passwd
      -- Class: group
          Class precedence list: ‘group’, ‘standard-object’, ‘t’

          Slots:
             • ‘name’ -- initarg: ‘:name’; reader:
               ‘sb-posix:group-name’; writer:
               ‘(setf sb-posix:group-name)’

               The name of the group.
             • ‘passwd’ -- initarg: ‘:passwd’; reader:
               ‘sb-posix:group-passwd’; writer:
               ‘(setf sb-posix:group-passwd)’

               The group's encrypted password.
             • ‘gid’ -- initarg: ‘:gid’; reader: ‘sb-posix:group-gid’;
               writer: ‘(setf sb-posix:group-gid)’

               Numerical group ‘id’.
             • ‘mem’ -- initarg: ‘:mem’; reader: ‘sb-posix:group-mem’;
               writer: ‘(setf sb-posix:group-mem)’

               A list of strings naming members of the group.

          Instances of this class represent entries in the system's
          group database.

   • stat
      -- Class: stat
          Class precedence list: ‘stat’, ‘standard-object’, ‘t’

          Slots:
             • ‘mode’ -- initarg: ‘:mode’; reader: ‘sb-posix:stat-mode’

               Mode of file.
             • ‘ino’ -- initarg: ‘:ino’; reader: ‘sb-posix:stat-ino’

               File serial number.
             • ‘dev’ -- initarg: ‘:dev’; reader: ‘sb-posix:stat-dev’

               Device ‘id’ of device containing file.
             • ‘nlink’ -- initarg: ‘:nlink’; reader:
               ‘sb-posix:stat-nlink’

               Number of hard links to the file.
             • ‘uid’ -- initarg: ‘:uid’; reader: ‘sb-posix:stat-uid’

               User ‘id’ of file.
             • ‘gid’ -- initarg: ‘:gid’; reader: ‘sb-posix:stat-gid’

               Group ‘id’ of file.
             • ‘size’ -- initarg: ‘:size’; reader: ‘sb-posix:stat-size’

               For regular files, the file size in bytes.  For symbolic
               links, the length in bytes of the filename contained in
               the symbolic link.
             • ‘rdev’ -- initarg: ‘:rdev’; reader: ‘sb-posix:stat-rdev’

               For devices the device number.
             • ‘atime’ -- initarg: ‘:atime’; reader:
               ‘sb-posix:stat-atime’

               Time of last access.
             • ‘mtime’ -- initarg: ‘:mtime’; reader:
               ‘sb-posix:stat-mtime’

               Time of last data modification.
             • ‘ctime’ -- initarg: ‘:ctime’; reader:
               ‘sb-posix:stat-ctime’

               Time of last status change.

          Instances of this class represent ‘posix’ file metadata.

   • termios
      -- Class: termios
          Class precedence list: ‘termios’, ‘standard-object’, ‘t’

          Slots:
             • ‘iflag’ -- initarg: ‘:iflag’; reader:
               ‘sb-posix:termios-iflag’; writer:
               ‘(setf sb-posix:termios-iflag)’

               Input modes.
             • ‘oflag’ -- initarg: ‘:oflag’; reader:
               ‘sb-posix:termios-oflag’; writer:
               ‘(setf sb-posix:termios-oflag)’

               Output modes.
             • ‘cflag’ -- initarg: ‘:cflag’; reader:
               ‘sb-posix:termios-cflag’; writer:
               ‘(setf sb-posix:termios-cflag)’

               Control modes.
             • ‘lflag’ -- initarg: ‘:lflag’; reader:
               ‘sb-posix:termios-lflag’; writer:
               ‘(setf sb-posix:termios-lflag)’

               Local modes.
             • ‘cc’ -- initarg: ‘:cc’; reader: ‘sb-posix:termios-cc’;
               writer: ‘(setf sb-posix:termios-cc)’

               Control characters.

          Instances of this class represent I/O characteristics of the
          terminal.

   • timeval
      -- Class: timeval
          Class precedence list: ‘timeval’, ‘standard-object’, ‘t’

          Slots:
             • ‘sec’ -- initarg: ‘:tv-sec’; reader:
               ‘sb-posix:timeval-sec’; writer:
               ‘(setf sb-posix:timeval-sec)’

               Seconds.
             • ‘usec’ -- initarg: ‘:tv-usec’; reader:
               ‘sb-posix:timeval-usec’; writer:
               ‘(setf sb-posix:timeval-usec)’

               Microseconds.

          Instances of this class represent time values.

17.6.6 Functions with idiosyncratic bindings
--------------------------------------------

A few functions in sb-posix don't correspond directly to their C
counterparts.

   • getcwd
      -- Function: getcwd
          Returns the process's current working directory as a string.
   • readlink
      -- Function: readlink pathspec
          Returns the resolved target of a symbolic link as a string.
   • syslog
      -- Function: syslog priority format &rest args
          Send a message to the syslog facility, with severity level
          ‘priority’.  The message will be formatted as by ‘cl:format’
          (rather than C's printf) with format string ‘format’ and
          arguments ‘args’.

17.6.7 Extensions to POSIX
--------------------------

Some of POSIX's standardized operators are not safe to use on their own,
so ‘SB-POSIX’ exports a few "helpers" that do not correspond exactly to
functionality present in the POSIX standard.

   The user and group database accessing routines are not required to be
thread-safe or reentrant, and so can only be used safely if all clients
coordinate around their use.  Since it would be logically impossible for
independently developed programs to coordinate, ‘SB-POSIX’ exports two
iteration macros, ‘SB-POSIX:DO-PASSWDS’ and ‘SB-POSIX:DO-GROUPS’, each
of which iterates over the respective database while preventing the
keyed accesses (‘SB-POSIX:GETPWNAM’, ‘SB-POSIX:GETPWUID’,
‘SB-POSIX:GETGRNAM’, ‘SB-POSIX:GETGRGID’) from running until iteration
completes.

   • do-passwds
      -- Macro: do-passwds (passwd &optional result) &body body
          Evaluate ‘body’ with ‘passwd’ bound to successive entries from
          the passwd database, and return ‘result’.  An implicit block
          named ‘nil’ surrounds the form; an implicit ‘tagbody’
          surrounds ‘body’.  It is unspecified whether ‘passwd’ is
          assigned, rebound, or destructively modified upon each
          iteration.  It is an error to use any operator that accesses
          the ‘passwd’ database during the dynamic extent of
          ‘do-passwds’.
   • do-groups
      -- Macro: do-groups (group &optional result) &body body
          Evaluate ‘body’ with ‘group’ bound to successive entries from
          the group database, and return ‘result’.  An implicit block
          named ‘nil’ surrounds the form; an implicit ‘tagbody’
          surrounds ‘body’.  It is unspecified whether ‘group’ is
          assigned, rebound, or destructively modified upon each
          iteration.  It is an error to use any operator that accesses
          the ‘group’ database during the dynamic extent of ‘do-groups’.

17.7 sb-queue
=============

Since SBCL 1.0.38, the ‘sb-queue’ module has been merged into the
‘sb-concurrency’ module (see sb-concurrency.)

17.8 sb-rotate-byte
===================

The ‘sb-rotate-byte’ module offers an interface to bitwise rotation,
with an efficient implementation for operations which can be performed
directly using the platform's arithmetic routines.  It implements the
specification at <http://www.cliki.net/ROTATE-BYTE>.

   Bitwise rotation is a component of various cryptographic or hashing
algorithms: MD5, SHA-1, etc.; often these algorithms are specified on
32-bit rings.  [FIXME cite cite cite].

 -- Function: rotate-byte count bytespec integer
     Rotates a field of bits within ‘integer’; specifically, returns an
     integer that contains the bits of ‘integer’ rotated ‘count’ times
     leftwards within the byte specified by ‘bytespec’, and elsewhere
     contains the bits of ‘integer’.

17.9 sb-simd
============

The ‘sb-simd’ module provides a convenient interface for SIMD
programming in SBCL. It provides one package per SIMD instruction set,
plus functions and macros for querying whether an instruction set is
available and what functions and data types it exports.

17.9.1 Data Types
-----------------

The central data type in ‘sb-simd’ is the SIMD pack.  A SIMD pack is
very similar to a specialized vector, except that its length must be a
particular power of two that depends on its element type and the
underlying hardware.  The set of element types that are supported for
SIMD packs is similar to that of SBCL's specialized array element types,
except that there is currently no support for SIMD packs of complex
numbers or characters.

   The supported scalar types are ‘f32’, ‘f64’, ‘sN’, and ‘uN’, where
‘N’ is either 8, 16, 32, or 64.  These scalar types are abbreviations
for the Common Lisp types ‘single-float’, ‘double-float’, ‘signed-byte’,
and ‘unsigned-byte’, respectively.  For each scalar data type ‘X’, there
exists one or more SIMD data type ‘X.Y’ with ‘Y’ elements.  For example,
in AVX there are two supported SIMD data types with element type ‘f64’,
namely ‘f64.2’ (128 bit) and ‘f64.4’ (256 bit).

   SIMD packs are regular Common Lisp objects that have a type, a class,
and can be passed as function arguments.  The price for this is that
SIMD packs have both a boxed and an unboxed representation.  The unboxed
representation of a SIMD pack has zero overhead and fits into a CPU
register, but can only be used within a function and when the compiler
can statically determine the SIMD pack's type.  Otherwise, the SIMD pack
is boxed, i.e., spilled to the heap together with its type information.
In practice, boxing of SIMD packs can usually be avoided via inlining,
or by loading and storing them to specialized arrays instead of passing
them around as function arguments.

17.9.2 Casts
------------

For each scalar data type ‘X’, there is a function named ‘X’ that is
equivalent to ‘(lambda (v) (coerce v 'X))’.  For each SIMD data type
‘X.Y’, there is a function named ‘X.Y’ that ensures that its argument is
of type ‘X.Y’, or, if the argument is a number, calls the cast function
of ‘X’ and broadcasts the result.

   All functions provided by ‘sb-simd’ (apart from the casts themselves)
implicitly cast each argument to its expected type.  So to add the
number five to each single float in a SIMD pack ‘x’ of type ‘f32.8’, it
is sufficient to write ‘(f32.8+ x 5)’.  We don't mention this implicit
conversion explicitly in the following sections, so if any function
description states that an argument must be of type ‘X.Y’, the argument
can actually be of any type that is a suitable argument of the cast
function named ‘X.Y’.

17.9.3 Constructors
-------------------

For each SIMD data type ‘X.Y’, there is a constructor named ‘make-X.Y’
that takes ‘Y’ arguments of type ‘X’ and returns a SIMD pack whose
elements are the supplied values.

17.9.4 Unpackers
----------------

For each SIMD data type ‘X.Y’, there is a function named ‘X.Y-values’
that returns, as ‘Y’ multiple values, the elements of the supplied SIMD
pack of type ‘X.Y’.

17.9.5 Reinterpret Casts
------------------------

For each SIMD data type ‘X.Y’, there is a function named ‘X.Y!’ that
takes any SIMD pack or scalar datum and interprets its bits as a SIMD
pack of type ‘X.Y’.  If the supplied datum has more bits than the
resulting value, the excess bits are discarded.  If the supplied datum
has less bits than the resulting value, the missing bits are assumed to
be zero.

17.9.6 Associatives
-------------------

For each associative binary function, e.g., ‘two-arg-X.Y-OP’, there is a
function ‘X.Y-OP’ that takes any number of arguments and combines them
with this binary function in a tree-like fashion.  If the binary
function has an identity element, it is possible to call the function
with zero arguments, in which case the identity element is returned.  If
there is no identity element, the function must receive at least one
argument.

   Examples of associative functions are ‘f32.8+’, for summing any
number of 256 bit packs of single floats, and ‘u8.32-max’, for computing
the element-wise maximum of one or more 256 bit packs of 8 bit integers.

17.9.7 Reducers
---------------

For binary functions ‘two-arg-X.Y-OP’ that are not associative, but that
have a neutral element, there are functions ‘X.Y-OP’ that take any
positive number of arguments and return the reduction of all arguments
with the binary function.  In the special case of a single supplied
argument, the binary function is invoked on the neutral element and that
argument.  Reducers have been introduced to generate Lisp-style
subtraction and division functions.

   Examples of reducers are ‘f32.8/’, for successively dividing a pack
of 32 bit single floats by all further supplied packs of 32 bit single
floats, or ‘u32.8-’ for subtracting any number of supplied packs of 32
bit unsigned integers from the first supplied one, except in the case of
a single argument, where ‘u32.8-’ simply negates all values in the pack.

17.9.8 Rounding
---------------

For each floating-point SIMD data type ‘X.Y’ there are several functions
that round the values of a supplied SIMD pack to nearby floating-point
values whose fractional digits are all zero.  Those functions are
‘X.Y-round’, ‘X.Y-floor’, ‘X.Y-ceiling’, and ‘X.Y-truncate’, and they
have the same semantics as the one argument versions of ‘cl:round’,
‘cl:floor’, ‘cl:ceiling’, and ‘cl:truncate’, respectively.

17.9.9 Comparisons
------------------

For each SIMD data type ‘X.Y’, there exist conversion functions ‘X.Y<’,
‘X.Y<=’, ‘X.Y>’, ‘X.Y>=’, and ‘X.Y=’ that check whether the supplied
arguments are strictly monotonically increasing, monotonically
increasing, strictly monotonically decreasing, monotonically decreasing,
equal, or nowhere equal, respectively.  In contrast to the Common Lisp
functions ‘<’, ‘<=’, ‘>’, ‘>=’, ‘=’, and ‘/=’ the SIMD comparison
functions don't return a generalized boolean, but a SIMD pack of
unsigned integers with ‘Y’ elements.  The bits of each unsigned integer
are either all one, if the values of the arguments at that position
satisfy the test, or all zero, if they don't.  We call a SIMD packs of
such unsigned integers a mask.

17.9.10 Conditionals
--------------------

The SIMD paradigm is inherently incompatible with fine-grained control
flow.  A piece of code containing an ‘if’ special form cannot be
vectorized in a straightforward way, because doing so would require as
many instruction pointers and processor states as there are values in
the desired SIMD data type.  Instead, most SIMD instruction sets provide
an operator for selecting values from one of two supplied SIMD packs
based on a mask.  The mask is a SIMD pack with as many elements as the
other two arguments, but whose elements are unsigned integers whose bits
must be either all zeros or all ones.  This selection mechanism can be
used to emulate the effect of an ‘if’ special form, at the price that
both operands have to be computed each time.

   In ‘sb-simd’, all conditional operations and comparisons emit
suitable mask fields, and there is a ‘X.Y-if’ function for each SIMD
data type with element type ‘X’ and number of elements ‘Y’ whose first
arguments must be a suitable mask, whose second and third argument must
be objects that can be converted to the SIMD data type ‘X.Y’, and that
returns a value of type ‘X.Y’ where each element is from the second
operand if the corresponding mask bits are set, and from the third
operand if the corresponding mask bits are not set.

17.9.11 Loads and Stores
------------------------

In practice, a SIMD pack ‘X.Y’ is usually not constructed by calling its
constructor, but by loading ‘Y’ consecutive elements from a specialized
array with element type ‘X’.  The functions for doing so are called
‘X.Y-aref’ and ‘X.Y-row-major-aref’, and have similar semantics as
Common Lisp's ‘aref’ and ‘row-major-aref’.  In addition to that, some
instruction sets provide the functions ‘X.Y-non-temporal-aref’ and
‘X.Y-non-temporal-row-major-aref’, for accessing a memory location
without loading the referenced values into the CPU's cache.

   For each function ‘X.Y-foo’ for loading SIMD packs from an array,
there also exists a corresponding function ‘(setf X.Y-foo)’ for storing
a SIMD pack in the specified memory location.  An exception to this rule
is that some instruction sets (e.g., SSE) only provide functions for
non-temporal stores, but not for the corresponding non-temporal loads.

   One difficulty when treating the data of a Common Lisp array as a
SIMD pack is that some hardware instructions require a particular
alignment of the address being referenced.  Luckily, most architectures
provide instructions for unaligned loads and stores that are, at least
on modern CPUs, not slower than their aligned equivalents.  So by
default we translate all array references as unaligned loads and stores.
An exception are the instructions for non-temporal loads and stores,
that always require a certain alignment.  We do not handle this case
specially, so without special handling by the user, non-temporal loads
and stores will only work on certain array indices that depend on the
actual placement of that array in memory.

17.9.12 Specialized Scalar Operations
-------------------------------------

Finally, for each SIMD function ‘X.Y-OP’ that applies a certain
operation ‘OP’ element-wise to the ‘Y’ elements of type ‘X’, there
exists also a functions ‘X-OP’ for applying that operation only to a
single element.  For example, the SIMD function ‘f64.4+’ has a
corresponding function ‘f64+’ that differs from ‘cl:+’ in that it only
accepts arguments of type double float, and that it adds its supplied
arguments in a fixed order that is the same as the one used by ‘f64.4’.

   There are good reasons for exporting scalar functions from a SIMD
library, too.  The most obvious one is that they obey the same naming
convention and hence make it easier to locate the correct functions.
Another benefit is that the semantics of each scalar operation is
precisely the same as that of the corresponding SIMD function, so they
can be used to write reference implementations for testing.  A final
reason is that these scalar functions can be used to simplify the life
of tools for automatic vectorization.

17.9.13 Instruction Set Dispatch
--------------------------------

One challenge that is unique to image-based programming systems such as
Lisp is that a program can run on one machine, be dumped as an image,
and then resumed on another machine.  While nobody expects this feature
to work across machines with different architectures, it is quite likely
that the machine where the image is dumped and the one where execution
is resumed provide different instruction set extensions.

   As a practical example, consider a game developer that develops
software on an x86-64 machine with all SIMD extensions up to AVX2, but
then dumps it as an image and ships it to a customer whose machine only
supports SIMD extensions up to SSE2.  Ideally, the image should contain
multiple optimized versions of all crucial functions, and dynamically
select the most appropriate version based on the instruction set
extensions that are actually available.

   This kind of run time instruction set dispatch is explicitly
supported by means of the ‘instruction-set-case’ macro.  The code
resulting from an invocation of this macro compiles to an efficient jump
table whose index is recomputed on each startup of the Lisp image.

18 Deprecation
**************

In order to support evolution of interfaces in SBCL as well as in user
code, SBCL allows declaring functions, variables and types as
deprecated.  Users of deprecated things are notified by means of
warnings while the deprecated thing in question is still available.

   This chapter documents the interfaces for being notified when using
deprecated thing and declaring things as deprecated, the deprecation
process used for SBCL interfaces, and lists legacy interfaces in various
stages of deprecation.

   “Deprecation” in this context should not be confused with those
things the ANSI Common Lisp standard calls “deprecated”: the entirety of
ANSI CL is supported by SBCL, and none of those interfaces are subject
to censure.

18.1 Why Deprecate?
===================

While generally speaking we try to keep SBCL changes as backwards
compatible as feasible, there are situations when existing interfaces
are deprecated:

   • *Broken Interfaces*

     Sometimes it turns out that an interface is sufficiently
     misdesigned that fixing it would be worse than deprecating it and
     replacing it with another.

     This is typically the case when fixing the interface would change
     its semantics in ways that could break user code subtly: in such
     cases we may end up considering the obvious breakage caused by
     deprecation to be preferable.

     Another example are functions or macros whose current signature
     makes them hard or impossible to extend in the future: backwards
     compatible extensions would either make the interface intolerably
     hairy, or are sometimes outright impossible.

   • *Internal Interfaces*

     SBCL has several internal interfaces that were never meant to be
     used in user code - or at least never meant to be used in user code
     unwilling to track changes to SBCL internals.

     Ideally we'd like to be free to refactor our own internals as we
     please, without even going through the hassle of deprecating
     things.  Sometimes, however, it turns out that our internal
     interfaces have several external users who aren't using them
     advisedly, but due to misunderstandings regarding their status or
     stability.

     Consider a deprecated internal interface a reminder for SBCL
     maintainers not to delete the thing just yet, even though it is
     seems unused - because it has external users.

     When internal interfaces are deprecated we try our best to provide
     supported alternatives.

   • *Aesthetics & Ease of Maintenance*

     Sometimes an interface isn't broken or internal, but just
     inconsistent somehow.

     This mostly happens only with historical interfaces inherited from
     CMUCL which often haven't been officially supported in SBCL before,
     or with new extensions to SBCL that haven't been around for very
     long in the first place.

     The alternative would be to keep the suboptimal version around
     forever, possibly alongside an improved version.  Sometimes we may
     do just that, but because every line of code comes with a
     maintenance cost, sometimes we opt to deprecate the suboptimal
     version instead: SBCL doesn't have infinite developer resources.

     We also believe that sometimes cleaning out legacy interfaces helps
     keep the whole system more comprehensible to users, and makes
     introspective tools such as ‘apropos’ more useful.

18.2 The Deprecation Pipeline
=============================

SBCL uses a “deprecation pipeline” with multiple stages: as time goes
by, deprecated things move from earlier stages of deprecation to later
stages before finally being removed.  The intention is making users
aware of necessary changes early but allowing a migration to new
interfaces at a reasonable pace.

   Deprecation proceeds in three stages, each lasting approximately a
year.  In some cases it might move slower or faster, but one year per
stage is what we aim at in general.  During each stage warnings (and
errors) of increasing severity are signaled, which note that the
interface is deprecated, and point users towards any replacements when
applicable.

  1. *Early Deprecation*

     During early deprecation the interface is kept in working
     condition.  However, when a thing in this deprecation stage is
     used, an ‘sb-ext:early-deprecation-warning’, which is a
     ‘style-warning’, is signaled at compile-time.

     The internals may change at this stage: typically because the
     interface is re-implemented on top of its successor.  While we try
     to keep things as backwards-compatible as feasible (taking
     maintenance costs into account), sometimes semantics change
     slightly.

     For example, when the spinlock API was deprecated, spinlock objects
     ceased to exist, and the whole spinlock API became a synonym for
     the mutex API - so code using the spinlock API continued working,
     but silently switched to mutexes instead.  However, if someone
     relied on

     ‘(typep lock 'spinlock)’

     returning ‘NIL’ for a mutexes, trouble could ensue.

  2. *Late Deprecation*

     During late deprecation the interface remains as it was during
     early deprecation, but the compile-time warning is upgraded: when a
     thing in this deprecation stage is used, a
     ‘sb-ext:late-deprecation-warning’, which is a full ‘warning’, is
     signaled at compile-time.

  3. *Final Deprecation*

     During final deprecation the symbols still exist.  However, when a
     thing in this deprecation stage is used, a
     ‘sb-ext:final-deprecation-warning’, which is a full ‘warning’, is
     signaled at compile-time and an ‘error’ is signaled at run-time.

  4. *After Final Deprecation*

     The interface is deleted entirely.

18.3 Deprecation Conditions
===========================

‘sb-ext:deprecation-condition’ is the superclass of all
deprecation-related warning and error conditions.  All common slots and
readers are defined in this condition class.

 -- Condition: deprecation-condition
     Class precedence list: ‘deprecation-condition’, ‘condition’, ‘t’

     Superclass for deprecation-related error and warning conditions.

 -- Condition: early-deprecation-warning
     Class precedence list: ‘early-deprecation-warning’,
     ‘style-warning’, ‘warning’, ‘deprecation-condition’, ‘condition’,
     ‘t’

     This warning is signaled when the use of a variable, function,
     type, etc.  in ‘:early’ deprecation is detected at compile-time.
     The use will work at run-time with no warning or error.

 -- Condition: late-deprecation-warning
     Class precedence list: ‘late-deprecation-warning’, ‘warning’,
     ‘deprecation-condition’, ‘condition’, ‘t’

     This warning is signaled when the use of a variable, function,
     type, etc.  in ‘:late’ deprecation is detected at compile-time.
     The use will work at run-time with no warning or error.

 -- Condition: final-deprecation-warning
     Class precedence list: ‘final-deprecation-warning’, ‘warning’,
     ‘deprecation-condition’, ‘condition’, ‘t’

     This warning is signaled when the use of a variable, function,
     type, etc.  in ‘:final’ deprecation is detected at compile-time.
     An error will be signaled at run-time.

 -- Condition: deprecation-error
     Class precedence list: ‘deprecation-error’, ‘error’,
     ‘serious-condition’, ‘deprecation-condition’, ‘condition’, ‘t’

     This error is signaled at run-time when an attempt is made to use a
     thing that is in ‘:final’ deprecation, i.e.  call a function or
     access a variable.

18.4 Introspecting Deprecation Information
==========================================

The deprecation status of functions and variables can be inspected using
the ‘sb-cltl2:function-information’ and ‘sb-cltl2:variable-information’
functions provided by the ‘sb-cltl2’ contributed module.

18.5 Deprecation Declaration
============================

The ‘sb-ext:deprecated’ declaration can be used to declare objects in
various namespaces(1) as deprecated.

 -- Declaration: deprecated

     Syntax:
          sb-ext:deprecated stage since {object-clause}*

          stage ::= {:early | :late | :final}

          since ::= {VERSION | (SOFTWARE VERSION)}

          object-clause ::= (namespace NAME [:replacement REPLACEMENT])

          namespace ::= {cl:variable | cl:function | cl:type}

     were NAME is the name of the deprecated thing, VERSION and SOFTWARE
     are strings describing the version in which the thing has been
     deprecated and REPLACEMENT is a name or a list of names designating
     things that should be used instead of the deprecated thing.

     Currently the following namespaces are supported:

     ‘cl:function’
          Declare functions, compiler-macros or macros as deprecated.

               note: When declaring a function to be in ‘:final’
               deprecation, there should be no actual definition of the
               function as the declaration emits a stub function that
               signals a ‘sb-ext:deprecation-error’ at run-time when
               called.

     ‘cl:variable’
          Declare special and global variables, constants and
          symbol-macros as deprecated.

               note: When declaring a variable to be in ‘:final’
               deprecation, there should be no actual definition of the
               variable as the declaration emits a symbol-macro that
               signals a ‘sb-ext:deprecation-error’ at run-time when
               accessed.

     ‘cl:type’
          Declare named types (i.e.  defined via ‘deftype’), standard
          classes, structure classes and condition classes as
          deprecated.

   ---------- Footnotes ----------

   (1) See "namespace" entry in the glossary of the Common Lisp
Hyperspec.

18.6 Deprecation Examples
=========================

Marking functions as deprecated:
     (defun foo ())
     (defun bar ())
     (declaim (deprecated :early ("my-system" "1.2.3")
                          (function foo :replacement bar)))

     ;; Remember: do not define the actual function or variable in case of
     ;; :final deprecation:
     (declaim (deprecated :final ("my-system" "1.2.3")
                          (function fez :replacement whoop)))

Attempting to use the deprecated functions:
     (defun baz ()
       (foo))
     | STYLE-WARNING: The function CL-USER::FOO has been deprecated...
     => BAZ
     (baz)
     => NIL ; no error

     (defun danger ()
       (fez))
     | WARNING: The function CL-USER::FEZ has been deprecated...
     => DANGER
     (danger)
     |- ERROR: The function CL-USER::FEZ has been deprecated...

18.7 Deprecated Interfaces in SBCL
==================================

This sections lists legacy interfaces in various stages of deprecation.

18.7.1 List of Deprecated Interfaces
------------------------------------

18.7.1.1 Early Deprecation
..........................

   • *SOCKINT::WIN32-**

     Deprecated in favor of the corresponding prefix-less functions
     (e.g.  ‘sockint::bind’ replaces ‘sockint::win32-bind’) as of 1.2.10
     in March 2015.  Expected to move into late deprecation in August
     2015.

   • *SB-UNIX:UNIX-EXIT*

     Deprecated as of 1.0.56.55 in May 2012.  Expected to move into late
     deprecation in May 2013.

     When the SBCL process termination was refactored as part of changes
     that led to ‘sb-ext:quit’ being deprecated, ‘sb-unix:unix-exit’
     ceased to be used internally.  Since ‘SB-UNIX’ is an internal
     package not intended for user code to use, and since we're slowly
     in the process of refactoring things to be less Unix-oriented,
     ‘sb-unix:unix-exit’ was initially deleted as it was no longer used.
     Unfortunately it became apparent that it was used by several
     external users, so it was re-instated in deprecated form.

     While the cost of keeping ‘sb-unix:unix-exit’ indefinitely is
     trivial, the ability to refactor our internals is important, so its
     deprecation was taken as an opportunity to highlight that ‘SB-UNIX’
     is an internal package and ‘SB-POSIX’ should be used by
     user-programs instead - or alternatively calling the foreign
     function directly if the desired interface doesn't for some reason
     exist in ‘SB-POSIX’.

     *Remedy*

     For code needing to work with legacy SBCLs, use e.g.  ‘system-exit’
     as show above in remedies for ‘sb-ext:quit’.  In modern SBCLs
     simply call either ‘sb-posix:exit’ or ‘sb-ext:exit’ with
     appropriate arguments.

   • *SB-C::MERGE-TAIL-CALLS Compiler Policy*

     Deprecated as of 1.0.53.74 in November 2011.  Expected to move into
     late deprecation in November 2012.

     This compiler policy was never functional: SBCL has always merged
     tail calls when it could, regardless of this policy setting.  (It
     was also never officially supported, but several code-bases have
     historically used it.)

     *Remedy*

     Simply remove the policy declarations.  They were never necessary:
     SBCL always merged tail-calls when possible.  To disable tail
     merging, structure the code to avoid the tail position instead.

   • *Spinlock API*

     Deprecated as of 1.0.53.11 in August 2011.  Expected to move into
     late deprecation in August 2012.

     Spinlocks were an internal interface, but had a number of external
     users and were hence deprecated instead of being simply deleted.

     Affected symbols: ‘sb-thread::spinlock’,
     ‘sb-thread::make-spinlock’, ‘sb-thread::with-spinlock’,
     ‘sb-thread::with-recursive-spinlock’, ‘sb-thread::get-spinlock’,
     ‘sb-thread::release-spinlock’, ‘sb-thread::spinlock-value’, and
     ‘sb-thread::spinlock-name’.

     *Remedy*

     Use the mutex API instead, or implement spinlocks suiting your
     needs on top of ‘sb-ext:compare-and-swap’, ‘sb-ext:spin-loop-hint’,
     etc.

   • *SOCKINT::HANDLE->FD*, *SOCKINT::FD->HANDLE*

     Internally deprecated in 2012.  Declared deprecated as of 1.2.10 in
     March 2015.  Expected to move into final deprecation in August
     2015.

18.7.1.2 Late Deprecation
.........................

   • *SB-THREAD:JOIN-THREAD-ERROR-THREAD and
     SB-THREAD:INTERRUPT-THREAD-ERROR-THREAD*

     Deprecated in favor of ‘sb-thread:thread-error-thread’ as of
     1.0.29.17 in June 2009.  Expected to move into final deprecation in
     June 2012.

     *Remedy*

     For code that needs to support legacy SBCLs, use e.g.:

          (defun get-thread-error-thread (condition)
            #+#.(cl:if (cl:find-symbol "THREAD-ERROR-THREAD" :sb-thread)
                       '(and) '(or))
            (sb-thread:thread-error-thread condition)
            #-#.(cl:if (cl:find-symbol "THREAD-ERROR-THREAD" :sb-thread)
                       '(and) '(or))
            (etypecase condition
             (sb-thread:join-thread-error
              (sb-thread:join-thread-error-thread condition))
             (sb-thread:interrupt-thread-error
              (sb-thread:interrupt-thread-error-thread condition))))

   • *SB-INTROSPECT:FUNCTION-ARGLIST*

     Deprecated in favor of ‘sb-introspect:function-lambda-list’ as of
     1.0.24.5 in January 2009.  Expected to move into final deprecation
     in January 2012.

     Renamed for consistency and aesthetics.  Functions have
     lambda-lists, not arglists.

     *Remedy*

     For code that needs to support legacy SBCLs, use e.g.:

          (defun get-function-lambda-list (function)
            #+#.(cl:if (cl:find-symbol "FUNCTION-LAMBDA-LIST" :sb-introspect)
                       '(and) '(or))
            (sb-introspect:function-lambda-list function)
            #-#.(cl:if (cl:find-symbol "FUNCTION-LAMBDA-LIST" :sb-introspect)
                       '(and) '(or))
            (sb-introspect:function-arglist function))

   • *Stack Allocation Policies*

     Deprecated in favor of ‘sb-ext:*stack-allocate-dynamic-extent*’ as
     of 1.0.19.7 in August 2008, and are expected to be removed in
     August 2012.

     Affected symbols: ‘sb-c::stack-allocate-dynamic-extent’,
     ‘sb-c::stack-allocate-vector’, and
     ‘sb-c::stack-allocate-value-cells’.

     These compiler policies were never officially supported, and turned
     out the be a flawed design.

     *Remedy*

     For code that needs stack-allocation in legacy SBCLs,
     conditionalize using:

          #-#.(cl:if (cl:find-symbol "*STACK-ALLOCATE-DYNAMIC-EXTENT*" :sb-ext)
                     '(and) '(or))
          (declare (optimize sb-c::stack-allocate-dynamic-extent))

     However, unless stack allocation is essential, we recommend simply
     removing these declarations.  Refer to documentation on
     ‘sb-ext:*stack-allocate-dynamic*’ for details on stack allocation
     control in modern SBCLs.

   • *SB-SYS:OUTPUT-RAW-BYTES*

     Deprecated as of 1.0.8.16 in June 2007.  Expected to move into
     final deprecation in June 2012.

     Internal interface with some external users.  Never officially
     supported, deemed unnecessary in presence of ‘write-sequence’ and
     bivalent streams.

     *Remedy*

     Use streams with element-type ‘(unsigned-byte 8)’ or ‘:default’ -
     the latter allowing both binary and character IO - in conjunction
     with ‘write-sequence’.

18.7.1.3 Final Deprecation
..........................

No interfaces are currently in final deprecation.

18.7.2 Historical Interfaces
----------------------------

The following is a partial list of interfaces present in historical
versions of SBCL, which have since then been deleted.

   • *SB-KERNEL:INSTANCE-LAMBDA*

     Historically needed for CLOS code.  Deprecated as of 0.9.3.32 in
     August 2005.  Deleted as of 1.0.47.8 in April 2011.  Plain ‘lambda’
     can be used where ‘sb-kernel:instance-lambda’ used to be needed.

   • *SB-ALIEN:DEF-ALIEN-ROUTINE, SB-ALIEN:DEF-ALIEN-VARIABLE,
     SB-ALIEN:DEF-ALIEN-TYPE*

     Inherited from CMUCL, naming convention not consistent with
     preferred SBCL style.  Deprecated as of 0.pre7.90 in December 2001.
     Deleted as of 1.0.9.17 in September 2007.  Replaced by
     ‘sb-alien:define-alien-routine’, ‘sb-alien:define-alien-variable’,
     and ‘sb-alien:define-alien-type’.