Bare-Bones threads package v0.3.

Assembled by Christopher Neufeld on May 31, 1996, inspired by the
excellent work of Wolfram Gloger (Gloger@lrz.uni-Muenchen.de), Linus
Torvalds, and Alan Cox.



This is a very basic bare-bones threading package which has been tested
on both single-CPU and SMP Linux boxes. It spawns extra processes for the
extra threads, so that full use can be made of all CPUs on the system. To
run on an SMP system you must compile bb_threads.c with the __SMP__ macro
defined.

You should find the following files:

README            -  this file
bb_threads.c      -  the threading subroutines
bb_threads.h      -  prototypes for the exported symbols from bb_threads.c
demo.c            -  a sample program using the threading
demo2.c		  -  a demonstration of separate signal handling
makefile          -  a simple makefile



The demo program shows all aspects of the code.


The typical use of the code will be as follows:

An enumerated list of mutex locks is created. You are allowed to have
up to 1024 separate locks (or change MAX_MUTEXES in bb_threads.c for
as many as you like). The more you create, the finer your control over
the locking of critical code. There is no performance penalty for
using a larger number of mutex locks, so be generous. (Note that there
is no mutex starvation protection here, it is entirely possible for
one thread to monopolize a mutex to the detriment of other threads.)

The stack size required by the spawned threads is estimated, and
passed to the function bb_threads_stacksize(). This subroutine must be
called before any threads are spawned, but may be called again with
new values of the stack size between calls.

Optionally, one can call bb_threads_shared_sighandlers(ARG), where ARG is
either zero or non-zero. If zero, subsequently spawned threads do not
share changes to their signal handlers. If non-zero, a change in the
signal action in one thread affects the signal behaviour of other
threads. This latter behaviour is the default, for backward
compatibility. While one can change the behaviour from one state to the
other in a running program, note that the state variable set by this call
is shared among all existing threads, so changing the state affects any
new thread creation call, in any running thread.

All of the mutexes used are initialized with bb_threads_mutexcreate()
before first use. Typically, in a loop over the enumerated list during
initialization of the program. 

The function which will serve as the entry point to the thread is
written. This function must be of type:
void f(void *args, size_t len)
Arguments will typically be passed by a pointer to a structure, or to
a single parameter if the function requires only one. The second
argument is a dummy, used to avoid changing the original code.

A new thread is created with bb_threads_newthread(f, &arg).

Note, however, that a virtual memory leak will be present if the
calling thread does not wait on the spawned threads with something of
the form:
bb_threads_cleanup(wait(NULL));
In other words, a thread doesn't just exit. It becomes a zombie,
holding onto its stack space, until cleaned up with this function. It
is important that the wait() function not appear in any other context,
or the zombies will be disposed of without clearing their stack space,
leading to a virtual memory leak.

If the program generates legitimate child functions by fork()-ing, as
well as spawning threads, then the bb_threads_cleanup(wait(NULL)) call
will return a spurious error message, unless bb_threads.c is compiled
with the SILENT_FAIL_CLEANUP macro defined.

There are no other cleanup actions required on threads or mutexes. I
hope this is useful to people, and provides a starting point for more
detailed packages.



Notes on the demo program:

I chose the demo program to add a large number of random numbers
together in different threads. If the program is rerun several times,
each time the different threads will accumulate different totals
(since they call the random() function in a different order, and the
random() function has a global state variable which is common to all
threads). The grand total, however, remains constant. I have two
mutexes, one on the random number calculation and addition, and the
other on the final output on each thread.



Change Log:

v0.4  Oct  2, 1996:  Realized that the thread-spawning functions were not
		     thread-safe. (whoops). Fixed it.

v0.3  Aug 22, 1996:  Added the independent signal handler capability. Also,
		     included a more general makefile produced by Linas
		     Vepstas <linas@teleportal.com>

v0.2  Jun 13, 1996:  Fixed a bug whereby memory was freed before having
		     its mprotect bits cleared.

v0.1  May 31, 1996:  First working version released.
