Interrupted Again

Previous Home Next

Yesterday evening as Jo and I walked along the beach, I was thinking about what to write for the next entry in this journal. I thought about the CPU dancing across a sea of binary numbers processing billions of instructions per second. I thought about my writing programs, compiling them into binary numbers and then causing the CPU to buck and swerve in its dance to carry out the instructions corresponding to my compiled code.

I was listing the concepts that I thought might be worth mentioning and I realized that I was moving from computer architecture, the sub discipline of computer science concerned with the logical design of computer hardware, to operating system, an area concerned with the software that provides the interface between the hardware and applications and user interfaces that most of us spend out time interacting with when we use a computer. In compiling my list of concepts, I was struck by how many "computerese" terms and phrases, e.g., interrupt handling (responding to an unexpected event while in the midst of doing something else) and multi tasking (the concurrent performance of several jobs), have slipped into the vernacular.

Computerese is jargon used by computer technologists. I don't know what you'd call the jargon used by psychologists and cognitive scientists to describe how humans think. The word "mentalese" is already taken; the philosopher, Jerry Fodor, postulates that humans represent the external world in a "language of thought" which is sometimes called "mentalese." Fodor's mentalese is more like the machine language for minds. I'm talking about the language that we use to describe how we think, how our thought processes work - a meta language for talking about thinking.

Much of what I was coming up with was concerned with how multiple computer processes (and mental processes) can operate concurrently. In the case of most computers, processes only appear to be running at the same time when in fact they are running on same processor (CPU) that is switching back and forth between the processes very quickly. I was thinking about this largely because of the robot example I'd used for the machine language program and reflecting on how often a robot has to perform several tasks at the same time: controlling the motors while looking for a bright light, while avoiding running into obstacles, while checking on the batteries, etc.

In the lingo of operating systems, processes are relatively heavy-duty computations which function independently for the most part. These heavyweight processes are powerful but they generally take a fair bit of time and memory to create and maintain. There are also lightweight processes, often called threads that are easier to create and maintain but don't come with so many bells and whistles. Processes of all sorts can create their own child processes, and, as terrible as it sounds, a parent process can kill it's children or put itself to sleep. An application such as a word-processing program is typically implemented to run as a single heavyweight process with several lightweight threads of control to handle such tasks as spelling and grammar checking, reading keystrokes and mouse movements, and managing the display of text and graphics.

The CPU can handle only one instruction per clock cycle and processes vy for those cycles. (Actually this isn't generally true; many modern computers have multiple ALUs and special circuitry that allows them to carry out multiple instructions at the same time. But even so there are generally many more things to be done than there things to do them on.) Every process is assigned a priority that will determine what share if any of the CPU's cycles the process is allocated. If you're a process with low priority, you'll have to wait until all of the processes with a higher priority are done before you'll get your shot at the CPU. If you're one of several processes with the same priority and there are no processes ready to run with a higher priority, then you'll get a slice of the CPU equal to that assigned to all of the other processes in your cohort. Short intervals of time are doled out to each of the processes; perhaps you'll be allowed to execute a few hundred or a few thousand instructions before your allotment is up. But the CPU will switch between the processes so quickly that it will seem like each process has it's own CPU. The part of the operating system responsible for switching between processes is called a task manager.

A process corresponds to a program running. Think about the machine language program that we looked at yesterday. If we were to interrupt a program corresponding to one process in order to allow the program corresponding to another process to run, what would we have to do? For a simple program like the light-seeking program we wrote yesterday, we'd have to remember where we left off - the address currently in the program counter, and we'd have to remember whatever it was that the program was working on - the current contents of the other registers. Then, the next time the program gets a chance at the CPU, we would restore the program counter and the other registers and let the program run for another slice of time.

We'd need some extra hardware to keep track of these short intervals of time but all that amounts to is counter since we already have a "clock" that generates a steady stream of pulses. If the clock pulses 1 thousand million times per second (1 Gigahertz or perhaps Giga Hertz since the unit of frequency corresponding to one cycle per second is named after a German physicist by the name of Heinrich Rudolf Hertz who lived from 1857 to 1894), then in order to give each process a time slice of 1 millisecond (an eternity in computer terms), we'd need a counter that we could set to one million at the beginning each time slice, decrement by one on each pulse of the clock, and then signal when it reaches zero. This is relatively simple hardware to add to the CPU.

For each process not currently running, we'd keep its program counter and other registers in memory somewhere. Then we'd have strategy for cycling through all of the processes. If all of the processes are of the same priority, then we'd just cycle through them using a simple round-robin scheme. Each time the counter signals that it has reached 1 million, we write out to memory the contents of the registers of the currently running process, read in the most recently stored contents of the registers of the process next in line to run, reset the counter, and restart the process. This reading out and writing in of register contents is called a context switch and it's a prime example of computerese that has entered the lexicon or risen in use because of the cachet associated with appearing to be computer literate.

The only gap (well, perhaps not the only one but certainly the most blatent one) in this explanation involves this "we" that I keep talking about. The only entity capable of doing anything inside the computer is the CPU. But the CPU has its hands full executing instructions, a billion or more per second. If we're going to handle multi tasking, we'll need some additional hardware to help orchestrate this switching between processes. Conceptually the added hardware is pretty simple.

We'll need circuitry to implement the counter and a gate that signals when the counter reaches zero. We can add primitive instructions to the computer's machine language to start the timer and specify how many clock cycles it should count off. Then we'd arrange for circuitry so that whenever the timer reaches zero, it resets the program counter to the address of a special program - the program that handles switching between processes. This special program will take care of writing out the contents of the registers used by the current process, choosing what process to run next, reading in the most recently stored contents for the process chosen to run, and resetting the program counter to give the chosen process its chance to run. And that's pretty much it; that's how multi tasking is implemented on most computers.

The mechanism whereby the CPU is interrupted by the clock and made to execute a special program is actually quite common. It's called an interrupt - the general technical term for stopping the CPU and redirecting the flow of control. There are many types of interrupts and interrupt handlers (the pieces of code that get run when a a particular type of interrupt occurs). Interrupts are used to signal the CPU when some event occurs outside of the computer such as bump sensor on a robot being hit, a key being pressed on a keyboard, or a relatively slow peripheral like a disk drive depositing data in memory. Interrupts are also used to handle unexpected internal events such as when a program contains gibberish (something other than an instruction that the CPU understands) or tries to write into some part of memory that it's not supposed to (in most modern computers, memory is partitioned and protected by the operating system so that a poorly written or malicious program isn't able to overwrite those parts of the operating system required to keep things running smoothly).

I really didn't intend to take up the subject of interrupt handling today. In fact, I was thinking about taking the day off from writing in my journal. The problem is that my mind gets filled up with ideas and I have trouble letting them go, not following up. Nowadays, we're all multi tasking. We pride ourselves on our ability handle interrupts and switch contexts smoothly. We prioritize everything that we have to do and we coordinate and synchronize our activities so that we perform at peak efficiency. All of this talk, reminds me of my own struggles to keep focussed, deal with interrupts and meet my responsibilities. Unfortunately, just now the computer terms that come to mind are negative; for example, "crosstalk" when two signals interfere with one another, "thrashing" when a CPU has so many processes to run that it spends all of its time context switching (this generally happens when there is limited memory and part of context switching involves moving programs and data from disk to RAM and back again), "deadlock" when two processes find themselves stuck each wanting something that the other one has, and "segmentation fault" ("segfault") when a program crashes as a result of trying to write or read in a protected part of memory.

I remember an entry in an earlier journal in which I tried write down an account of my own mental processes. It's a little personal but I'll edit out the more embarrassing parts and include an excerpt here. The entry I'm excerpting from is dated October 5, 2001. This was a time during which I was the chair of the Computer Science Department at Brown and also serving as the Acting Vice President for Computing and Information Services (CIS) for the university. I'd drive in so I could swim with the "early birds" around 6:30am and usually stay until around 7:30pm. It was an hour drive each way to and from Little Compton so I would start at 5:30am and often didn't get home until after 8:00pm. Part of the day I'd wear my hat as VP for CIS and part of the day I'd don the hat of the department chair. I had two sets of people reporting to me and two separate constituencies that I was responsible to. Every time the phone rang or someone knocked on my office door, I first had to figure out which hat I should be wearing. I thought I was getting pretty good at handling all the stress and I surprised myself by how quickly I could switch roles and how many different tasks I could handle simultaneously. But around the time of this entry, I was feeling a little "machine like". Here is the excerpted journal entry.

This morning I thought to myself - think about this; I'm writing a note to myself and in that note I'm referring to my thoughts and reflecting on how they affected me; language and thinking becomes complicated by recursion and self reference, thinking about my thinking about my thinking - that there is a danger in my present path of losing my humanity of becoming more machine like and less sensitive, engaged and connected to people. Just now, some part of me noted the passing of the cliche "losing one's humanity" as though there was one part of me listening to another part, examining, prepared to pounce upon, a stream of words issuing from some other separate generator of thoughts; I let the cliche pass, noting once again my tendency to lapse into cliche but not feeling up to either an edit [...] or a remedial lesson. (Tense and reference are so difficult when thoughts tumble over and under other thoughts.) As I write these words now an hour after thinking the thoughts I'm reflecting on, I try to avoid being over reflective, self editing but I find it hard. My stack of ideas and threads of thought is precariously lengthening and I'm afraid I will lose what I originally thought to be the main thread of my thought: the dangers of "loss of humanity" and "turning into a machine."

I don't know how long it took to write the previous paragraph, a couple of minutes perhaps. It's 8:15AM. I'm sitting in my office and eating my breakfast, take-out scrambled eggs, wheat toast and a cappuccino from the little cafe across the street from our building - I'm still just a little guilty that I didn't sit down and eat in the cafe and leave my usual tip for Marie. Some part of me has gone on thinking about the lesson I thought could be had from reflecting on those cliched phrases; I can almost feel some order emerging or at least related thoughts being brought to the fore - I don't think the sense of emerging order is an illusion but I'll never know - as soon as I stop to scrutinize my thoughts my observations will pollute the process of reflection. But I've also awakened a score of competing threads: how do you spell cappuccino; what's the point of this exercise; why are you taking the trouble to write this down - is this a form of therapy and if so let's do it right or is this something that at some point will be part of a document that I will show to someone else and if so perhaps you should think of it in those terms; is that the indicator for an email message displayed in a corner of my screen and should I attend to it. My brain is full of thoughts and I could, I have in the past and believe that I still have the discipline, push most of them to the background and focus on one or a few. For a moment, however, I want to feel that cacophony of thoughts rustling, nagging, warning in my head. It is amazing to me the richness and multitude of these thoughts - I'm not bragging; I'd feel the same if those threads were concerning the most mundane of things. At times the chaos in my head is disturbing when I find I can't focus on things that I think I should focus on. At other times it is soothing when it rises to the level of white noise or I find myself comfortable with the familiar voices in my head.

The stack of threads in my head is not like the stack of threads used by the operating system in the computer in front of me to support multi tasking. My computer will never lose track of a thread, at least assuming the operating system doesn't crash; eventually even the lowest priority thread will rise to the top of the heap and be executed. Not so with me. I can sense threads becoming thinner more tenuous, less emphatic. I suppose there is an analog in computer systems; a piece of code can "time out" and terminate or "kill" it's respective thread of control. A quiet is descending on me and I see the stack blowing away like wisps of vapor. I'm not sure what to do next but I can see the clock display on my screen and I know that very soon the department will come to life around me and some bustling ball of energy will interrupt my reverie. Right this minute it feels good to think I have a reverie to be interrupted.

I find it strange to read this now. I imagine that immediately after writing this entry, I started reading and responding to email, called one of my direct reports in CIS to ask about the latest request for a "strategic plan", or grabbed my cell phone and ran off for a meeting over in university hall. I don't think that my brain operates anything like a modern computer, but I do think that the notions of processes and threads, multi tasking and thrashing, deadlocking and sefgaulting have some metaphorical value in analyzing my thinking and if not they still afford me some much needed distraction at times. If you're interested in models of the mind with a computational flavor, you'd probably be interested in the writings of Marvin Minsky [Minsky, 1987], Allen Newell [Newell, 1990] and Daniel Dennett [Dennett, 1998].