This is to explain why we're doing all the single-stepping in another thread and how this
whole stuff works.

First, let's have a look at the core part of the sse - it's the part which actually does
the single-stepping - this part is basically the `protected bool Step (StepFrame frame)'
if you look at the source code.

It gets a so-called step frame from its caller and single-steps until leaving that step
frame.  Normally, this is a range of memory and we step until we stop somewhere outside of
that range.  It's actually a bit more complicated than this since we need to deal with
method calls, JIT trampolines and all this stuff, but this shouldn't matter here.

When the user issues a "step until next source line" command in the GUI, the sse normally
needs to do several step operations until reaching the next source line.  A good average
is probably about 5-20 machine instructions per source line - but of course, this depends
a lot on the code you're currently debugging.  There's also no upper limit on that number -
it may well go over one million if you're out of hardware watchpoints and using Finish()
in a method containing a loop.

However, you can assume that normally the sse needs to process five or more step
operations each time the user issues a single command.

Internally, the sse steps one single machine instruction each time, waits until the target
stopped again and then checks whether it's done with the stepping.  For obvious performance
reasons, this whole stuff needs to be very fast - so we aren't doing any symbol lookups
unless really necessary.

Under Linux, you have two ways of waiting for the child which you're currently debugging -
you can either use waitpid() or wait until you get a SIGCHLD (you get a SIGCHLD each time
the child stops).

In the old single-thread situation, I did a non-blocking waitpid() to check whether the
child already stopped and then a single, but blocking iteration of the glib main loop.
The glib main loop is using poll() and not sigsuspend(), so there was the race condition
of getting the SIGCHILD after the waitpid() but before the poll().  This worked because
the glib main loop uses timeout of a few hundred milliseconds for the poll() - so this
race condition wasn't causing a deadlock, but just a delay of a hundred milliseconds.

However, it turned out that the negative side-effects of this were huge - if you need to
do five or more step operations per user command, you cannot afford getting a hundred
millisecond delay, not even if you're just getting it sometimes but not always.

The other big problem was that we were doing an iteration of the glib main loop each time
and this is an expensive operation.

The new sse is now doing all the single-stepping in a separate thread - and I'm using a
reliable sigsuspend() to wait for the SIGCHLD (the advantage of using sigsuspend() is that
you could theoretically send the background thread a SIGCHLD to wake it up, but we're not
using this "feature" at the moment).

Unfortunately, there is a problem with the way how Linux handles threads:

For the Linux kernel, a thread is just a kernel process - and a process may only be traced
by one process at a time.

There are two ways to start tracing another process:

* When we start debugging an application, we fork() a child - and before calling execl(),
  the child process calls ptrace (PTRACE_TRACEME) - after doing the execl(), the parent is
  sent a SIGCHLD and it can ptrace() the child.

  However, only the thread which initially forked() the child has the right to trace it -
  and this right is *NOT* inherited if the parent creates a new thread after doing the
  fork().

* Each time the target created a new thread, we use ptrace (PTRACE_ATTACH) to attach to
  this thread - which gives the thread which did the PTRACE_ATTACH the right to debug this
  new thread.

So, to summarize, a single thread in the debugger may attach to as many child processes as
it likes - but the right to trace a child process is always given to exactly one thread in
the debugger - and it cannot be inherited or transfered to any other thread.

Only the debugger thread which has these tracing rights may use ptrace() on that child and
unfortunately this also applies to /proc/<pid>/mem.

It is obvious that only the sse's background thread may ever want and need to use ptrace()'s
stepping commands or waitpid() to wait for it - but of course the GUI and a lot of user-level
functions need to read the target's memory.

However, this is not such a big problem - we just need to make sure that we only access
that target's memory from the sse's background thread.

There are two ways to do this:

* The sse is now sending the FrameChangedEvent and the MethodChangedEvent from the
  background thread - so if you install a handler for these events, it can read the
  target's memory directly.

* If you need to read the target's memory from any arbitrary thread, the sse can also send
  a command to its background thread to do this.  This is also how backtraces work - the
  command which is sent to the background thread can be arbitrarily complex (we're just
  using a delegate which is executed by the background thread), so the overhead of the
  thread switch and the synchronization is minimal.

Basically, my idea is the following:

* If the debugger is displaying a varible in GUI and it needs to be updated each time the
  target stops, attach to the FrameChangedEvent, read all the necessary data in that handler
  and then send a notification to the gtk# thread.

  To make this more easy, frontends/gui/DebuggerWidget.cs has some thread synchronization
  stuff which is pretty useful.

  If gtk# ever becomes thread-safe, we can also do the GUI stuff directly in the
  FrameChangedEvent handler.

* If you just need one single variable, for instance because the user issued a `print'
  command, we can afford the thread switch and just use the sse as an ITargetMemoryAccess.

For managed applications, I'm using some "hack" to read the dynamic symbol tables from the
JIT - the information from these symbol tables is needed very often, so the thread
synchronization would be too expensive.  The information from these symbol tables applies
to all threads, so all the code which deals with it must be thread-safe.

So this is how it works:

When the JIT is run under the mono debugger, it creates a special thread which is just
used by the debugger.  This thread is either stopped on a breakpoint or blocking on a
pthread_cond_t.  While it is stopped at that breakpoint, it owns a special mutex which is
used to protect all the symbol tables.  The condition is signalled each time the symbol
tables are modified.

To make things even more easy for the debugger, the dynamic symbol tables are stored in
continuous memory chunks, so the debugger just needs to read a few big blobs.

In the debugger, all the symbol table handling is done in its own thread - and this thread
attaches to this special JIT thread.  The clue is that we only need to read anything from
the JIT while this JIT thread is stopped at this breakpoint - and then that thread is
stopped and since we're tracing it, we can access its memory.

For performance and memory usage reasons, we just copy all the data from the JIT as blobs
and store them - they're parsed when they're actually used - and this can be done from any
thread.




