From: swart@src.dec.com (Garret Swart)
Newsgroups: comp.os.research
Subject: Re: Plan 9 process/thread comment?
Date: 10 Apr 92 21:44:58 GMT
Organization: DEC Systems Research Center
Originator: osr@ftp


Why are threads and processes different?  Here are some reasons,
both subjective and objective.

- By their definition, threads do not have to be visible outside of
  a process.  This allows (but does not require) thread creation
  and scheduling to be largely performed at user level.  Some
  advantages of this are:

    + Fewer kernel context swaps in most cases.  250 instructions for
      a null system call can swamp the cost of a fast context switch.
      Though a user level scheduler has to call the kernel sometimes,
      experience has shown this to be much less frequent.
      
    + Less checking of arguments.  The kernel should not let a buggy
      or malicious client mess up its invariants but it is the norm
      for a buggy client to have the ability to screw up its own
      libraries.  Note that though it is the norm it can cause problems
      and that is one reason why some of us are pushing for safe
      languages, where the features of the language that can screw up
      other facilities are isolated (e.g. mfree, pointer arithmetic,
      unchecked array dereferencing, passing addresses of objects
      outside the scope where the object is known to exist).  This has
      been done with Modula-3 and we are working on doing this with
      C++.

    + Fewer data structures shared between all processors.  Since each
      process has its own ready queue the global ready queue is not
      accessed so much.  (This advantage is not inherent but it is
      typical.)

    + Allows for scheduling policy to more easily be adjusted on a per
      process basis as much of the policy lives in a library.

  The old disadvantages of user level schedulers have been addressed
  a number of times, most completely by Anderson et al. in their work
  on scheduler activations.  I think this was reported at the latest
  SOSP.  The problems they address include:

    + Page faults blocking the kernel thread being used by the user
      level scheduler
      
    + Priorities not working between threads in different processes

  They have also designed an RPC system that for many workloads
  works entirely at user level.

- [Subjective] Threads are a programming mechanism, like for loops
  or procedures.  They make it easier to write programs that have
  certain attributes.

  Processes are containers that are used to run a program on
  many OSs, in particular Unix.  The user of a program should not have to 
  care what particular implementation  techniques were used in 
  the implementation of the program.  Processes act as
  firewalls between programs, allowing separate processes to
  fail independently from each other.

  The Plan 9 model solves the same problem that threads address with
  coroutines plus processes forked with the option to share nearly
  everything.  Though the Plan 9 process model (aka Variable Weight
  Processes) allows for a myriad of different types of processes sharing
  who knows what with who knows whom, the actual patterns of sharing
  are usually either of the thread variety (nearly everything) or of
  the normal process variety (nearly nothing), anything else is
  too confusing.

  With a good implementation threads can have the power
  of a process (independent blocking, ability to exploit
  multiprocessors) and, in general, the weight of a coroutine.

- If process = program then handling errors and debugging is much easier
  as the system knows the boundary of what should be grouped together
  and

    + Killed when the program faults with a bad pointer reference
      or whatever

    + Written into the same core file

    + Manipulated with the debugger

    + Manipulated by a user with "ps" and "kill".

  Threads inside processes allow this equation to hold much more uniformly.  
  RPC and nonshared memory (traditional) process groups can sometimes cause
  this equation to break down, but with much less frequency than it
  would in the Plan 9 model.

- [Subjective] At SRC we use threads extensively in our systems, primarily
  for ease of programming.  We have implemented threads both completely at
  user level, almost completely in the kernel (microkernel of course!) and
  systems using a mixed approach have been built and tested (cf. Anderson 
  et al.).  We have implemented threads for multiprocessors and 
  single processors.  All of these implementations implement the same 
  interface and  our programs run unchanged on top of each.

  Threads allow interfaces to be made simpler as each operation can be
  made synchronous.  It is threads that allow RPC to be reasonable.  With a
  single threaded program, synchronous communication can be very
  inefficient but with a  multithreaded program synchronous communication 
  factors the problems of synchronization and communication quite nicely.

Garret Swart