F06 Assignment Specification | |
Dr. Bennet |
void th_init(void)
Initialize the package. The threaded program must
call this function first.
This allows the library to perform any needed initialization.
One essential job of th_init
is to record the initial thread,
the one provided by the process running the program, so it can be
scheduled along with the ones created by the package.
th_id_t th_fork();
This is modeled after the Unix fork()
call for creating processes.
A th_fork()
call creates a new thread and returns twice,
once in the original thread (the parent) and once in
the new thread
(the child). In the parent, it returns the thread id of the child. In the
child, it returns the symbolic constant ARE_CHILD
. The package
must define
ARE_CHILD
such that it is not the identifier of
any actual thread.
When a thread calls th_fork()
, the library creates a child thread
with a new stack containing a copy of the caller's topmost stack frame,
including up to five parameters.
The child thread is initially suspended, and
th_fork()
returns to the parent. The
th_fork()
will return in the child thread later, whenever it is
selected to be run. The parent thread retains its same stack, and does
not yield the CPU. If the child thread returns from the function which
called th_fork()
, it is equivalent to the thread performing a
th_exit(0)
. A parent's return from this function behaves normally.
The return type, th_id_t
, must be defined by the package.
It is usually an integer or a void pointer, depending on the
data structures used in the implementation.
th_yield(void)
The current thread yields use of the CPU itself. If there are no other ready threads, this returns immediately in the calling thread. Otherwise, the caller is placed at the end of the ready queue and the thread at the head of the queue receives control.
The thread exits. Its return value is i, which can be recovered
using th_wait
.
The caller terminates the thread designated by t. It will be
assigned the exit value given by i as though it had performed
exit(
i)
. A thread may terminate itself, which
is equivalent to performing a th_exit
. It is an error to
kill a thread which has already terminated.
The calling thread waits for another thread indicated by t.
The value of t must have been returned by an earlier th_fork
.
If that thread has already exited, th_wait
immediately returns the
exit value from the thread t. If not, the caller is suspended and
the next ready thread is started. If there are no ready threads,
the entire program exits with an error message. When t
finishes, the waiting thread is made ready and
moved to the end of the ready queue.
Later, it will be resumed, and
th_wait
will return the exit value from t.
Each thread created by th_create
should be th_wait
ed on
by exactly one other thread. If no one waits, then space
allocated for the thread's stack may not be reclaimed. The results
of having a thread th_wait
ed by more than one other are undefined.
th_id_t th_me()
Return the id of the calling thread.
Set the size in bytes of stack space allocated for all successive
th_fork
calls. It returns the old size. The symbolic constant
DEF_STACK_SIZE
gives the default size used when th_stksize
has
not been called.
The main thread that the process starts with cannot be terminated.
Any attempt to do so is an error and should terminate the entire
process. It does have a thread id (at least, after
th_init
is called), and other threads can wait on it.
It will be a long wait, though.