A thread is pre-empted when higher priority work becomes ready to process. Under normal circumstances the pre-empting thread will run then give up its time-slice and eventually the original thread will be re-scheduled.
It is possible for a thread not to be re-scheduled if a higher priority thread will not give up the processor. However, the OS/2 scheduler applies dynamic boost to priorities according to resource requirements and makes priority comparisons based on a calculated priority. The elements involved in the priority calculation are the following:
TCBPriClass
0x04
Priority is calculated by forming an index by ORing TCBPriClass and TCBPriClassMod and reading a constant value from the priority table. The low byte of this is then further ORed with the TCBPriLevel.
The following diagram shows the priority table.
┌───────────────────────────────────────────────────────────────────────────┐│ Table Index = (TCBPriClass | TCBPriClassMod) │ │ │ │ Starved 08 --------------------------------------------------+│ │ Device I/O 10 -------------------------------------------------+|│ │ Foreground 20 ------------------------------------------------+||│ │ Window 40 -----------------------------------------------+|||│ │ VDM Interrupt 80 ----------------------------------------------+||||│ │ |||||│ │ +-- TCBPriClass |||||│ │ | |||||│ │ | ============================================================ |||||│ │ | Not Keyboard || Keyboard |||||│ │ | || │ │ +-> Server Idle Regular TC || Server Idle Regular TC IWFDS│ │ │ │ │ │ 0x300, 0x100, 0x200, 0x800, 0x300, 0x100, 0x200, 0x800,// -----│ │ 0x62f, 0x100, 0x61f, 0x800, 0x62f, 0x100, 0x61f, 0x800,// ----S│ │ 0x72f, 0x100, 0x71f, 0x800, 0x72f, 0x100, 0x71f, 0x800,// ---D-│ │ 0x72f, 0x100, 0x71f, 0x800, 0x72f, 0x100, 0x71f, 0x800,// ---DS│ │ 0x300, 0x100, 0x300, 0x800, 0x300, 0x100, 0x400, 0x800,// --F--│ │ 0x62f, 0x100, 0x61f, 0x800, 0x62f, 0x100, 0x61f, 0x800,// --F-S│ │ 0x74f, 0x100, 0x73f, 0x800, 0x74f, 0x100, 0x73f, 0x800,// --FD-│ │ 0x74f, 0x100, 0x73f, 0x800, 0x74f, 0x100, 0x73f, 0x800,// --FDS│ │ 0x500, 0x100, 0x500, 0x800, 0x500, 0x100, 0x500, 0x800,// -W---│ │ 0x62f, 0x100, 0x61f, 0x800, 0x62f, 0x100, 0x61f, 0x800,// -W--S│ │ 0x74f, 0x100, 0x73f, 0x800, 0x74f, 0x100, 0x73f, 0x800,// -W-D-│ │ 0x74f, 0x100, 0x73f, 0x800, 0x74f, 0x100, 0x73f, 0x800,// -W-DS│ │ 0x500, 0x100, 0x500, 0x800, 0x500, 0x100, 0x500, 0x800,// -WF--│ │ 0x62f, 0x100, 0x61f, 0x800, 0x62f, 0x100, 0x61f, 0x800,// -WF-S│ │ 0x74f, 0x100, 0x73f, 0x800, 0x74f, 0x100, 0x73f, 0x800,// -WFD-│ │ 0x74f, 0x100, 0x73f, 0x800, 0x74f, 0x100, 0x73f, 0x800,// -WFDS│ └───────────────────────────────────────────────────────────────────────────┘
Notes
VDM Simulated interrupts always result in a value of 0x800
Foreground server class is not affected by the keyboard boost.
Time-critical class is not affected by any boosts.
Idle class is not affected by any boosts.
By examining the priority table it is clear that idle class will always be pre-empted by any other class.
Time-critical class can never be pre-empted by any other class.
Time-critical threads can only be pre-empted by other time-critical threads with a higher delta.
Server and Regular class threads may pre-empt each other depending on priority boosts and delta.
The key to looking at pre-emption problems is to look for other CPU bound threads of a higher priority. In particular time-critical threads.
.P displays the current calculated priority for each thread.