GeSHi © 2004, Nigel McNie.
/* NAME : Thomas Stout User ID: tstout
/* DUE DATE : 12/9/2005
/* PROGRAM ASSIGNMENT : mini-project
/* FILE NAME : README
/* --------------------------------------------------------- */
Explain how each thread obtains its stack space.
For both versions, the program first calculates by what value the stack pointer
should be changed to reserve the requested amount of stack space for the thread.
Next, it passes this value on to the function THREAD_INIT(), this function has
different versions depending on what platform the system is running on.
First, the program executes a setjmp() to save the current threads context.
Next, the program moves the value of the stack pointer by the value that is
passed in to the function. Then, the stack pointer is manually moved,
reserving the space that it was moved past as the stack space for the new
thread. Next, a setjmp() is called to save the current context to be used by
the newly created thread. Then a longjmp() is used to cause the original
thread to continue exectution. When the context that was saved for the new
thread is eventually loaded, the thread will call THREAD_WRAP(), which will
cause its function to run.
In Linux, the altered value for the stack pointer can be directly written to
the jump_buf context of the new process. Since this can be done directly,
there is no need for the linux version to use assembly instructions to move
the stack pointer and then call setjmp() to save the value to the jump_buf.
The adderss of THREAD_WRAP() is also written directly into the program
counter stored in the jump_buf, so that that function will be run when the
thread is resumed with a call to longjmp().
When a longjmp() is eventually called that points the jump_buf that stores the
context of the new process, the process will be loaded in with the modified
value of the stack pointer, preserving this threads stack space.
Why is the call to function THREAD_WRAP() necessary?
The call to THREAD_WRAP() is used to cause the thread to run the appropriate
function the first time that its jump_buf is used to restore the threads
context. The THREAD_WRAP() function is the first function executed when a new
thread is resumed, regardless of the platform that the thread system is running
How does this system perform context switching?
This system performs context switching using setjmp() and longjmp(). A jump_buf
is stored for each thread, storing the threads current context. This allows for
the calls to THREAD_SCHEDULER() to perform a SaveEnvironment (setjmp) to save a
threads context, and perform a RestoreEnvironment (longjmp) to restore the
threads context. This system doesn't suffer from the problems of corrupted
stacks, like setjmp() and longjmp() usually would, because the values of the
stack pointers that are stored in the jump_bufs are altered when the thread is
initially created, to make sure that the thread has its own stack space.
Why is this system using a non-preemptive scheduling policy? Suggest a way of
using a preemptive scheduling policy.
The system is using a non-preemptive scheduling policy because this ensures that
the portions of code in the semaphores and mutex locks that must be atomic will
not be interupted by a context switch. The system could be converted to a
preemptive system by using a timer. If the timer was set up to cause an
interrupt at regular intervals, the interrupt handler for this timer could make
a call to the THREAD_SCHEDULER() function, which would cause a new process to be
switched in. Before calling THREAD_SCHEDULER(), the interrupt handler would
have to place the currently executing thread back into the ready queue, so that
the thread could be run again at a later time.
A detailed description of your implementation of THREAD_JOIN()
For THREAD_JOIN(), first the function makes sure that the thread that they wish
to join with is a valid thread that has not already been terminated. If it is a
running thread, then the function adds the caller to the JoinList queue of the
thread they wish to join, changes the callers status the joining, and runs the
thread scheduler to select a new thread to run.
A detailed description of your implementation of THREAD_SUSPEND()
First, the function makes sure that the thread to be suspended is a valid thread
that is not already suspended. Next, it removes the thread to be suspended from
the ready queue. After that, it adds the thread to the suspended queue and
changes the threads status to suspended. Finally, it checks to see if the
thread that was suspended was the currently executing one. If it was, it calls
the thread scheduler to select a new thread to run.
A detailed description of your implementation of THREAD_RESUME()
First, the function makes sure thta the thread to be resumed is a valid thread
and that it is suspended. Next, it removes the suspened thread from the suspend
queue. Finally, it adds the thread to the ready queue and changes its status to
A detailed description of your implementation of smokers-sem.c
This program uses semaphores to solve the smokers problem. The following
semaphores a used by the program:
smokers - An 2 dimensional array of semaphores, the first dimension has three
entries, one for each smoker. The second dimension has two entries
one for each ingredient the smoker needs.
table - A 1 dimensional array of semaphores with three entries, one for
There are three smoker threads created and one agent thread. The smokers all
wait on their own semaphores for the agent to give them the ingredients they
need to make a cigarette. After the agent gives out ingredients, it waits on
the table semaphores for the ingredients that it just gave away to be given back
by the smokers. Once the ingredients are given back, the agent gives away two
ingredients again to another smoker.
A detailed description of your implementation of exchange.c
This program uses channels to allow for the sorter threads to communicate with
each other. There is a seperate channel used for each direction for the threads
communication. This is done so that one thread doesn't receive its own message.
The threads all compare the numbers they are holding, and pass the numbers
either left or right based on the sorting algorithm. Upon receiving the new
numbers from their neighbor, each thread updates the numbers they are holding.
The only threads that do not communicate with two neighbors are threads 0 and 4.
Thread zero only talks to thread 1 and thread 4 only talks to thread 3, this
ensures that the sorting algorithm will force the lowest numbers to go down to
thread 0 and force the highest numbers to go up to thread 4.
A detailed description of your implementation of ring-leader.c
This program creates N threads with N communication channels that are used for
passing information between the threads. Each thread is given a random UID when
the program starts, and then the leader election algorithm is run, selecting the
thread with the highest UID to be the leader. Threads continuosly pass messages
between each other, representing the highest known UID in the network. Once the
message gets all the back to the original sender, so that a thread is notified
that the highest known UID is their own UID, that thread becomes the leader and
starts circulating the END message, ending the program.