MyThread library
- Duration: 16th - 18th Sept 2009
- Languages used: C++ (with inline GNU assembly code)
- Platform: Linux 2.6 (80386 arch, for simplicity during context switches)
Brief
MyThread library is a simple user-thread library I wrote for self-interest during my Bachelors, to demonstrate the "Many to One" multithreading model.
Details
My thread library implements the "Many to One" model. Note that the PThread and Solaris thread libraries implement the other two threading models: "One to One" and "Many to Many". We can also implement the last two models, but those are a lot more challenging, since the global threading structures must be protected by synchronisation (using SIGUSR1, SIGUSR2, or using semaphores). The last 2 models can use the powerful clone()
system call available in Linux.
I studied the 3 threading models while reading the Dinosaur book, but I just had a vague understanding of how they are implemented. I knew how to do context switching (The MINIX book), and how to use UNIX interval timers, and so I tried coding a simple thread library of my own, in order to understand the nitty-gritty details.
API
Although the library I wrote is very simplistic, it allows a programmer to do some basic threading, using 4 threading functions:
myThread_create()
- To create a threadmyThread_exit()
- To exit a threadmyThread_init()
- To initialise the thread librarymyThread_getID()
- To get the current thread's ID
Experience gained
Context switching, UNIX interval timers, using inline GNU assembly in C++ code
Implementation notes
- Many user threads are mapped to a single kernel thread (Many to one)
- Interval timers transfer control to the thread scheduler periodically
- 80386 register values are saved in a "context" structure
- Thread scheduling is round robin
- Each thread gets a time slice of 1 second (too much, just for testing purposes)
Note when using the library
- The threads should not do something fancy like generate signals, since signals have not been taken care of by the thread library
- A
fork()
duplicates ALL the threads, not just the calling thread setitimer()
andgetitimer()
should not be used by the threads- For simplicity in context switching, this library is specific to the Intel 386 processor, specify the option '-march=i386' while compiling with g++
Thoughts for improvements
The library is not robust, since it expects the programmer to call the threading functions in an "orderly" and meaningful manner. I have thought about a few ways to prevent the program from crashing in case the functions are not used properly:
myThread_exit()
is not called at the end of a thread - Solution: push the address of myThread_exit() on the stack, so that when the thread exits, it gets called automaticallymyThread_init()
is not called before creating threads - Solution: have a flag to indicate if this function has been called or not. The other library functions should check this flag
I used Doxygen to generate the documentation. Please check out the documentation for more implementation details.
References
- Operating Systems Design and Implementation (The MINIX Book): For context switching and signal handling internals
- Operating System Principles (The Dinosaur Book): For the 3 multi-threading models
- Advanced Programming in the UNIX Environment: For signal handling and PThreads
- linux.die.net: Linux man pages