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.