The CTSS supervisor

The supervisor is at the heart of the CTSS system and operates similarly to what we'd call a kernel today. Let's look at each of its functions, comparing them to modern systems to get a feel of what is different.

Hardware

/images/ctss/ctss-hardware-diagram.png Diagram of CTSS hardware. Source: Rupert Lane. License: CC0.

The hardware controlled by CTSS changed over its lifespan. This is the setup that matches the CTSS source code used in the emulator. Most I/O work was done by channel controllers which offloads some of the work from the CPU. Each channel can have up to 10 devices connected to it. User programs cannot access components directly, they need to go through supervisor services.

Memory

There are two separate 32kW banks of memory, known as Core Memory A and B. Note each word is 36 bits, so that's the equivalent of around 147 kilobytes in each bank. As the 7094 can only address 32kW at a time, these are switched between as needed. The supervisor sits in Core A at all times. User programs are brought into Core B as requested by the user, and may be swapped out to drum or disk as CTSS schedules other tasks to run. The maximum memory available to a task is 32kW and there is no concept of virtual memory; however several smaller tasks can be in memory at the same time.

Tasks

A fixed maximum number of users can be logged in at any time (30 is the limit on the emulated system). Each user can only have one task active, so could not login twice simultaneously or create (fork) a new task while an existing one is running.

There is no equivalent to a shell as a separate user program. Logged in users type in commands which are processed by the supervisor. Commands and their parameters can each be up to 6 characters long. Commands can be either system programs (eg LISTF) or user created programs and are treated the same way: the supervisor will load the program into core B and transfer to it. Once a task is completed, control is returned to the supervisor.

Each task can be in a particular state, such as working, waiting for I/O etc. Two special states refer to the task after it is completed: dormant means the program has finished but is still in core so can be restarted or the machine state analysed. Dead means the program is out of core.

Scheduling

The scheduling algorithm for CTSS evolved over time as experience was gained using the system. As of the later system it had nine priority queues, ordered so that smaller or newer tasks would get a small amount of CPU time quickly, and longer running tasks would run less frequently but get more CPU time when it was being run.

It is also possible to run background tasks at a lower priority. This included jobs submitted by users from the online system (called FIB jobs) as well as non-time-sharing aware jobs, such as batch or standalone 7090 programs. This ability to run pre-CTSS jobs explains the 'Compatible' in the OS's name.

Protection

CTSS applies relocation to each task so it can be placed anywhere in memory without the task being aware of its physical position. The system also keeps track of what areas of memory the program is using, so any access outside of there leads to a protection violation and the program being terminated.

Further reading

The original paper by Fernando Corbato is available at the ACM. It describes an earlier version of the system we have today, but also includes information on why the system was developed.

The CTSS Programmer's Guide section AA gives more detail on the supervisor.

Bob Supnik's analysis of CTSS hardware was also useful in understanding how CTSS worked and is emulated.

Questions, corrections, comments

I welcome any questions or comments, and also especially any corrections if I have got something wrong. Please email me at rupert@timereshared.com


Early software on the IBM 7x

In the beginning, there was nothing. At the launch of the 701 in 1952, IBM would happily sell (or rent) you a computer, but it came with no operating system and no high-level compilers, as these did not exist yet. What you had was machine code and some early assemblers.

Indeed, IBM was not really in the business of selling software at all. IBM would facilitate meetings amongst its customers on ways to program its computers. Techniques to automatically assemble machine language programs were discussed, but each site would adapt these for its own use. Over time, through user groups such as SHARE, assemblers and subroutine libraries were distributed and improvements suggested. An example of some of these for the 704 can be seen at Richard Cornwell's page.

Using the computer without an operating system

How then was the computer used?

/images/ctss/701-programming-example.png

Sample hand written program for the 701. Source: IBM's early computers by Charles J Bashe.

According to George F. Ryckman, who worked with a 701 at General Motors Research Laboratories in the early 1950's:

Each user was allocated a minimum 15-minute slot, of which time he usually spent 10 minutes in setting up the equipment to do his computation. He mounted his own tapes and set up the card reader, card punch, and printer to carry out his computation. By the time he got his calculation going, he may have had only 5 minutes or less of actual computation completed-wasting two thirds of his time slot.

For the programmer, this was not a great experience as they had limited time to debug their programs. For the computer owners it was even worse, given the great expense of the machine, most of the time the CPU was sitting idle as programmers set up their program and tried to work out what was going on,

Early high level languages

The idea of a programming language operating at a higher level than assembly had been discussed since the 1940s, with one of the first fully working ones being Short Code for the UNIVAC. Assembly language programmers expressed scepticism: running a compiler would add to the time taken to produce the machine code, and how could code produced by a compiler compile to their own hand-optimised code?

/images/ctss/fortran-manual-cover-1956.png

Cover of the 704 Fortran manual. Source: IBM Manual at bitsavers.org

Fortran, developed between 1956 and 1957 by John Backus and a team at IBM, helped answer these questions. It had a syntax that allowed easy translation of mathematical formulae into code and was fairly quick to run. Scientists and researcher adopted it quickly, and it spread to many other contemporary computers.

A simple Fortran program to print Hello World 5 times:

C     HELLO WORLD PROGRAM
      DO 10 I=1,5
      WRITE (6,20)
10    CONTINUE
      STOP
20    FORMAT(13H HELLO, WORLD)
      END

Another early language was MAD, the Michigan Algorithm Decoder. Developed at the University of Michigan in 1959 for the 704, it provided a more English-like syntax inspired by early drafts of the Algol language, and had a fast compiler.

The equivalent of the above program in MAD:

*     HELLO WORLD PROGRAM
      THROUGH LOOP, FOR I=1, 1, I .G. 5
          PRINT COMMENT $HELLO, WORLD$
LOOP  CONTINUE
      END OF PROGRAM

Batch operating systems

High level languages like these helped speed the development process, but the problem of efficient machine utilisation was still present.

The solution to this was batch processing. A series of jobs for several programmers could be grouped together into a batch of work that could be executed by the computer in sequence with minimal set up time. Programmers would submit their code and running instructions to the operator, who would prepare a set of tapes to load into the computer and execute. After the batch was run, a tape containing items to print or punch to cards would be transferred to a smaller computer, and the physical paper/cards delivered to the programmers.

The development of these batch operating systems again started with customers contributing and sharing code: examples are the SHARE Operating System and Bell Labs' BESYS. Eventually, IBM adapted the Fortran Monitor System (used at MIT) and released this as IBSYS.

An example of a set of control cards to compile the above Fortran code, run it and produce a listing.

$JOB           HELLO WORLD
$EXECUTE       FORTRAN
$ID    HELLO
*      XEQ
*      LIST8

Along with increased utilisation, this helped efficiency as jobs had to be submitted in a way that was understandable by the computer. The set up tasks were also done by experienced operators who used the machine constantly rather than programmers who did not.

The disadvantages were latency and lack of debugability. It could take hours or days for the batch to finish and each programmer to receive their output. Minor errors in the program that could have been quickly fixed in the "open shop" method of operation would now have to wait for the next batch run.

The solution to this was time-sharing, of which CTSS was one early example. Next time we'll look at CTSS, starting with the supervisor.

Further reading and things to try

Questions, corrections, comments

Please email me at rupert@timereshared.com and I will update this page.


The IBM 7094

Running CTSS under emulation can help us understand the operating system, but it's important to put it into context by looking at the hardware it actually ran on.

/images/ctss/ibm-7094.jpg

The IBM 7094. Source: IBM CE manual

Big, fast, expensive

The IBM 7094 was big, taking up a large room at the MIT computer centre for its CPU and peripherals.

It was one pf the fastest computers available in the early 1960s.

It was also very expensive: a typical system sold for $2.9 million (equivalent to $23 million in 2023) or could be rented for $63,500 a month (equivalent to $501,000 in 2023) (from Wikipedia).

All this meant that very few sites could afford one - mostly universities and large corporations with extensive need for scientific computation facilities.

The 700/7000 range of computers

From 1952 IBM had developed a range of computers, first using vacuum tubes and later transistors. The table below shows how their scientific range evolved - there were also commercial application versions that were not completely compatible with the scientific models.

Year Model Logic Memory Notes
1952 701 Tubes 2kw Williams tubes aka Defence Calculator
1954 704 Tubes 4-32kw core First h/w floating point
1958 709 Tubes 32kw core First indirect addressing
1959 7090 Transistors 32kw core 6x faster than 709, ½ the price
1962 7094 Transistors 32kw core 2x faster than 7090
1963 7040 Transistors 32kw core Scaled down version of 7090
1963 7044 Transistors 32kw core Slightly faster version of 7040
1964 7094II Transistors 32kw core 2x faster than 7094

MIT had a 704, then a 709 which was the first machine to get CTSS. They upgraded through 7090 - 7094 - 7094 II and had a second machine to support Project MAC.

CPU and memory

The 7094 had a 36 bit word size and could directly address up to 32kw of core memory (so around 144kB - bytes as a standard measure of memory had not yet been standardised).

It has a single main accumulator and a multiplier/quotient register for multiplication and division. It has four index registers allowing indirect addressing. Numbers were stored in sign/magnitude form, with the top bit the sign and the remaining 35 bits the number.

At the time there was no standard for text encoding like ASCII; the 7094 used 6-bit BCD encoding, allowing only numbers, capital letters and some punctuation symbols.

For CTSS, MIT requested an additional 32kw of memory used in a bank-switched manner, so one bank was for the supervisor and the other bank could be fully utilised by the client program.

Storage

The primary storage mechanism for computers at the time was magnetic tape. This offered fast sequential read/write but due to the linear nature of tape could be slow for random-access. Installations would often have multiple tape drives: for a batch Fortran compile run for example, there could be one tape for the compiler, one for the input program, one for scratch storage and one for the output object, all being used at the same time. CTSS used tapes for user file storage on early versions before the disk was available; after that it was used for bulk file input and backup. Each tape could store around 3MB and could be read at several hundred bytes per second.

Random-access storage was done by what IBM called DASDs (direct access storage devices) and what we'd now call drums and hard disks. The 7320 drum was a cylinder with one head per track that could store 174,000 36 bit words. CTSS used this for swapping and some file storage.

The 1301 hard disk was one of the first commercially available hard disks and could store 28MB of data. It spun at 1800 rpm and could transfer around 90,000 bytes per second. CTSS used this for file storage. If you wanted to buy one, it would cost over $100,000 in 1963 dollars.

Input/output

The console had switches and lights for the operator to toggle in values, view the state of the computer and start operations. There was also a line printer for logging.

User data could be fed into and out of the machine by punched card. Each card holds 80 characters. In practice this was not used for regular user input as it was too costly in CPU cycles; the user would instead punch data to cards using an off-line punch; the cards would be transferred to tape via a smaller computer and finally the tape loaded into the 7094.

What is missing here is interactive input/output. MIT requested IBM to build a data concentrator to handle multiple serial lines and used this to attach teletypwriters like the one below. It was also possible to connect over the telephone wires using an acoustic coupler.

/images/ctss/teletype-model-37.jpg

Teletype Model 37. Source: Wikipedia. License: CC BY-SA 4.0

There was also an experimental graphical display connected to the IBM via a PDP-7, but this is not supported by the emulator.

Other peripherals

There were also a number of other items requested from IBM by MIT to support CTSS:

  • Trapping I/O operations to interrupts so they could be handled by the supervisor
  • Memory protection and relocation
  • A real time clock and interval timer

Further reading

Much of the information on this page came from Wikipedia. Another great source is Tom Van Vleck's page on multicians.org about CTSS.


CTSS: A quick tour using s709

In this post I will show how to get CTSS running using the s709 emulator.

/images/ctss/s709-and-login.png

Running s709 and a login session. Source: Rupert Lane. License: CC0.

Get the kit

We'll use my eliza-ctss repo to get set up as this automates several of the steps involved. You can also get the components directly from the s709 page and set it up following the instructions there - both methods will yield the same system.

You will need a Unix like environment that can compile C code, run shell scripts etc. You will also need a telnet CLI or GUI client.

Start by cloning the repo and changing into its directory. All commands will be run from there.

  $ git clone https://github.com/rupertl/eliza-ctss
  $ cd eliza-ctss

Set up the system

(Numbers in square brackets refer to notes below, do not enter these on your terminal.)

  $ source env.sh                    [1]
  $ make-binaries                    [2]
  $ make-disks                       [3]
  $ format-disks                     [4]
  $ install-disk-loader              [5]
  $ installctss                      [6]
  1. Set up the path and environment variables needed. Run this before any other commands.
  2. Compile the s709 and utility binaries, and place them into ctss/bin.
  3. Create files in dasd/ representing the disk and drums needed for CTSS.
  4. Format the disks and drums. You will be prompted to press Enter a few times and type q and Enter when done. This may take 60s.
  5. Install a basic disk loader on the disks to prepare for the full CTSS install.
  6. Install the base CTSS components on the disks.

Start the system and log in

  $ source env.sh
  $ runctss

This will start CTSS and begin accepting logins. The simulator window will show log in/out activity.

In another window, telnet to port 7094 on your local machine. Type login guest and at the password prompt type system.

$ telnet 0 7094
Trying 0.0.0.0...
Connected to 0.
Escape character is '^]'.
s709 2.4.1 COMM tty0 (KSR-37) from 127.0.0.1

MIT8C0: 1 USER AT 12/30/14  852.7, MAX = 30
READY.                                     
      
login guest
W 852.8
Password
 M1416     5 LOGGED IN  12/30/14  852.8 FROM 700000
 LAST LOGOUT WAS  12/25/14 1626.0 FROM 700000      
 HOME FILE DIRECTORY IS M1416 GUEST          
                                   
THIS IS A RECONSTRUCTED CTSS SYSTEM.
IT IS A DEBUG AND NOT FULLY FUNCTIONAL VERSION.
                                               
 CTSS BEING USED IS: MIT8C0
R .050+.000

Your two windows should now look like the image at the top of this post.

Orientation

  • CTSS communicates in upper case, but you can type in lower case and it will be translated to upper automatically.
  • There is no prompt, but you will know CTSS is ready for input when it prints R followed by 2 numbers (which represent the CPU time and swapping time for the last command run).
  • Delete will delete the last character and Control-U will kill a whole line. This is an affordance of the emulator; on a a real teletype you'd type # to delete and @ to kill; these keys still work as such on the emulator.
  • Control-C will interrupt a program and Control-\ (backslash) will quit it.
  • Commands are in the familiar format of the program name followed by parameters. Optional arguments are enclosed in brackets.
  • When you enter a command, CTSS will first type something like W 1724.3. The W means you are waiting for the command to load and the numbers are the time of day the command started (using tenths of minutes after the decimal point).

Looking at directories and files

CTSS has the concept of a Master File Directory containing several User File Directories, one for each user. It is not possible to make further sub-directories. There is the concept of a shared directory which we will look at in a later post.

To view the contents of your directory, type listf.

listf 
W 1305.9
        
     9 FILES    90 RECORDS
 NAME1  NAME2 MOD NOREC   USED
  CQA1    MAD 000     3 12/30/14
 HELLO    MAD 000     1         
PRIMES MADTRN 000     2
MYLISP  SAVED 000    77 12/26/14
  FACT   LISP 000     1         
DEFINE   LISP 000     2
 FFACT   LISP 000     1 12/13/14
PROCAL   LISP 000     2         
BOTTLE    MAD 000     1
                       

R .016+.016

You can give parameters to change the display order and select which files are printed. For example, to show MAD source code files in alphabetic order:

listf (sna1) * mad
W 1328.5
        
     3 FILES     5 RECORDS
 NAME1  NAME2 MOD NOREC   USED
BOTTLE    MAD 000     1 12/13/14
  CQA1    MAD 000     3 12/30/14
 HELLO    MAD 000     1         
                       

R .016+.016

File names have two parts, called name1 and name2, each up to six characters long. Note the first and second parts are not separated by a dot, so what we'd call "hello.mad" would be "HELLO MAD" on CTSS. The first part of the name is called name1, hence the parameter to sort by name1 is (sna1). As shown, you can use * as a wildcard.

You can print a file to the console with P. This will include some blank lines at the end so you will need to scroll up your terminal to see it.

p hello mad
W 1332.4
        

	 VECTOR VALUES HELLO = $12H HELLO WORLD*$
	 PRINT FORMAT HELLO                      
	 END OF PROGRAM    


         
R .000+.033

Compiling and running a program

Let's compile and run the above file.

mad hello (list)
W 1333.7
LENGTH 00020.  TV SIZE 00003.  ENTRY 00011
R .016+.033

As the name2 of the file was MAD, we don't need to give it. If the file had been called hello mymad we'd have entered mad hello mymad.

The compile did not produce any errors. If you do a listf for files you will see two new ones.

listf hello *
W 855.3
       
     3 FILES     3 RECORDS
 NAME1  NAME2 MOD NOREC   USED
 HELLO    MAD 000     1 01/05/14
 HELLO    BSS 000     1         
 HELLO    BCD 000     1
                       

R .016+.016

The BCD file contains a listing of the compilation. The BSS file contains object code.

There is no separate linker step required to get this in a runnable state. Instead, the loader will bring this into memory and find any called routines. By typing LOADGO you can then run ut immediately.

loadgo hello
W 1335.0
EXECUTION.
 HELLO WORLD
  EXIT CALLED. PM MAY BE TAKEN.
R .166+.016

Logging off

Type logout. The system will also log you off after a period of inactivity. You can start the telnet session again if you want to login again.

CTSS will support up to 30 simultaneous users, but note if you are already logged in with a certain user ID, you cannot start a second session.

Shutdown

It's important to shut down CTSS cleanly when finished to avoid corrupting its disks.

You will need to switch back to the main emulator window you started earlier - this cannot be done from the telnet session.

Execute the following, pressing Enter after each non Control-C line.

  • Press Control-C
  • Type ek 40017
  • Type st
  • Press Control-C
  • Type ek 0
  • Type st
  • Press Control-C
  • Type ek 40032
  • Type st
  • Type q and Enter to exit.

What is going on here? On the real IBM 7094 the operator would initiate shutdown by toggling in a value on the front panel (ek, for enter keys, in the emulator)

You can start CTSS again by running runctss as before.

Dealing with disk errors

If you forget to do the above, or your machine crashes, or if there are any problems starting CTSS again, all is not lost. Run this command to do the equivalent of a fsck or chkdsk.

  $ source env.sh
  $ salvagectss

You will need to type st a couple of times to start the machine. When the output says QUIT, type q.

Further reading

The CTSS Programmer's Guide section AA.2 has a contemporary "Time-sharing Primer" showing nee users how to perform simple tasks.


Compatible Time-sharing System

CTSS, the Compatible Time-sharing System, was probably the first time-sharing system. Developed in the early 1960s at MIT, it ran on a IBM 7094, supporting up to 30 users on a system with just 64kwords of memory and a clock speed well under 1MHz.

/images/ctss/video-montage-corbato.jpg

CTSS project director Fernando J. Corbató (shown here wearing a bow tie) demonstrates CTSS in 1963 to a reporter from WGBH. Source: Youtube.

Some of the key innovations it brought were

  • Users could develop and run programs interactively using teletypwriters.
  • Access was protected by logging in with a user name and password, and each running task could not interfere with others.
  • It used a disk drive for storage, with users' work partitioned into directories and divided into files.
  • It enabled the development of ELIZA, the world's first chatbot, along with document preparation tools and a form of email.

Although it only ever ran on two computers at MIT, it was very influential: many of the CTSS engineers went on to develop Multics, and ideas from CTSS contributed to other OS. Using it today, it seems very familiar to those used to the Unix command line.

Preservation status

There is a good amount of documentation at bitsavers.org covering the machine and the operating system. Probably the best reference is the Programmer's Guide.

The original source code for CTSS was found on a backup tape 20 years ago and has been reconstructed into a version runnable on two emulators

  • s709, by David Pitts
  • simh, by Richard Cornwell

We will use s709 for most of the work on this site as it is slightly easier to use.

Topics

On future pages I plan to cover:


Next →