OS/2 Multitasking



Chapter:Chapter 02 – Inside OS/2 Warp
Subsection: 01. Base Operating System Architecture
Document Number:02
Topic: OS/2 Multitasking
Date Composed: 10-07-96 02:00:40 PM Date Modified: 01-15-99 11:10:35 AM

Introduction to Multitasking

At any given moment in time, a personal computer microprocessor can execute only one instruction in one task. However, by dividing the microprocessor time between multiple tasks, it is possible to give the impression to relatively slow human senses that they are running simultaneously. This technique is called multitasking.

DOS is intrinsically a single tasking operating system. This means that it can only perform one task, or job, at a time. If you wish to run an application program other than one which is currently running, you must terminate the current application and then start the second application. This limitation, as much as the limitation on memory usage, is due to the historical roots of DOS. The original Intel 8088 microprocessor did not have the hardware support required to effectively implement a multitasking, virtual memory, or memory isolated operating system.

OS/2 utilizes the built in multitasking capabilities of the Intel 80×86 family of microprocessors. These capabilities include the ability to address large amounts of real memory – up to 4 GB – and the ability to protect the system resources being used by one program from intrusion by another program. For this reason, the operating mode of the 80×86 microprocessors which provides for multitasking is known as protect mode.

The multitasking ability of OS/2 allows the system to perform more than one task at a time. You may have several different programs running at once, as well as multiple communications sessions. It is also possible to have one program performing several tasks simultaneously. The basic unit of program execution is the thread. Each program running under OS/2 must have at least one thread, but may have more than one if it has been so designed.

Processes and Threads

The minimal benefit of being able to switch from one program to another without terminating the first is something which everyone can appreciate. The real benefits of true multitasking become apparent when downloading several large files from a BBS, using FTP to transfer a file to the internet, spell checking a large document, and printing checks for accounts payable. The downloads, spell check, and check printing can be started and then you can work interactively with the word processor while the other tasks proceed in the background.

The benefits derived from using multiple threads in a single program are not so apparent, however. From the standpoint of the user, the primary benefit is that of faster perceived program response time. The programmer may provide one thread to allow for data input, another thread for updating the screen, and yet a third for performing calculations. In a spreadsheet environment, for example, as soon as a user has entered a number into a cell, the display can be updated with newly calculated values and while the user is entering additional data, the background thread can recalculate the rest of the spreadsheet. This results in a much faster perceived speed of operation because the user does not have to wait for the entire spreadsheet to recalculate before additional data is entered.

When each program is launched Warp creates a new process. Every process (program) has at least one thread. If the programmer of an OS/2 program decided that multiple threads were required, he or she could use special function calls within OS/2 to do so. In general, programs have only one thread unless the programmer has overtly designed the program for more.

Task Management

OS/2 multitasking is managed by the task dispatcher. The dispatcher handles the dispatching of tasks with a set of algorithms which are designed to allow multiple tasks to run simultaneously with as little effect upon each other as possible, while still allowing high priority tasks swift access to the processor when needed. OS/2 is a dynamic, priority based, preemptive multitasking system with round-robin scheduling.

In OS/2 Warp, the dispatcher dynamically modifies a thread’s time slice based on trigger actions that may have occurred. For instance, if a thread encounters a page fault during its time slice, it is given an extra time slice to process the data contained in the faulted page. Applications doing disk I/O are also given extra time slices if the data they are reading is in the disk cache. When the TIMESLICE= parameter is used as in versions 1.x and 2.x of OS/2, none of these dynamic modifications of a threads allocated time will occur. Instead, each thread will be given the minimum time slice of X, and its time slice will not be allowed to go beyond value Y. See also the TIMESLICE document for more details about this CONFIG.SYS file parameter.

Priority Based Multitasking

A priority based multitasking operating system is one in which each task is assigned a priority. The priority of each task is determined by the programmer. If the programmer makes no overt choice, the operating system, OS/2 in this case, assigns a default priority, regular class, priority level 0.

In any priority based task scheduling operating system, the task with the highest priority which is capable of running, that is, not blocked, will get the CPU. All other tasks must wait until that task becomes blocked before they may have CPU time. A task becomes blocked when it must wait for input from a keyboard or mouse, for example, or for data to be read from a disk, or for a communications buffer to fill. There are many other reasons why a task might become blocked. If a task of a higher priority than the current running task becomes unblocked, then OS/2 will preempt the running task to give the CPU to the task with the higher priority.

OS/2 has four priority classes.

  1. Time critical (800)

    A time critical task such as communications or networking will run in this priority class. Such programs need to have access to the CPU very quickly.

    In communications, for example, when the data receive buffer fills up it is necessary to remove the data from it and store it in a less critical location until it can be processed by a lower priority task. When the receive buffer fills, the communications port hardware generates a hardware interrupt which is handled by the OS/2 device driver for that port. For an asynchronous communications port this is the COM.SYS device driver. The device driver sends a software interrupt to the application program which moves the data from the receive buffer and stores it in another location in memory.

    The portion of the program which handles the communications buffer must be a very high priority so that it can get the data from the buffer before more data arrives and causes a receive buffer overrun. The rest of the communications prgram can run at a lower priority class. When overruns occur, the data must be resent which reduces the total data transfer rate.

    Time critical tasks take a very small portion of the CPU’s time. Even after all time critical tasks receive all the CPU time they require, there is still plenty of time left for all the other tasks running on the computer.

  2. Server (400)
    Server class programs are used by Warp Server, for example, to process requests for data by client workstations and to get the data requested ready to transfer across the network. Processing these types of tasks at the Server class ensures that administrative tasks such as creating new user IDs do not interfere with them.
  3. Regular/normal (200)
    Regular, or normal class is the priority class at which most application programs run. This is also the default class at which OS/2 will run programs which do not overtly specify a priority class.
  4. Idle time (100)
    A program which runs at idle class will only receive CPU time when all other programs at higher priorities have become blocked. In reality, for most average systems, this can be quite a large amount of time. To see this, start the OS/2 Pulse program applet which comes with OS/2. It is located in the Productivity folder. Most of the time the processor is doing very little, if anything, so there is lots of time for idle class programs to run.

The Pulse program itself runs at idle priority. It simply counts the CPU cycles which it receives as a consequence of the fact that no other process needs them, and displays the result as a graph indicating the amount of CPU time being used by all the other programs on the system. To perform this task accurately, it cannot run at regular class or higher because it would always receive some CPU cycles in the normal round-robin sequence of task dispatching. This would skew the results.

A good example of a productive application which should be run at idle class would be a math intensive calculation. There is an OS/2 program which calculates the common math constants Pi and e ( Euler’s constant) to any number of decimal places in increments of 500 places. Suppose I want to calculate Pi to 1,000,000 decimal places. At the same time, I want to do all my normal daily tasks like word processing, Lotus Notes, network communications, and asynchronous communications.

Since this calculation takes a couple days on even a fast system, I cannot afford to have it tie up my system. This program was written so that I can change the priority class, so I set it at idle class and start the calculation. Actually, this program was written so intelligently that I can change the priority class while it is calculating. With the Pi calculation going in the background in idle class, I can go do my regular daily work. Any CPU cycles not needed for my normal work are given by Warp to the Pi calculation.

Figure 1: The 4 priority classes of Warp each have 32 levels.

32 Priority levels per class

Figure 2.1.1, above, shows the four priority classes of OS/2 Warp. The boxes to the right of the priority class diagram represent threads of several processes which are running. Threads on the same line are at the same priority class and level. Threads shown with red rectangles are blocked; that is, they cannot run because they are waiting for some system activity, such as disk access to complete, or the printer to request more data. The threads indicated by yellow rectangles are capable of running, but are not currently running because another thread is. The one thread represented by a green rectangle is running. Only one thread can run at a time.

Each priority class under OS/2 has 32 priority levels numbered from 0 through 31. There are a total of 128 discrete priority levels at which tasks can run. This means that multiple tasks may run in regular class, for example, but one or more may still be at a higher priority level within the regular class. The numeric values for each priority class are given in Table 2.1.1.

Priority Class

Numeric Range

Time Critical 800 – 831
Server 400 – 431
Regular 200 – 231
Idle 100 – 131

Table 2.1.1: Priority class numeric ranges.

Using PSTAT to determine the priority of a task

Warp has a utility called PSTAT which allows you to display or print a list of all the tasks and threads running on your system. PSTAT shows the process and thread IDs for each task as well as the priority level for each task. Figure 2.1.2 shows the output of PSTAT when run on the author’s system. The command below issued from the command prompt sends the output of the command to a file named C:\PSTAT.DAT. The /C parameter is used to display the current process and thread data. Other parameters allow display of memory, DLL, and semaphore information.


                    Process and Thread Information

Process   Process   Session   Process   Thread
ID        ID        ID       Name       ID    Priority   Block ID   State

 002F      0000       13      C:\IBMLAN\SERVICES\ALERTER.EXE    01      0200     FFFE004C   Block
002E      0000       13      C:\IBMLAN\SERVICES\TIMESRC.EXE    01      0200     FFFE004A   Block
002D      0000       13      C:\IBMLAN\NETPROG\RNS1.EXE    01      0200     FFFE0048   Block
02      0200     06880096   Block
03      0200     068800C2   Block
04      0200     068800EE   Block
002B      0000       13      C:\IBMLAN\SERVICES\NETLOGON.EXE    01      0200     FFFE0046   Block
02      0200     FFFD0072   Block
03      031F     FFFE0045   Block
04      0200     040054FE   Block
002A      0000       13      C:\IBMLAN\SERVICES\NETSERVR.EXE    01      0300     FFFE003E   Block
02      0300     FFFE003C   Block
03      0300     FDF2BB44   Block

                                          04      0200     FDF254B8   Block
05      0300     FFFE003F   Block
0029      0000       13      C:\IBMLAN\SERVICES\NETSERVR.EXE    01      0301     FFF78083   Block
02      0300     FFFE003D   Block
03      0300     040054E6   Block
04      0300     FFFE0040   Block
05      0300     04004853   Block
06      0301     FFFE0041   Block
0026      0000       13      C:\MUGLIB\MUGLRQST.EXE    01      0200     040054C8   Block
02      0200     FE1ACE34   Block
0025      0000       13      C:\IBMLAN\SERVICES\MSRV.EXE    01      0200     040054BC   Block
02      0200     FFFE0037   Block
0023      0000       13      C:\IBMLAN\SERVICES\WKSTAHLP.EXE    01      031E     2260BE6C   Block

                                          02      0200     225005FE   Block
03      031E     2250210E   Block
04      031E     2250061C   Block
0022      0000       13      C:\IBMLAN\SERVICES\WKSTA.EXE    01      0300     FFFE003A   Block
02      021F     FFFD005B   Block
03      0200     FFFE0033   Block
04      021F     FFFD0060   Block
0018      0000       00      C:\OS2\EPWMUX.EXE    01      0200     FFFE0024   Block
0013      0000       00      C:\OS2\EPWMUX.EXE    01      0200     FFFE001F   Block
0012      0000       00      C:\OS2\EPWPSI.EXE    01      0200     06880012   Block
0011      0000       00      C:\OS2\EPWMP.EXE    01      0200     FE03E834   Block
02      0200     FFFE0025   Block
03      0200     FFF78083   Block

 000E      0000       00      C:\WAL\MEMMANIT.EXE    01      031F     FFFE0016   Block
000C      0000       00      C:\IBMLAN\NETPROG\ATKINIT.EXE    01      0302     FFFE0013   Block
02      0200     FFFE0014   Block
000B      0000       00      C:\IBMCOM\VLANINIT.EXE    01      0200     FFFE0017   Block
000A      0000       00      C:\OS2\EPWROUT.EXE    01      0200     FFFE0020   Block
02      0200     FFFE001A   Block
0009      0000       00      C:\OS2\SYSTEM\LOGDAEM.EXE    01      021F     04A00252   Block
0008      0000       00      C:\IBMLAN\NETPROG\LSDAEMON.EXE    01      0200     FFF78083   Block
0007      0000       00      C:\IBMCOM\PROTOCOL\LANDLL.EXE    01      030B     544F4B52   Block
0005      0000       00      C:\MPTN\BIN\CNTRL.EXE    01      0304     F2750002   Block
02      0304     F2750001   Block
03      0304     1450525A   Block

                                          04      0304     14505272   Block
05      0304     F2750001   Block
06      0304     F2750002   Block
07      0304     FFF78083   Block
08      0304     F2750008   Block
0004      0000       00      C:\IBMCOM\LANMSGEX.EXE    01      0200     FFFEF636   Block
000D      0001       01      C:\OS2\PMSHELL.EXE    01      0200     FDF20F24   Block
02      0300     FFCA000D   Block
03      0300     FFFD001C   Block
04      0300     FFFD001D   Block
05      0300     04000E28   Block
06      0200     FE179B6C   Block
07      0200     FE17BBF0   Block
08      041F     FDF20F54   Block

                                          09      0200     FFFE001B   Block
0A      0200     FFFD0006   Block
0B      0300     FFFE001D   Block
0C      0300     FFFE001E   Block
0D      0300     FFFE001C   Block
0E      0304     FFFD002A   Block
0F      0304     04000E1A   Block
10      0200     FFFD002C   Block
11      0301     FDF25078   Block
12      0200     FDEDAD40   Block
13      0300     04000E36   Block
14      0300     FE03DB74   Block
15      0300     FDF254F8   Block
16      0401     FE1E037C   Block

                                          17      0401     FE1E0DA8   Block
00A0      000D       15      F:\IMPOS20\IMPOS.EXE    01      0200     FE1F16EC   Block
02      0200     0688011A   Block
0093      000D       1E      E:\DESCRIBE\OS2\DESCRIBE.EXE    01      021F     FE1E6E38   Block
02      0200     FE1E6BC8   Block
03      0200     FE1E6BF4   Block
04      021F     FE1E1980   Block
05      0200     FE1E200C   Block
06      0200     FE1E2A30   Block
008E      000D       1D      (kernel)    01      0200     FE1E08D4   Block
0055      000D       1C      E:\UTILITY\FILESTAR\FILESTAR.EXE    01      0200     FDEF5C30   Block
03      0200     FDEF5990   Block
04      0200     FDF0FACC   Block

 004B      000D       18      F:\NOTES\ILNOTES.EXE    01      0201     FE01ADF0   Block
004A      000D       1B      F:\NOTES\QNC.EXE    01      0200     FDFE7F68   Block
0048      000D       1A      E:\IBMAV\IBMAVTIM.EXE    01      0200     FFF78083   Block
0047      000D       11      E:\WPC200\WPC200.EXE    01      0200     FE1C2BEC   Block
02      0200     FE1C29D0   Block
03      0200     FE1C2948   Block
04      0200     FE1C292C   Block
0034      000D       13      C:\OS2\CMD.EXE    01      0200     FFCA0034   Block
00AA      0034       13      C:\OS2\PSTAT.EXE    01      031F     00000000  Running
0032      000D       04      F:\NOTES\QNC.EXE    01      0200     FE18C7B0   Block
0033      0032       04      F:\NOTES\ISERVER.EXE    01      0201     FFF78083   Block
02      0206     FFF78083   Block
03      0207     040054DA   Block

                                          04      0207     040054D4   Block
05      0201     FFF78083   Block
06      0205     FE1B71F0   Block
0045      0033       04      F:\NOTES\QNC.EXE    01      0206     FE1C4D88   Block
0046      0045       04      F:\NOTES\IADMINP.EXE    01      0201     FFF78083   Block
0041      0033       04      F:\NOTES\QNC.EXE    01      0206     FDEFDC70   Block
0042      0041       04      F:\NOTES\IAMGR.EXE    01      0201     FFF78083   Block
0043      0042       04      F:\NOTES\QNC.EXE    01      0201     FDEFDB64   Block
0044      0043       04      F:\NOTES\IAMGR.EXE    01      0201     FE136AAC   Block
003C      0033       04      F:\NOTES\QNC.EXE    01      0206     FDFF3F70   Block
003D      003C       04      F:\NOTES\IUPDATE.EXE    01      0201     FFF78083   Block
003A      0033       04      F:\NOTES\QNC.EXE    01      0206     FE1B0D58   Block
003B      003A       04      F:\NOTES\IROUTER.EXE    01      0201     FFF78083   Block

 0038      0033       04      F:\NOTES\QNC.EXE    01      0206     FE1C2864   Block
0039      0038       04      F:\NOTES\IREPLICA.EXE    01      0201     FFF78083   Block
001F      000D       19      E:\IBMAV\IBMAVSD.EXE    01      0200     FE040FCC   Block
001C      000D       17      E:\UTILITY\GTU30\SENTRY.EXE    01      0200     FDF1B27C   Block
02      0200     FFF78083   Block
03      0200     FFF78083   Block
04      0200     FFF78083   Block
05      0200     FFF78083   Block
001B      000D       16      E:\FAXWORKS\FAXWORKS.EXE    01      0200     FE10AECC   Block
02      0300     FDEDA968   Block
03      0200     0688006A   Block
04      0200     FFFE002F   Block
05      031F     00BC09E4   Block

 0019      000D       14      C:\IBMLAN\NETPROG\NETMSG.EXE    01      0200     FDFF1CC0   Block
02      0200     FFFE0039   Block
03      0200     FE126BCC   Block
04      0200     FDFF1EE8   Block
0016      000D       12      C:\OS2\PMSHELL.EXE    01      0200     FE18CA20   Block
02      0300     FDEDA614   Block
03      030A     FDEDA5FC   Block
04      0300     FE18C7B4   Block
05      0300     FE17CE68   Block
06      0200     FDEDAD58   Block
07      0400     FE141FD8   Block
08      0200     FE122D34   Block
09      0200     FE122C30   Block
0B      0400     FE18C050   Block

                                          0C      021F     43D82800   Ready
0D      0200     FFFE0026   Block
0E      0400     FE11FF54   Block
0014      000D       10      C:\OS2\PMSPOOL.EXE    01      0200     FFF78083   Block
02      0200     FE149BC4   Block
03      0200     4388000E   Block
04      0200     FE18DFF0   Block
05      0200     FE150970   Block
06      0200     FE1509A8   Block
000F      000D       00      C:\OS2\SYSTEM\HARDERR.EXE    01      0300     04000E44   Block
02      0300     04001158   Block
03      0300     0400117C   Block

Figure 2: The results of PSTAT on the Author’s system.

Altering Priority Levels

OS/2 does not provide for user access to priority levels. A programmer, however, may provide access to priority levels within a program and provide the user with controls in the program to manipulate them. There are also some third party utilities available which allow the user to view and alter the priority levels of other running programs. One such utility is CPU Monitor Plus, by BonAmi Software.

Extreme care should be taken when altering the priority level of a process or thread, as the action taken may have the opposite of the desired effect. Consider, for example, the print spooler process. This process manages the transfer of print data from application programs, to the hard drive, and from there to the printer.

When I ask most people what priority they think that the spooler process should run at, they tell me it should be a very low priority process. In fact, it should be a high priority process. The reason for this is that printing, being an essentially mechanical process, is very slow compared to the speed of the processors in today’s computers. As a result, when the spooler sends data to the printer, it must then wait for a computer’s eternity for the printer to print the data and request more from the spooler. When this request for more data is received by the spooler, it is important to respond and get the data to the printer as quickly as possible to prevent delays to an already slow process.

The spooler is blocked most of the time, either waiting for a print job or waiting for the printer to request more data for a running print job. While blocked, it gets no CPU time, and all five spooler threads have priority level 200, the base level of the Regular priority class. When a print job is spooling, however, one of the threads is boosted to priority level 400, the base level of Server (a.k.a. Fixed High) class. This provides a high enough priority to ensure that printing gets done quickly but, because the spooler is blocked most of the time waiting for the printer to request more data, it does not affect the performance of the rest of the system.

The Spooler object in the System Setup folder allows users to adjust the priority of the print spooler. You should be careful with this, however. Decreasing the priority will slow the print process significantly. Increasing the priority will have no noticable effects while small print jobs are printing because they complete so quickly, but can cause the rest of the system to slow considerably while very large print jobs are being printed. Another problem with increasing the priority too much is that the spooler priority becomes higher than that of other important tasks such as network functions. This can cause problems not only with the response time on the local workstation, but it can also create problems for networking tasks.

The default print spooler priority setting is perfect for most environments.

Preemptive Multitasking

In any multitasking operating system, there are some tasks which are extremely important and which must obtain access to the processor as quickly as possible at specific times. Such a task would be a communications or networking program. These tasks, or really a small portion of these tasks, the portion responsible for the time critical part of the process, should be run at a high priority. For communications programs this is usually at some high level in the time critical class.

When a program with a higher priority than the currently running program or task becomes unblocked, OS/2 preempts the lower priority task and gives the CPU to the higher priority task.

Round-Robin Scheduling

Round-robin scheduling simply means that all tasks which are running at the same priority will receive time slices in a round-robin fashion, so that each can have some time. The Warp task dispatcher manages this and preempts any task which has taken the maximum time slice.

Dynamic Priority

The priority level at which a task runs under OS/2 is dynamic; OS/2 can change the priority of a task depending upon its needs. There are three ways in which OS/2 uses it’s ability to dynamically alter the priority of applications, even while they are running.

CPU Starvation

It is possible that some tasks in a multitasking system might become starved for CPU time. Since most running tasks will be at regular priority, many will be at the same priority level. As these tasks run in round-robin fashion, the amount of time taken by the tasks which are not blocked may prevent one or more of the remaining tasks from obtaining CPU time within the amount of time specified in the MAXWAIT statement in CONFIG.SYS.

When a task becomes starved for CPU time in this manner, the OS/2 task scheduler boosts the priority of the starved task within its class by one priority level. This places this task at a higher priority level than the other tasks with which it was running. It will, therefore, receive a timeslice before those other programs. When it does receive a timeslice, it is allocated one minimum timeslice by the scheduler and then it is reduced to its base priority.

This dynamic priority scheduling allows each task to be sure it will receive at least some CPU time.

Foreground Boost

When running a program in a multitasking environment, especially one with which you will continually interact such as a word processing program, it is reasonable to expect that program to respond to user input quickly. One of the ways in which OS/2 ensures that this will happen is to provide the foreground task, that is the one with which the user is interacting and which has the keyboard focus, a boost in priority. In this case the boost is by a level of one within the task’s priority class.

Foreground I/O Boost

Setting PRIORITY_DISK_IO=YES in CONFIG.SYS provides a priority boost to I/O operations for the application running in the foreground. This ensures that a DOS program, or an OS/2 program which was not written with a separate thread for I/O operations will perform its I/O tasks and return control to the user as quickly as possible.