Previously I discussed the GNU Pth library which implements cooperative multi-tasking for the C programming language. That's pretty low level. But I recently read about cooperative multi-tasking at an even lower level: inside the microcode of the Xerox Alto central processor! It's hard to get much lower level than that.
The engineers at Seattle's Living Computers museum maintain a blog where they write about their experiences repairing and maintaining the historic computers that make up the museum's exhibits and fill its labs.
In a two-part series (1, 2), one of the engineers discusses the Xerox Alto, the first computer designed specifically to run a graphical user interface. Graphical user interfaces were very new at the time, so there was a lot of experimentation to do. In order to make that experimentation quick and easy, the very CPU of the Alto was itself programmable in microcode.
The second article discusses the microcode in detail. Microcoding CPUs may have been uncommon in 1973 when the Alto was created, but it's common enough today that most computer science programs will include an introduction to it, so there was nothing too surprising. Until I got to the bottom in the section called "Tasks":
To allow the devices in the Alto to share the Alto's processor with minimal overhead, the Alto's designers developed very simple cooperative task-switching hardware.
Conceptually, the processor is shared between sixteen microcode Tasks, with a priority assigned to each one: Task 0 is the lowest priority task, and Task 15 the highest. Each device in the Alto has one or more tasks dedicated to it. To make task switching fast and cheap to implement in hardware, the only state saved by the task-switching hardware for each Task is that task's program counter — the MPC ("Micro Program Counter"").
Only one task is running on the processor at a time, and at any time the microcode for a task may invoke a "task switch" function (named, strangely enough, TASK). When a TASK instruction is executed, the processor selects the highest priority task that needs to run (is "Requesting Wakeup") and switches to it by jumping to the instruction pointed to by that Task’s MPC.
Wow—greenlets implemented in hardware! I've read about a lot of CPUs, and this is the first time I remember reading about one with cooperative task-switching at the microcode level.
It's a stretch to call this gevent for hardware, of course. (For one thing, there doesn't seem to be any concept of an event loop.) But programmers still had to worry about yielding to other "greenlets" in a timely fashion:
Since the Alto’s Task system is cooperative (meaning that task switches only happen when microcode explicitly requests them) the microcode for each task must be careful to yield to other tasks every so often so that they don’t get starved of time. If the Disk Word Task is late in execution, data from the disk is corrupted. If the Display Word Task doesn’t get enough time, the display will flicker or display glitches.