Simple Threads
Optional assignment for higher grade (3 points)
In this assignment you will implement a simplified version of many-to-one user level threads in form of a library that we give the name Simple Threads.
Preparations
Before you continue make sure you’ve read the implementing threads page. Among the slides in Studium you also find self study material about implementing threads.
Git
You should already have cloned the threads-and-synchronization repository.
Manage execution contexts
The ucontext.h
header file defines the ucontext_t
type as a structure that
can be used to store the execution context of a user-level thread in user space.
The same header file also defines a small set of functions used to manipulate
execution contexts. Read the following manual pages.
Example
In examples/src/contexts.c
you find an example program demonstrating
how to create and manipulate execution contexts.
Study the source. To compile, navigate to the examples
directory in the terminal, type make
and press enter.
make
To run:
./bin/contexts
Get started
In higher-grade/src
you find the following files.
- sthreads.h
- Header file specifying the Simple Threads API.
- sthreads.c
- Implementation of the Simple Threads API.
- sthreads_test.c
- A program used to test the Simple Threads API.
Study the source and pay attention to all comments.
First compile and test run
In the terminal, navigate to the higher-grade
directory. Use make to
compile.
make
Run the test program.
./bin/sthreads_test
The program prints the following to terminal and terminates.
==== Test program for the Simple Threads API ====
Cooperative scheduling (2 points)
For grade 2 points you must implement all the functions in the Simple Threads API
except done()
and join
. This includes cooperative scheduling where
threads yield()
control back to the thread manager.
The test program’s main()
thread and all threads
created by main()
share a single
kernel-level thread. The threads must call yield()
to pass control to the thread
manager. When
calling yield()
one of the ready threads is selected to execute and changes
state from ready to running. The thread calling yield()
changes state from
running to ready.
For grade 4 you may assume the main thread and all other threads are non-terminating loops.
Preemptive scheduling (3 points)
For 3 points, you must also implement the done()
and join()
functions in the
Simple Threads API. In addition to cooperative scheduling with yield()
you must also implement
preemptive scheduling.
If a thread doesn’t call yield()
within its time slice it will be preempted
and one of the threads in the ready queue will be resumed. The preempted thread
changes state from running to ready. The resumed thread changes state from ready
to running.
Timer
To implement preemptive scheduling you need to set a timer. When the timer expires the kernel will send a signal to the process. You must register a signal handler for the timer signal. In the signal handler you must figure out a way to suspend the running thread and resume one of the threads in the ready queue.
Timer example
In examples/src/timer.c
you find an example of how to set a timer.
When the timer expires the kernel sends a signal to the process. A signal
handler is used to catch the timer signal.