CS 3330: Lecture 24: Exceptional Control Flow

This page does not represent the most current semester of this course; it is present merely as an archive.

Non-local jumps (8.6)

We can graph the flow of a program through different methods over time like so:

 main()
-------->+
         |
         |
         | calls foo()
         +------------>+
                       |
           returns 11  |
         +<------------+
         |
         |
         V

Sometimes it is helpful to be able to break this push/pop flow with what are called non-local jumps:

 main()
-------->+
         |
         | setjmp(j)
         +---------->+
                     |
      3        0     |
   ----->+<----------+
  /      |
 |       | foo()
 |       +------>+
 |               | baz()
 |               +------>+
 |                       | longjmp(j,3)
 |                       +------------>+
 |                                     |
  \                                   /
   ----------------------------------- 

Thought Question: what would setjmp need to put into j for this to be possible?

Switch/Case (background)

What is a switch statement? We think of it like a bunch of if statements, but it is faster than that. The code

switch(x) {
    case 0: foo();
    case 1: baz(); 
            break;
    case 2: xyxxy();
}

will turn into the following pseudo-assembly code:

    addresses = [L0, L1, L2] // obviously not assembly...
    jmp addresses[x]         // also missing <0 and >2 cases

L0: call foo
L1: call baz
    jmp Lend
L2: call xyxxy
Lend:

The switch statement is created by using the value as an index into a list of code addresses. That list-of-addresses is called a jump table.

Interrupts and Exceptions (8.1.2_

Interrupts

Suppose the disk wants to tell the CPU that data is available.

  1. The disk lets the I/O Bridge know it wants to interrupt the CPU.

  2. The I/O Bridge then

    1. puts a number on the System Bus that means "data from disk available".
    2. puts voltage on a special pin on the CPU which means "interrupt what you are doing".
  3. The CPU

    1. Finishes its current operation.
    2. Effectively "setjmp"s: stores the current processor state in the kernel stack.
    3. Reads the number off of the System Bus (call it x).
    4. switch(x) into a special set of kernel-defined methods called the exception table. For a disk data availability interrupt that interrupt handler is probably going to do something like add page-table entries for the read data so the user code can access it.
    5. Once the handler is done, it effectively "longjmp"s back to the code that had been interrupted.

Traps, Faults, and Aborts

A Trap is an instruction that acts like an interrupt. It is used to let user code talk to the kernel (because the kernel is the one running the exception handler)

An abort is an interrupt, trap, or fault that never jumps back to the interrupted code, instead terminating the program. The C library function exit contains an abort.

A Fault is an instruction that acts like an interrupt because it failed to behave normally. If the handler can fix the problem, the fault will re-execute the instruction that faulted. If the handler cannot fix the problem, the fault will act like an abort instead.

Terminology

Traps, Faults, and Aborts are collectively called Exceptions. They differ from Interrupts in that they are generated because of running code, not because of external activity.

There is no agreed-upon term for Interrupts + Exceptions. The textbook uses "exception" for the combined set when it can, as noted in page 711.

Linux System Calls (8.1.3)

x86 interrupts and exceptions are generated by

All of these are handled by the hardware, so the hardware puts constraints on them. In particular, there may only be a 1-byte index into the exception table, which means there can be at most 256 exception types.

Linux gets around this limitation by having one particular trap (number 128 = 0x80) which means "use the values of the registers to pick what to do next". %eax% is used to store which system call is wanted, and the other registers (except %esp) are parameters into that call. For example,

movl $1, %eax
movl $3330, %ebx
int $0x80

means "OS, run system call" (trap number 0x80) "number 1" (which is exit, closing a process) "with parameter 3330" (which is what exit(3330) would do).

If you are interested, you can browse a list of system calls at http://syscalls.kernelgrok.com/.

Copyright © 2015 by Luther Tychonievich. All rights reserved.
Last updated 2014-11-25 17:21 -0500