How does cooperative multitasking work?
Asked Answered
C

3

7

I read this Wikipedia text slice:

Because a cooperatively multitasked system relies on each process regularly giving up time to other processes on the system, one poorly designed program can consume all of the CPU time for itself or cause the whole system to hang.

Out of curiosity, how does one give up that time? Is this some sort of OS call? Let's think about non-preemptive cases like fibers or evented IO that do cooperative multitasking. How do they give up that time?

Take this NodeJS example:

var fs = require('fs');
fs.readFile('/path/to/file', function(err, data) {});

It is obvious to me that the process does nothing while it's waiting for the data, but how does V8 in this case give up time for other processes?

Let's assume Linux/Windows as our OS.

Edit: I found out how Google is doing this with their V8.

On Windows they basically sleep zero time:

void Thread::YieldCPU() {
  Sleep(0);
}

And on Linux they make an OS call:

void Thread::YieldCPU() {
  sched_yield();
}

of sched.h.

Conversable answered 29/6, 2011 at 13:32 Comment(2)
Doesn't the kernel decide which process should "give up time"?Longhair
@Hannesh: That's preemptive multitasking.Little
O
4

Yes, every program participates in the scheduling decisions of the OS, so you have to call a particular syscall that tells the kernel to take back over. Often this was called yield(). If you imagine how difficult it is to guarantee that a paticular line of code is called at regular, short intervals, or even at all, you get an idea of why cooperative multitasking is a suboptimal solution.

In your example, it is the javascript engine itself is interrupted by the OS scheduler, if it's a preemptive OS. If it's a cooperative one, then no, the engine gets no work done, and neither does any other process. As a result, such systems are usually not suitable for real-time (or even serious) workloads.

Orcinol answered 29/6, 2011 at 13:41 Comment(1)
+1, one can look at Sleep() Win32 function - while Win32 uses preemptive multitasking Sleep() does exactly that.Little
P
2

An example of such an OS is NetWare. In that system, it was necessary to call a specific function (I think it is called ThreadSwitch or maybe ThreadSwitchWithDelay). And it was always a guess as to how often it was needed. In every single CPU-intensive loop in the product it was necessary to call one of those functions periodically.

But in that system other calls would result in allowing other threads to run. In particular (and germane to the question) is that I/O calls resulted in giving the OS the opportunity to run other threads. Basically any system call that gave control to the OS was sufficient to allow other threads to run (mutex/semaphore calls being important ones).

Plumage answered 29/6, 2011 at 13:48 Comment(0)
D
0

As a general rule, co-operative multitasking involves the functions signalling that they are now waiting, rather than going into spin loops ( where they process while waiting ) they suspend themselves.

In this case, the processing behind the ReadFile will handle the waiting for data and the relevant signalling that it is suspendable. Within you own code, whatever it is written in, you should suspend processing if you are waiting for a long-running process, not spin. However, in many cases, the suspend processes are automatically handled, because suspension activities are built in. The danger in this is tht if you deliberately force long-term spins, then you will hang the system.

The alternative ( from that wiki ) is pre-emptive multitasking, where the process is forced out action after a certain time, irrespective of what it is doing. This means that whatever you do, it cannot run forever, because the system process will force it out. However, it can be less efficient as the break points are not defined.

Dayfly answered 29/6, 2011 at 13:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.