# Does cooperative scheduling suspend processes when they perform an I/O operation?

Many operating systems references say that with cooperative (as opposed to preemptive) multitasking, a process keeps the CPU until it explicitly voluntarily suspends itself. If a running process performs an I/O request that cannot be immediately satisfied (e.g., requests a key stroke that is not yet available), does the scheduler suspend it, or does it really keep the CPU until the request can be serviced?

[Edited to replace "blocks on i/o" with "performs an I/O request that cannot be immediately satisfied."]

• This questions seems to ask for specifics of operating systems which, imho, would be offtopic here. If this is not the case, please rephrase your question into a more abstract one. – Raphael Mar 6 '12 at 23:04
• When I posted it to the Unix group, I was told it was inappropriate there and belonged here, which I agreed with, since it's not about one specific operating system. I think this one is comparable to the question about branch prediction. It will be interesting to see what the community decides about what is and is not appropriate here. – Ellen Spertus Mar 7 '12 at 1:58

In a truly "cooperative" setting, and if there was no hardware protection, a process could certainly block on I/O and not relinquish control until the I/O was done (or never relinquish control at all). For example, Windows 3.1 was this way: if a single user process wanted to take over the entire computer, and prevent anything else from running, it could.

But on a system with multitasking you expect the system API I/O commands to relinquish control of the processor when they are called. So when a running process blocks on I/O, assuming that the process uses the normal system APIs, other processes will be allowed to run until the I/O is complete, and eventually the original process will resume once the I/O is done. In other words, calling a blocking I/O function is one way that a process on a cooperative system can voluntarily suspend itself.

If a running process blocks on i/o

Blocking on IO is pretty much equivalent to suspending your process. In the context of the linux kernel, executing some IO system call such as read() will cause a sysenter or interrupt handler to trigger to look after that IO, calling do_sys_read() ultimately. Here, if the current request cannot immediately be satisfied, the function calls sched() which then may execute another process.

In the context of a co-operative system, I would expect that when you make a system call for some IO reason, if the request cannot be satisfied the kernel picks another task and executes that. This document provides some background - basically, if you waited on IO, you could be hung forever waiting for that IO. The idea of co-operative scheduling being that you frequently call sched() or the equvalent relinquish-the-cpu method, if doing CPU-intensive tasks.

Kernel-mode considerations get more interesting. On architectures where they are available such as certain embedded platforms, interrupts handlers will still be invoked in response to hardware or software interrupts. It is usually possible, implementation-wise, to disable interrupt handling, but that also has drawbacks.

In the cooperative scheduling (preferably cooperative multitasking) model, there is no concept of a scheduler in a sense that the operating system does not have any control of how long the process runs.

An application programmed correctly would voluntarily give up the CPU on I/O. But, badly written applications might just keep waiting on I/O, thereby blocking other processes.

PS: This approach was later given up by most of the OS in favor of preemptive-scheduling (which had an external scheduler) and now we have all sorts of different scheduling algorithms used by different OS.

EDIT: My answer was based on the scheduling as described in its original form (years ago :P). As Gilles commented some systems still use cooperative scheduling. And there is a scheduler. I am not sure if those systems use COS in its pure and original form.

• Many embedded OSes (including but not limited to RTOS) have cooperative scheduling. This isn't to say there's no scheduler; the scheduler is the code that determines which thread to run next. Preemption is about the scheduler being entered automatically as opposed to upon the running task's request. – Gilles Mar 6 '12 at 20:24
• @Gilles Nice comment (putting into an edit). I agree with you that its not completely unused. My answer was just based on the algorithm as was defined originally. AFIK, it is used with some modifications (with some scheduler). I am not sure if it used in its pure form in some OS. – Ankit Mar 6 '12 at 21:05

Co-operative multitasking implies that an executing context must explicitly relinquish control to the scheduler, and if it wishes, can prevent a context switch from occurring.

Most implementations explicitly perform a context switch for any system call that does not return promptly, and often even if they do, to increase the fairness of processor allocation.

Usually it is only possible for failed processes (or intentionally denying service to the remainder of the system) to prevent frequent task-switching.

Pre-emption, as explained by Gilles, is a limitation of the architecture of the system that prevents timed interruption of the active task and forced context switches.