Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!ucbvax!amdcad!rpw3 From: rpw3@amdcad.AMD.COM (Rob Warnock) Newsgroups: comp.protocols.tcp-ip Subject: Interrupts & Polling [was: Re: Super Cheap IP router (< $1000)] Message-ID: <25223@amdcad.AMD.COM> Date: 14 Apr 89 04:36:46 GMT References: <8904140206.AA10084@ucbvax.Berkeley.EDU> Reply-To: rpw3@amdcad.UUCP (Rob Warnock) Organization: [Consultant] San Mateo, CA Lines: 71 dcrocker@AHWAHNEE.STANFORD.EDU (Dave Crocker) writes: +--------------- | Interrupts kill... | An interrupt is very useful when you don't expect much activity and don't | want the overhead of polling. On the other hand, if you DO expect heavy | activity, polling is quite nice... | Many, occasional sources of activity warrant interrupts. | A few, active sources warrant polling. +--------------- Which is why the two-level interrupt service structure I wrote a "tutorial" about in comp.arch (circa 3/20/89?) does exactly this, although that was not one of the points I stressed in that article. In the absence of interrupt activity, you are "interrupt driven". But once you get an interrupt, additional interrupts are queued on a lightweight task queue, and [this is the part I left unstressed] every second-level interrupt routine checks for more work of its own type before exiting, and if there is any, requeues itself on the tail of the task queue. [This promotes fairness. And of course, you can have multiple 2nd-level interrupt queues/priorities if you like.] Thus, once fired up by a 1st-level interrupt, the 2nd-level interrupt service layer is *polled* -- exactly as you requested! This has the nice behavior that a full interrupt context save/restore only has to be done once for each "burst" of interrupts (and in timesharing systems, interrupts *are* "bursty"). I once wrote a PDP-8/e communications kernel which, using this approach, was able to handle 10,000 characters a second *through* the node. Interrupt per character, on each side, or 20k ints/sec. If you have a *large* number of sources of data to service (such as *many* async terminal ports, say more than 100, as on that PDP-8/e), and you have some very-light-weight 1st-level hardware interrupt mechanism (such as the Am29000's "freeze mode"), then using interrupts as "asynchronous polls" can save you some polling overhead while still not requiring a full context save. That is, hardware interrupts remain enabled even while the 2nd-level service routines work. This is a useful tradeoff even on some CISCs [such as the MC68000 -- though not the '020], where the 1st-level catch-the-data/queue-the-2nd-level-task function can be done without very much save/restore overhead. Like Dave's experience, I have seen this technique result in a factor of *12* improvement in the TTY-handling capacity of a 68000-based Unix. Note that this "interrupt/polling" switchoff has a direct analogy to those link-level access protocols which attempt to provide low latency under light load and good efficiency under heavy load. I'm talking about things like the "Urn" protocol and some forms of "reservation/TDMA" or "random-access/TDMA" which have a contention phase which degenerates into round-robin under load. There are also some forms of "virtual token bus" which deliberately drop the token under light load, reverting to a contention mode. [Sorry I don't have access to formal references on these handy, as I hear a flood of "Tell me more"s already. Anybody else?] Anyway, the point is that any good design provides a smooth *dynamic* tradeoff between latency and efficiency. p.s. I personally feel that the FDDI standard is oriented too far to the "efficiency" side; on maximal configurations of FDDI, the "packet exchange" time (say, an NFS disk block request/response) on a lightly loaded net can be over 3 milliseconds -- that's worse than Ethernet! Rob Warnock Systems Architecture Consultant UUCP: {amdcad,fortune,sun}!redwood!rpw3 DDD: (415)572-2607 USPS: 627 26th Ave, San Mateo, CA 94403