Processes, Threads, Functions

CS 321 2007 Lecture, Dr. Lawlor

Kinds of Program Control Flows

There are quite a few different levels of saving and restoring that you can design.  Existing levels are nesting, and from least-to-most context include:
  1. Functions, where things execute one at a time.  Hopefully you're familiar with normal functions.
  2. User-level threads, where you save and restore processor registers yourself, usually via an explicit "swap" subroutine call.  Also called "coroutines" or "user/userspace threads", or (by Sun Java folks) "green threads".  Check out my little "minithread" example code for an example (Directory, Zip, Tar-gzip).   The key routine is just the "mth_swap" subroutine, which saves an old set of registers and loads up a new one, and the core of this is just:
        mov [eax],esp  ; Save the old stack pointer
        mov esp, [ecx] ; Load up the new stack pointer
      Typical examples include Netscape Threads, or any of a thousand tiny projects mostly relying on setjmp/longjmp or "makecontext/swapcontext".  Each thread has its own stack, usually just allocated with "malloc", but shares the rest of memory with other user-level threads.
  3. Kernel-level threads, or just "threads", are where the OS saves and restores processor registers to switch threads at interrupt time.  Also called "native threads". The most common example is pthreads.  There's actually a hybrid of kernel and user-level threads where you save and restore processor registers yourself (not in the OS), but you do it inside a signal handler during an interrupt.
  4. Processes, where the OS swaps out all of memory and all I/O connections in addition to the registers.  This is what you usually think of as a "program"--we covered it last class.
  5. Virtual Machines, where the OS itself and everything in it is swapped out. QEMU is a pretty typical example.  A virtual machine is usually treated as an ordinary process inside the outer ("host") OS.
All these levels actually nest.  So a virtual machine might contain several processes, with the emulated OS switching between them.  Each process might contain several kernel threads, with the OS again switching between them.  Each kernel thread might contain several user-level threads, which user code explicitly switches between.  Each user-level thread contains several functions, which call one another.

Creating Different Program Control Flows

UNIX: Linux, Mac OS X
User-Level Threads
fibers & others makecontext/swapcontext (example) & others
Kernel Threads
CreateThread (example)
pthread_create (example)
CreateProcess (example)
fork (example)
Virtual Machines
varies (QEMU, VMWare, etc.)

See all the example code as a (Directory, Zip, Tar-gzip).

You should become familiar with both Windows and UNIX flavors of thread and process creation.