In the mid-sixties a lot of computer usage was oriented toward the production of paper listings. Even the most fervent advocates of time-sharing would routinely print out thick stacks of paper, both listings showing the source and compiled instructions of their programs and core dumps for analysis when a program failed. Mainframe systems printed their output on line printers, which typically used type slugs of some kind striking a carbon-coated ribbon against paper. A printer that could print 20 pages per minute was pretty fast.
The IBM 7094 that we used to develop Multics had a slow line printer directly attached to it, used only for system error and status messages; user printer output was collected by a CTSS process called the disk editor and written to tape, for printing on an offline IBM 1401. A standard 1401's printer had uppercase letters only; Project MAC's machine had a special RPQ to print upper and lower case.
The use of upper and lower case letters and the ASCII character set throughout was a Multics design choice that was leading-edge in the mid-sixties. It made processing of language as well as numbers more convenient, but it limited our choices of terminals and printers and required hardware and software implementation decisions and innovations in order to carry it out.
In the GE 645 architecture, the line printer was directly connected to the mainframe's I/O controller, and supported by spooling software. (I first heard the term "spooling" on an IBM 7070 system, where we used a package called Simultaneous Peripheral Operations On Line. Of course this acronym might have been a backformation.) The design for the 645 system included a special upper and lowercase printer, the PRT202. This device printed 132 columns at 600 lines per minute. Hammers behind the paper drove it against an inked ribbon when type slugs mounted on a drum were in the correct position. If the printer wasn't perfectly tuned up, and the hammers fired a little early or late, lines on the printer listing wouldn't be perfectly straight. The quality of the output, while usually readable, was not good enough for publication; for final output of documents, we used Flexowriters, then Selectric terminals like the IBM 2741, and later, daisy-wheel terminals.
The CTSS disk editor worked by searching the whole file system for files called OUTPUT RQUEST that listed files to be printed, and copying those files to tape. It therefore spent a lot of time looking for stuff that wasn't there, and would run slower as the amount of disk storage online grew. For Multics, we chose a different design: the Multics I/O daemon is a process that is always running: users request the printing of a file using a command (dprint, later called enter_output_request) that sends an interprocess message to the daemon. Since Multics IPC messages have only a 72-bit payload, the IPC message just tells the daemon that a request has been queued; the request details are passed in a ring 1 message segment. (Before message segments were available in Multics, the dprint command passed a message to the daemon by constructing a file system link with a coded target in a special append-only directory.)
The Multics I/O daemon also handles punched card input and output. Punched output is handled like printing, except that the data is sent to a different device. There are three possible formats for punched output: the daemon can
take each line in the file as a card image and translate the ASCII to card codes.
take 960-bit chunks from the file and map them to the 960 holes on a card.
encode the file in a compressed format, called 7punch, that includes checksums and sequencing to reduce errors.
Punched card output on the 7094's CTSS and FMS systems at MIT was preceded by special lace cards called FLIP cards, which spelled out the user's account number and the file in block letters you could read if you held the card up to the light. Multics continued this practice, but it was less satisfactory since user names and file names might consume many cards.
Card input on Multics requires that users provide special control cards to indicate who the input is for and what name it should be filed under; the daemon reads such decks into a "card input pool" directory and lets users copy their input, to prevent denial of service attacks. The other use of the card reader on Multics was to read the one-card bootstrap loader, until Bernie's Zero Six Dog hack.
One of the main uses for the system printers during Multics development in the sixties was printing system crash dumps. The 6.36 simulation environment worked like a traditional batch system, and could provide users with either a traditional core dump or a core image that could be interrogated interactively on CTSS with the GEBUG command. When Noel Morris and I took over debugging bootstrap1 from Nguyen Van Binh in 1967, the only way to take a dump was to use the low-level 635 RAID debugger and some tricky panel switch manipulation, to print to a printer directly attached to the system. In 1968, John Gintell wrote a slick standalone dump program that booted from the card reader; instead of dumping absolute memory, it dumped segments, interpreting the descriptor segment and page tables. This dump program booted from cards and was controlled by the CPU toggle switches and the EXECUTE button. It still printed only to a directly attached printer.
In the late sixties the dump program evolved into BOS and system core dumps were written to tape instead of the printer, so we could reboot the system sooner and print the dumps when service was restored. The BOS dump program was modified to dump virtual memory instead of physical: that is, the dump program could simulate taking page faults and display pages not in core. It could also interpret the APT and dump the per-process segments for all loaded processes. About 1970, BOS was modified to dump the system memory image into a disk partition (the FDUMP command) so Multics could format the dump after it rebooted.
Analyzing a dump that was most of a box of paper was an arcane skill, that depended on knowledge of system table structures and algorithms; while some pattern recognition was involved, most of the process was simply tracing through one of a few standard routes, unless the system memory tables had been corrupted. Several programs allowed the examination of dumps from on-line terminals, starting with GEBUG for 6.36 simulator dumps in the mid sixties; then online_dump (od) in the early 70s, interpret_fdump (ifd) in the mid-70s, and finally analyze_multics (azm) in the early 80s. These programs allowed an expert user to look at a system dump image interactively and diagnose system crashes without printing the dump to paper. Bernie Greenberg's ifd mechanized many of the standard dump analysis activities: its why command was often able to locate the immediate cause of a system crash automatically.
[Paul Green adds:] The first day or so that we had FDUMP was the day we set a record for the number of crashes in a single day! (My memory says 13, but I have no way of validating that; it was certainly more than 6). Printing the dump to paper took 60-90 minutes, as I recall. This limited the number of crashes one could take per day. FDUMP sped things up so fast that we could crash more often. People didn't consider it progress at first; not until the software was made more reliable. Looking back on it, it is amazing that we tolerated the poor reliability and availability figures of that day. Our test procedures were really poor.
Performance of the printer daemon was an important issue, of course. In early versions of Multics we found that the printers would just stop when time-sharing load got too high. The efficiency of the code that drove the printer received a lot of attention and rewrite, and this helped, but not enough. The only way we could keep critical daemon processes running was to give them artificially high scheduler priority, and they then tended to take a large amount of system resources. The rewrite of the scheduler by Bob Mullen about 1975 gave us "realtime" classes, so that we could put the printer drivers in a class that got enough response to keep the printers going at full speed without letting them sink the system.
In the early 70s, I made various improvements to the I/O daemon to produce a better looking header page and a tail page that showed the user the cost of printing the output. I implemented "big letters" on the header and tail page, like those used on the FLIP cards, and designed upper and lower case alphabets for them. (Source code is available online.) Inspired by local features of MIT's OS/360 batch system, I also changed printer setup, specifying a printer carriage tape the length of two pages, and trained operators to set the paper up on the printer so that the header sheet was always on an outside page.
The bottom of the header page had a few rows of characters printed right over the page perforations, to aid in separating output jobs. In addition, I invented another job separation aid: the daemon assigns a "print job number" sequentially to each job printed on a device, and prints that number in all four corners of the head and tail page, so that an operator can easily check for correct separation. This number, and the name of the physical printer used, is also included in an optional interactive message sent by the daemon when your job finishes printing, which helped users find their output when it got misfiled.
When the Access Isolation Mechanism was added to Multics in the early 1970s, one requirement was for "security labeling" of printed output. Top secret output had to say TOP SECRET at the top and bottom of every page, and be printed only on printers that were designated for top secret output; and so on for every other classification. To support this, the I/O daemon had to be restructured somewhat: additional labeling fields were added to the print request and additional control arguments for the dprint command, and the print driver code was modified to print labels if they were needed. The classification was also printed in big letters on the head and tail pages.
The I/O daemon also supports remote printer/reader/punch stations such as the IBM 2780 and 3780, accessed over phone lines. These devices were popular with the large batch machines of the time, and are also supported by Multics.
Support in the I/O daemon for devices besides line printers was added at the end of the 70s and during the 80s. Honeywell made high-volume Page Printing Systems that could print hundreds of pages a minute, and Multics software was written for these devices. We also added support for several kinds of laser printers. Some of the clever line printer oriented hacks like printing through the perforation didn't work for laser printers, and we had rethink some of our features.
Thanks to Bernie Greenberg, Paul Green, and Dave Vinograd for their comments.
04/28/95, updated 02/27/96