Kevin's Research Blog

Operating Systems: Co-Operative Multitasking

When you heard the term "Co-operative multitasking", what is the first thing that comes to your mind? If you lived through the 80s and 90s, then you probably have PTSD for Windows 3.x and pre-MacOS X crashing and hanging due to a badly coded program, requiring a full reset of the entire system. You might be thinking to yourself, there's absolutely no place in the modern world for co-operative multitasking. You might be right, but also, it's been awhile since any computer scientist has actually given co-operative multitasking another solid look to see where it could possibly apply in our modern digital age. After all, if every modern operating system is pre-emptive now, that must be the future of computer operating systems going forward, right?

What is pre-emptive multitasking?

First, let's go through how the computer operating system you are most likely using to read this article multitasks.

Pre-emptive multitasking is done entirely within the operating system kernel without any of the running applications really knowing about it, the operating system kernel will rapidly switch between all the actively running tasks in your computer at a very rapid speed, trying to give each process equal opportunity to run. In most cases, this works really well. We have as a result created very stable operating systems, such as the UNIX-like systems, like Linux, and BSD, of which OS X is a part of. And Microsoft has their NT kernel, which also uses this method of multitasking. As long as an application doesn't try to overload the system, everything runs really well.

One of the drawbacks of this method, is that if an application needs more processing power, there isn't much it can really do. Most operating systems provide a method to increase it's priority, where the kernel will give it more CPU cycles, but that's about it. Performance applications like intense business server applications, or games are at the mercy of this sort of multitasking system. There also isn't an easy way to even test if the same application will run better under a co-operative multitasking environment, as it is not really possible to swap an application between the two types of multitasking.

What is co-operative multitasking?

This sort of multitasking is probably most familiar to those who grew up in the 80s and 90s with Windows and Pre-X Macintosh computers. A lot of people experienced a lot of crashes, device and hardware issues, among a large array of performance issues. So, why would I be talking about co-operative multitasking in what is essentially a post-co-operative multitasking era of computers? First, let me explain why applications could have been unstable and how co-operative multitasking works.

Co-operative multitasking as the name implies, each application is required to well co-operate. The kernel has an API, which every application running is required to call when they are done performing their tasks so that the next program in the system can then do their tasks. If a program does not call this API promptly enough, it can lead to a slow and otherwise laggy system. This was much easier to do back in the 80s and 90s, as PCs were very very slow back then, so if one program didn't do it's job fast enough, the system was noticeably slower. However, jump ahead to our modern era of computers, and now we have super fast processors, and this limitation of co-operative multitasking is now gone. As each task should easily be-able to perform their duty and call the kernel API in ample time. A well coded program in a co-operative multitasking environment on modern hardware should be-able to potentially even run better than with pre-emptive multitasking.

One of the nifty parts of a well programmed co-operative multitasking operating system is that if an application doesn't need any CPU whatsoever, it doesn't even need to have a idle loop which actually still consumes some CPU. With a well written co-operative multitasking kernel, the applications themselves can say, I don't require any attention until this specific event happens, like say a mouse click. This allows every other application, including kernel services to have more CPU cycles allocated to them, then they would otherwise have on a pre-emptive kernel.

Another interesting feature of co-operative multitasking is that each task knows that it has essentially exclusive access to the system at the time it is running. This can enable some rather interesting things to happen, both in the kernel, and in the application itself. For example, the kernel knows what task is going to be running, and so it can swap in anything specific at that point to ensure the applications runs as smoothly as possible during it's time. RISC-OS uses this fact to load every application at the exact same location in memory, at least from the application's point of view. Each application on RISC-OS loads at $8000 in memory. This also means, that another application can't even see any other applications while it is running, and to it, it thinks that it is the only application running. The RISC-OS kernel does have various APIs which allow applications to still transfer data between each other, but otherwise, one application absolutely cannot view or alter the memory of another running application that easily. From the application point of view, it knows it has exclusive access to the system while it's running, so it can do things which an application in a pre-emptive environment shouldn't otherwise do, such as direct hardware access. If a task is say a full-screen application and is single tasked, this provides a lot of performance benefits to the application itself, as it knows that it won't be swapped out with another task.

The last modernish co-operative kernel

There is one last co-operative multitasking operating system in the world that is still being actively updated and maintained. That operating system is none other than RISC-OS.

Despite RISC-OS using co-operative multitasking, well written software for the operating system creates a very stable environment. RISC-OS has been working on co-operative multitasking even when every other operating system moved on to pre-emptive multitasking. This is what actually makes RISC-OS a perfect research operating system to play around with co-operative multitasking concepts and ideas.

One very interesting feature of RISC-OS, is that applications running on it, don't even need to multitask if they need full exclusive access. A lot of full-screen applications essentially turn off multitasking all together, and take full control of the system. This works really well for these specific applications, such as games. Most of these non-multitasking applications usually have a quick hotkey to easily suspend the full-screen application, similar to say Alt-Tab, but when the full-screen application is suspended when back in multitasking, it then takes 0% CPU until the user calls it back up again. This can lead to a distraction free environment for specific tasks, and when you do wish to check something, you can. It allows the user to focus on what they want to focus on, rather than what the operating system wants them to focus on.

Co-operative multitasking in the modern era

I have some ideas for a few research projects as a result. RISC-OS has a modern networking and sockets stack for example. One idea that I am considering is to write several single tasking server applications, which do not use multitasking at all. These server applications will then have exclusive access to the system without any other process, or even the operating system itself bogging it down.

This can have several complications, as for example, remote management of the system would be much more difficult, as tools like SSH and VNC require a properly functioning multitasking environment to function. My thoughts on how to get around this is to create a services system of sorts, where a supervising single tasking program will manage multiple listening sockets, and dispatch them accordingly. One service would be one which would allow me to deploy a new version of my application to the server for example, and to restart this secondary service.

Another interesting advantage to having a fully single tasked server application is security. When you consider how most server attacks happen in the real world, under a more strict single tasking server program, it would make it much more difficult for an attacker's software to get any CPU cycles, if any. The attacker will need to target the single tasked server software only, as nothing else would be accessible, as nothing else can consume any CPU cycles but the server program.

Where next?

Personally, I feel that we need to take a second look at co-operative multitasking that now computers are much more powerful than before. The main bottleneck of co-operative multitasking was that single task that always took too much time to return control back to the kernel. With CPUs now in the GHz, this is much less of a bottleneck now.

RISC-OS also has an interesting and very well implemented hotkey, Alt-Break, which will interrupt any task and allow the user to terminate a task that has taken all the CPU cycles. It works much more efficiently than Windows' Ctrl-Alt-Delete method, which didn't really allow you to easily end that poorly written task. If co-operative multitasking is written well, I can definitely see the benefits of using it in the modern era of computing.

#current #hobbyist #riscos #thoughts