The figure is OS specific, and hardware specific. So, no, I can't.
I can tell you what I know concerning the AmigaOS 2.x architecture though. For starters, boot-up occurs in a task. In order to support asynchronous I/O, all device drivers spawn their own tasks (this is not a system requirement, but it's what they do to maintain the Amiga's responsiveness. This is largely why a 7MHz Amiga feels more responsive than Linux on a 200MHz box). You might have the following device drivers in a typical Amiga these days: trackdisk.device, scsi.device, perhaps ide.device if you have an ATAPI controller attached (a la Amiga 600). Then, for each major category of device hanging off a particular bus, you might have a task waiting for events. Events come from two sources: applications queueing IORequest blocks, or hardware-generated interrupts. This allows the system to handle interrupts from device units in user-mode, thus again improving system response times.
For example, the handler for DH0: is a task which schedules requests to a filesystem handler task. This task issues calls to a supra.device unit, representing a harddrive. supra.device is responsible for formulating the required SCSI packets that need to go over the SCSI bus, but it defers that action to scsi.device. This architecture is required because I might have non-Supra equipment hanging off the bus (e.g., a scanner, for example). So, scsi.device multiplexes and schedules transactions on behalf of its clients, without knowing who those clients actually are. A task is used instead of a flat binary responding to interrupts because of SCSI's split transaction support. In fact, when you hear SCSI advocates thump their chests about the "multitasking" capability of the bus, this is what they're talking about.
An aside: Note that USB works the same way. You must have a driver for USB host controller, able to schedule packets to transmit and receive over the bus. This driver behaves more like a network driver than what most people think of as a device driver. You also need individual drivers for peripherals too (e.g., keyboards, webcams, etc), because they don't have direct access to the USB host controller. If direct access to the controller were the norm, it would result in monopolizing the resource, which actually slows things down, or even prevents concurrent use from happening at all. E.g., you couldn't type on your USB keyboard while printing to the USB printer.
Anyway, back to the Amiga -- then you have the user interface itself. Intuition's input handler (appropriately named "input.device") runs as a separate task, taking input from keyboard.device, trackdisk.device, game.device, and timer devices. Its job is to serve as a centralize message queue for all system events. Hooking into this system allows you to implement screen savers without patching ROM vectors, support new input devices for the disabled (as long as they can emulate a mouse or keyboard), or even change or synthesize input events (allowing, for example, one to write a virtual KVM, letting you wrap your mouse between screens of multiple computers, assuming you had a network between them). This must run as a separate task because, if it didn't, then any faulty application will hang the entire machine.
Intuition itself is a separate task in the input.device handler chain, which is responsible for parceling messages out to individual applications. This is how applications actually receive and respond to input events. Classes of input events includes key up/down, mouse button up/down, mouse moved, gadget clicked, disk inserted or removed, etc.
So to run a single application on a minimally equipped Amiga (say, Amiga 1000), you have, as a conservative guess:
* Boot-up thread used to bootstrap the machine.
* Trackdisk thread for floppy unit 0 (DF0).
* Mouse driver thread.
* Keyboard driver thread.
* game.device thread to coordinate those two.
* input.device thread to coordinate game.device events along with other system events.
* timer.device to handle microsecond-precision timing with a single CIA timer, multiplexed across *ALL* other system tasks (I'm not fabricating this either; resolution is as small as 20us with careful coding techniques).
* Intuition task to manage input.device and coordinate event handling among user applications.
* console.device task to manage VT-100 emulation asynchronously from applications (allows apps to write data to the screen at the same time as the blitter is finishing up the previous update, thus allowing the screen to scroll as fast as a text-mode display, even though it's not)
* The filesystem handler task, which interprets dos.library function calls Open(), Close(), Read(), etc. into low-level trackdisk.device calls.
* And, finally, your user application, which coordinates amongst the various other system tasks via several convenient library interfaces.
That's a total of 11 (or 12, if I miscounted) tasks, cooperating on a minimally configured AmigaOS 1.x system on an Amiga 1000.
My Amiga 500 with AmigaOS 2.04 spawns one thread *PER DEVICE* at BOOT-UP, thus making bootable volume discovery effectively O(1) time, instead of O(n) time, which makes booting the machine much faster.
Note that each task is a small, self-contained program. You talk about building single-purpose (at any given time) 6502 systems using SPI and I2C ports to communicate with the outside world -- this is the software equivalent, where you have several cooperating tasks talking to each other through message passing.
Now, on Linux, I don't have any understanding behind why so many kernel threads exist. The reasons behind spawning a thread or process are generally the same as in the Amiga -- more modular, easier to debug if/when problems occur, etc. But the POSIX memory model, where each process has its own memory space, also means greater reliability (usually) -- in theory, I can crash most processes, and simply restart them without having to reboot the machine.
For example, I've had xpdf lock up my X windows session (standard GUI architecture on Unix-alike systems) on numerous occasions. The fix is simple: using another computer, SSH or telnet into the box, and kill xpdf. That will restore the X session. If something like this were to happen on Windows, you're SOL -- you have to do a hard reboot.
In fact, the very ability to SSH/Telnet into my machine isn't possible without multitasking, because who would respond to a network packet to port 22 or 23? Your CAD software doesn't have a clue, nor a care, about what happens on that port, so it certainly wouldn't respond. However, when SSH runs, the sshd daemon (pronounced "demon", thus explaining BSD's choice of mascot. A daemon is a background server, kind of like a TSR in DOS) accepts connections on port 22, and kicks off a virtual console. Thus, I can control my computer from another computer, remotely.
|