\chapter{Threads}

The calls in this chapter can be used to put together runtime systems
for languages that support threads.
This threads package, like most thread packages, provides basic
functionality for creating threads, destroying threads, yielding, 
suspending, and awakening a suspended thread. In
addition, it provides facilities whereby you can write your own thread
schedulers.  

\section{Basic Thread Calls}

\function{typedef struct CthThreadStruct *CthThread;}
\index{CthThread}
\desc{This is an opaque type defined in {\tt converse.h}.  It represents
a first-class thread object.  No information is publicized about the
contents of a CthThreadStruct.}

\function{typedef void (CthVoidFn)();}
\index{CthVoidFn}
\desc{This is a type defined in {\tt converse.h}.  It represents
a function that returns nothing.}

\function{typedef CthThread (CthThFn)();}
\index{CthThFn}
\desc{This is a type defined in {\tt converse.h}.  It represents
a function that returns a CthThread.}

\function{CthThread CthSelf()}
\index{CthSelf}
\desc{Returns the currently-executing thread.  Note: even the initial
flow of control that inherently existed when the program began
executing {\tt main} counts as a thread.  You may retrieve that thread
object using {\tt CthSelf} and use it like any other.}

\function{CthThread CthCreate(CthVoidFn fn, void *arg, int size)}
\index{CthCreate}
\desc{Creates a new thread object.  The thread is not given control
yet.  To make the thread execute, you must push it into the
scheduler queue, using CthAwaken below.  When (and if) the thread
eventually receives control, it will begin executing the specified
function {\tt fn} with the specified argument.  The {\tt size}
parameter specifies the stack size in bytes, 0 means use the default
size.  Caution: almost all threads are created with CthCreate, but not
all.  In particular, the one initial thread of control that came into
existence when your program was first {\tt exec}'d was not created
with {\tt CthCreate}, but it can be retrieved (say, by calling {\tt
CthSelf} in {\tt main}), and it can be used like any other {\tt
CthThread}.}

\function{void CthFree(CthThread t)}
\index{CthFree}
\desc{Frees thread {\tt t}.  You may ONLY free the
currently-executing thread (yes, this sounds strange, it's
historical).  Naturally, the free will actually be postponed until the
thread suspends.  To terminate itself, a thread calls
{\tt CthFree(CthSelf())}, then gives up control to another thread.}

\function{void CthSuspend()}
\index{CthSuspend}
\desc{Causes the current thread to stop executing.
The suspended thread will not start executing again until somebody
pushes it into the scheduler queue again, using CthAwaken below.  Control
transfers to the next task in the scheduler queue.}

\function{void CthAwaken(CthThread t)}
\index{CthAwaken}
\desc{Pushes a thread into the scheduler queue.  Caution: a thread
must only be in the queue once.  Pushing it in twice is a crashable
error.}

\function{void CthAwakenPrio(CthThread t, int strategy, int priobits, int *prio)}
\index{CthAwakenPrio}
\desc{Pushes a thread into the scheduler queue with priority specified by 
{\tt priobits} and {\tt prio} and queueing strategy {\tt strategy}.  
Caution: a thread
must only be in the queue once.  Pushing it in twice is a crashable
error. {\tt prio} is not copied internally, and is used when the scheduler 
dequeues the message, so it should not be reused until then.}

\function{void CthYield()}
\index{CthYield}
\desc{This function is part of the scheduler-interface.  It simply
executes {\tt \{ CthAwaken(CthSelf()); CthSuspend(); \} }.  This combination
gives up control temporarily, but ensures that control will eventually
return.}

\function{void CthYieldPrio(int strategy, int priobits, int *prio)}
\index{CthYieldPrio}
\desc{This function is part of the scheduler-interface.  It simply
executes \\
{\tt\{CthAwakenPrio(CthSelf(),strategy,priobits,prio);CthSuspend();\}}\\
This combination
gives up control temporarily, but ensures that control will eventually
return.}

\function{CthThread CthGetNext(CthThread t)}
\index{CthGetNext}
\desc{Each thread contains space for the user to store a ``next'' field (the
functions listed here pay no attention to the contents of this field).
This field is typically used by the implementors of mutexes, condition
variables, and other synchronization abstractions to link threads
together into queues.  This function returns the contents of the next field.}

\function{void CthSetNext(CthThread t, CthThread next)}
\index{CthGetNext}
\desc{Each thread contains space for the user to store a ``next'' field (the
functions listed here pay no attention to the contents of this field).
This field is typically used by the implementors of mutexes, condition
variables, and other synchronization abstractions to link threads
together into queues.  This function sets the contents of the next field.}

\section{Thread Scheduling and Blocking Restrictions}

\converse{} threads use a scheduler queue, like any other threads
package.  We chose to use the same queue as the one used for \converse{}
messages (see section \ref{schedqueue}).  Because of this, thread
context-switching will not work unless there is a thread polling for
messages.  A rule of thumb, with \converse{}, it is best to have a thread
polling for messages at all times.  In \converse{}'s normal mode (see
section \ref{initial}), this happens automatically.  However, in
user-calls-scheduler mode, you must be aware of it.

There is a second caution associated with this design.  There is a
thread polling for messages (even in normal mode, it's just hidden in
normal mode).  The continuation of your computation depends on that
thread --- you must not block it.  In particular, you must not call
blocking operations in these places:

\begin{itemize}

\item{In the code of a \converse{} handler (see sections \ref{handler1}
and \ref{handler2}).}

\item{In the code of the \converse{} start-function (see section
\ref{initial}).}

\end{itemize}

These restrictions are usually easy to avoid.  For example, if you
wanted to use a blocking operation inside a \converse{} handler, you
would restructure the code so that the handler just creates a new
thread and returns.  The newly-created thread would then do the work
that the handler originally did.

\section{Thread Scheduling Hooks}

Normally, when you CthAwaken a thread, it goes into the primary
ready-queue: namely, the main \converse{} queue described in section
\ref{schedqueue}.  However, it is possible to hook a thread to make
it go into a different ready-queue.  That queue doesn't have to be
priority-queue: it could be FIFO, or LIFO, or in fact it could handle
its threads in any complicated order you desire.  This is a powerful
way to implement your own scheduling policies for threads.

To achieve this, you must first implement a new kind of ready-queue.
You must implement a function that inserts threads into this queue.
The function must have this prototype:

{\bf void awakenfn(CthThread t, int strategy, int priobits, int *prio);}

When a thread suspends, it must choose a new thread to transfer control
to.  You must implement a function that makes the decision: which thread
should the current thread transfer to.  This function must have this
prototype:

{\bf CthThread choosefn();}

Typically, the choosefn would choose a thread from your ready-queue.
Alternately, it might choose to always transfer control to a central
scheduling thread.

You then configure individual threads to actually use this new
ready-queue.  This is done using CthSetStrategy:

\function{void CthSetStrategy(CthThread t, CthAwkFn awakenfn, CthThFn choosefn)}
\index{CthSetStrategy}
\desc{Causes the thread to use the specified \param{awakefn} whenever
you CthAwaken it, and the specified \param{choosefn} whenever you
CthSuspend it.}

CthSetStrategy alters the behavior of CthSuspend and CthAwaken.
Normally, when a thread is awakened with CthAwaken, it gets inserted
into the main ready-queue.  Setting the thread's {\tt awakenfn} will
cause the thread to be inserted into your ready-queue instead.
Similarly, when a thread suspends using CthSuspend, it normally
transfers control to some thread in the main ready-queue.  Setting the
thread's {\tt choosefn} will cause it to transfer control to a thread
chosen by your {\tt choosefn} instead.

You may reset a thread to its normal behavior using CthSetStrategyDefault:

\function{void CthSetStrategyDefault(CthThread t)}
\index{CthSetStrategyDefault}
\desc{Restores the value of \param{awakefn} and \param{choosefn} to
their default values.  This implies that the next time you CthAwaken
the specified thread, it will be inserted into the normal ready-queue.}

Keep in mind that this only resolves the issue of how threads get into
your ready-queue, and how those threads suspend.  To actually make
everything ``work out'' requires additional planning: you have to make
sure that control gets transferred to everywhere it needs to go.

Scheduling threads may need to use this function as well:

\function{void CthResume(CthThread t)}
\index{CthResume}
\desc{Immediately transfers control to thread {\tt t}.  This routine is
primarily intended for people who are implementing schedulers, not for
end-users.  End-users should probably call {\tt CthSuspend} or {\tt
CthAwaken} (see below).  Likewise, programmers implementing locks,
barriers, and other synchronization devices should also probably rely
on {\tt CthSuspend} and {\tt CthAwaken}.}

A final caution about the {\tt choosefn}: it may only return a thread
that wants the CPU, eg, a thread that has been awakened using the {\tt
awakefn}.  If no such thread exists, if the {\tt choosefn} cannot
return an awakened thread, then it must not return at all: instead, it
must wait until, by means of some pending IO event, a thread becomes
awakened (pending events could be asynchonous disk reads, networked
message receptions, signal handlers, etc).  For this reason, many
schedulers perform the task of polling the IO devices as a side
effect.  If handling the IO event causes a thread to be awakened, then
the choosefn may return that thread.  If no pending events exist, then
all threads will remain permanently blocked, the program is therefore
done, and the {\tt choosefn} should call {\tt exit}.

There is one minor exception to the rule stated above (``the scheduler
may not resume a thread unless it has been declared that the thread
wants the CPU using the {\tt awakefn}'').  If a thread {\tt t} is part
of the scheduling module, it is permitted for the scheduling module to
resume {\tt t} whenever it so desires: presumably, the scheduling
module knows when its threads want the CPU.

\zap{
\function{void CthSetVar(CthThread t, void **var, void *val)}
\desc{Specifies that the global variable pointed to by {\tt
var} should be set to value {\tt val} whenever thread {\tt t} is
executing.  {\tt var} should be of type {\tt void *}, or at least
should be coercible to a {\tt void *}.  This can be used to associate
thread-private data with thread {\tt t}.

it is intended that this function be used as follows:}

\begin{alltt}
    /* User defines a struct th_info containing all the thread-private  */
    /* data he wishes to associate with threads.  He also defines       */
    /* a global variable 'current_thread_info' which will always hold   */
    /* the th_info of the currently-executing thread.                   */
    struct th_info \{ ... \} *current_thread_info;

    /* User creates a thread 't', and allocates a block of memory       */
    /* 'tinfo' to hold the thread's private data.  User tells the       */
    /* system that whenever thread 't' is running, the global variable  */
    /* 'current_thread_info' should be set to 'tinfo'.  Thus, thread    */
    /* 't' can access its private data just by dereferencing            */
    /* 'current_thread_info'.                                           */
    t = CthCreate( ... );
    tinfo = (struct th_info *)malloc(sizeof(struct th_info));
    CthSetVar(t, &current_thread_info, tinfo);
\end{alltt}

\desc{Note: you can use CthSetVar multiple times on a thread, thereby
attaching multiple data items to it.  However, each data item slows
down context-switch to that thread by a tiny amount.  Therefore, a
module should ideally attach no more than one data item to a thread.
We allow multiple data items to be attached so that independent
modules can attach data to a thread without interfering with each
other.}

\function{void *CthGetVar(CthThread t, void **var)}
\desc{This makes it possible to retrieve values previously stored with
{\tt CthSetVar} when {\tt t} is {\it not} executing.  Returns the value
that {\tt var} will be set to when {\tt t} is running.}
}
