Thread Scheduling
The threads library implements a thread scheduler that multiplexes thread execution across a pool of LWPs.
An LWP in the pool is either idling or running a thread.
When a thread, T1 is made runnable, it is added to the dispatch queue.
An idle LWP L1 in the pool is awakened by signalling the idle synchronization variable.
LWP L1 wakes up and switches to the highest priority thread on the dispatch queue.
If T1 blocks on a local synchronization object, L1 puts T1 on a sleep queue and then switches to the highest priority thread on the dispatch queue.
If the dispatch queue is empty, the LWP goes back to idling.
If all LWPs in the pool are busy when T1 becomes runnable, T1 simply stays on the dispatch queue, waiting for an LWP to become available.
An LWP becomes available either when a new one is added to the pool or when one of the running threads blocks on a process-local synchronization variable, exits or stops, freeing its LWP.
Thread States
An unbound thread can be in one of five different states:
RUNNABLE
ACTIVE
SLEEPING
STOPPED
ZOMBIE
The transitions between these states and the events that cause these transitions are:
Preemption
Threads compete for LWPs based on their priorities.
A queue of ACTIVE threads is maintained.
If a RUNNABLE thread has a higher priority than that of some ACTIVE thread:
This thread is removed from the ACTIVE queue and preempted from its LWP.
This LWP then schedules the higher priority RUNNABLE thread which caused the preemption.
There are basically two cases when the need to preempt arises:
When a newly RUNNABLE thread has a higher priority than that of the lowest priority ACTIVE thread.
When the priority of an ACTIVE thread is lowered below that of the highest priority RUNNABLE thread.
Cleaning ZOMBIE Threads:
When a thread terminates, it is put on a deathrow queue and their state is set to ZOMBIE.
Note: The action of freeing a thread's stack is not done at thread exit time to minimize the cost of thread exit by deferring unnecessary and expensive work.
A special thread called the reaper does this job periodically:
The reaper runs when there are idle LWPs, or when a reap limit is reached.
The reaper traverses the deathrow list, freeing the stack for each thread.