From RISC OS
Preemptive multitasking (or PMT for short) is a multitasking model in which the operating system takes control away from a program and gives it to another program, in order to ensure that all applications get their fair share of time. Most current operating systems use preemptive multitasking, although RISC OS does not currently use this model, instead opting for a model known as cooperative multitasking, where applications decide when to cede control to the operating system. However, there has been much discussion about the issue for many years, and there have been attempts to bring it to RISC OS.
Benefits of PMT
- A frozen program should not freeze the system, the OS should be able to take control once that program's "time slice" is over, and then you should be able to kill the frozen program, without losing anything you were working on.
- When running software that heavily loads the CPU, the rest of the system doesn't become unresponsive while the program is doing something.
- Programs don't have to be written to stop in the middle of what they're doing to preserve system responsiveness, as the OS does this for them. This makes development simpler.
Cons of PMT
- Developing a PMT OS is usually trickier than a CMT OS.
- Software in a PMT OS doesn't automatically get the whole CPU to itself for as long as it wants. That's the primary benefit of PMT, but some people consider it a disadvantage. However, with use of interrupts and priority levels, a PMT OS can usually do the tasks just as effectively, while keeping the system responsive.
Difficulties of PMT that are specific to RISC OS
Many APIs in RISC OS are not thread-safe. That is, the OS maintains some state between calls to an API. For example Wimp_OpenTemplate can only open one window template file at once - the API doesn't provide for a way to specify which template file a subsequent request is directed to. If Wimp_OpenTemplate is called twice in a row for different files, the first file will be closed and all accesses will go to the second file without warning that the wrong file is being accessed.
Previous attempts to bring PMT to RISC OS
Gold was a project by Acorn to move RISC OS over to the Mach microkernel, which is used today by Apple as the basis of the Darwin kernel used by OS X.
Galileo was another project by Acorn to move to a PMT OS, this time from the ground up. Galileo was cancelled with the closure of the workstation division.
Wimp2, by Niall Douglas, used a different approach from previous attempts to build a PMT OS. Rather than build a PMT OS from the ground up, Wimp2 essentially ran inside of the existing OS, as a PMT environment for applications to run in. Programs could either be patched to run in the Wimp2 environment (with varying success,) or they could be recompiled for Wimp2. Incompatible programs ran outside of the Wimp2 environment. This approach has some serious issues, however.
Wimp2 works by setting a callback from a timer. The timer code is run in interrupt mode so cannot call Wimp_Poll, but the callback will get run next time the OS is in user mode. When the callback happens, Wimp2 calls Wimp_Poll on behalf of the application (which is quite possibly busy doing something else). Any messages it receives from Wimp_Poll are thus delayed and fed to the application at a later time.
A similar use of callbacks is provided in the pthread library in UnixLib, which is used by Firefox and other applications to implement threading.
Approaches to bringing PMT to a CMT OS
Preemptive multitasking is a major change to a CMT environment, as applications aren't usually expecting to be preempted. There are various methods of doing this, of varying difficulty, and varying benefit.
Directly running CMT applications in the PMT environment
This is by far the hardest method to do properly, although it provides the largest benefit, as existing software would get the benefits of PMT. Unfortunately, when done poorly, stability of the entire system is compromised.
WimpPatch for Wimp2 is an example of this approach.
Virtualization involves running either applications or an OS inside of a virtual machine, a type of emulator. This approach has been used by many operating systems to run CMT (or even single-tasking) software without the issues of running them inside the main PMT environment. It's also been used for other reasons (for example, running 26-bit-only applications in a 32-bit-only environment using Aemulor) that are outside of the scope of this article.
Microsoft Windows NT uses this approach by running 16-bit Windows applications and DOS applications in a carefully designed VM, known as the NTVDM, that translates calls to Windows, DOS, and the BIOS into Windows NT calls. All applications run in the same process space. This allows these applications to run seamlessly with the main environment, albeit with the downside that interactions between virtualized programs are still subject to the problems that CMT has.
Mac OS X uses this approach to run a complete copy of Mac OS 9 on top of OS X. Old applications run inside of this virtualized copy of the old OS. This is not a very seamless approach, but it's effective.
OS/2 uses a similar approach to NT for DOS apps, although each DOS app gets its own copy of the VM. As Windows 3.1 itself is a DOS app, it's treated the same way. Special drivers are in the Windows 3.1 environment to display Windows 3.1 windows in the OS/2 environment, although it's not seamless. This is a similar approach to what Mac OS X uses.
Running the PMT environment on top of the CMT OS
This is the least optimal approach for stability and performance, as a CMT application can still freeze the entire system, or reduce responsiveness.
However, it's by far the simplest method for getting PMT onto an existing CMT OS.
This approach was used by Wimp2, although there are very few applications which natively use Wimp2.
Making Applications Have PMT behaviour
This isn't exactly the same thing as having the OS PMT the application, but it can be extremely effective in some cases.
The idea is to abstract away from the application the need to Wimp_Poll at a given time to behave nicely - it just listens for events it needs to handle. This is much how things work for applications under X Windows or the Windows MFC framework.
There are probably not many examples of this in RISC OS, but the experimental versions of Firefox does this. In that specific case, the ChoX11 library splits the Wimp Poll into its own thread, and delivers events (using standard threading locks) to the application's event queue. This is very effective over the alternative, since otherwise Firefox can single task for long periods of time before asking for another event (which is when you would cooperatively multitask), and means it behaves smoothly without having worry about splitting up complex processing.
The significant downside is that for many applications, this would require changes to their Wimp_Poll handling, and it needs to be disabled temporarily over redraw loops, so is mostly suitable for ports where applications would be using ChoX11 anyway. However, the complexity in some cases could be hidden inside DeskLib or other Wimp libraries, so that some applications would only need a recompile, or minor changes.
- Wikipedia article on preemption
- Wimp2 page
- Microsoft knowledge base article on how multitasking works in Windows 95