When I first started on this assignment, I thought it would be very challenging. I had done a similar assignment previously using SUNOS and found it quite difficult. The good news is that SOLARIS provides a much better API for getting this job done, so the project is not quite as difficult as I first thought. Since that's the case, I specified a couple of extra things you need to do, just to make it interesting.
Threads are creating using the GThread_create function. The three parameters specified there should be self explanatory. There should be no pre-set limit in your gthreads regarding how many threads can be created, so don't pre-allocate some fixed amount of space for handling threads. Also, "create" does NOT schedule the thread immediately! It just creates it, and it is scheduled later when a thread is being pre-empted or the current thread is yielding.
Threads may call "GThread_yield" to voluntarily give up the CPU to another thread. The code for yield should just select another ready thread and transfer control to that thread at the last point in it's execution path.
Threads MUST call GThread_exit before terminating. This actually makes our job a bit easier, since you don't have to worry about what to do if a thread's "StartFunc" just exits (which pthreads allows).
You should maintain a count of active threads, and return that count in response to a "GThread_count" call. The testgt.c program will use this extensively to know when all threads have completed.
One other important point. The main program is also a thread, and should be scheduled just like all the other threads. In other words, I expect the main program of testgt.c to be pre-empted just like any other thread, and it may also call GThread_yield to yield.
GTMutex_create is called to initialize a mutex to the default "unlocked" value. GT_MUTEX is defined as a void* in gthreads.h, but of course you will make a structure of you own choosing to use for mutexes, and do a type cast to the right type.
GTMutex_lock, GTMutex_unlock and GTMutex_islocked should be self-explanatory. However, to make it more interesting, we specify the following two requirements. DO NOT SPIN waiting for a lock to free up. Instead, if a thread asks for a lock that is not available, de-schedule that thread, making a note of the mutex that it is waiting on. When the mutex is freed, re-schedule that thread (you can either schedule it immediately, or note that it is a candidate for later scheduling). Second, we will require that only the thread that locked a mutex can unlock it. In other words, if any thread other than the one that locked a mutex tries to unlock it, do not unlock it and return GT_FAILED instead.
For each mutex, keep track of the successful and unsuccessful lock attempts. testgt.c will use these values to insure things are working right.
To implement the Mutex, use the Sparc "swap" instuction. It's easy to include a small piece of assembly language code in your C program using the "asm" macro.
| Test 1, GThread_yield testing | 30% |
| Test 2, Pre-emptive Multitasking testing | 30% |
| Test 3, Proper operation and scheduling of Mutexes | 20% |
| Test 4, Proper ownership tracking of Mutexes | 10% |
| Quality of Code (Neatness, commenting, etc) | 10% |
mail rly@cc < gthreads.c