Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 11 Jan 2002 13:41:07 -0800
From:      Bakul Shah <bakul@bitblocks.com>
To:        Dan Eischen <eischen@vigrid.com>
Cc:        arch@freebsd.org
Subject:   Re: Request for review: getcontext, setcontext, etc 
Message-ID:  <200201112141.QAA25529@devonshire.cnchost.com>
In-Reply-To: Your message of "Sun, 06 Jan 2002 00:49:13 EST." <3C37E559.B011DF29@vigrid.com> 

next in thread | previous in thread | raw e-mail | index | archive | help
I quick-scanned this discussion thread and got a bit
confused, so please allow me to approach it in my own way:-)

I have a simulation thread library which allows a thread
context switch with 12 or so instructions on a x86.  Actual
switching is done in a function with inline assembly code.
During this switch if a signal is received a signal handler
will get control.  The kernel must (and does) save & restore
the necessary state to continue the interrupted simulation
thread context switch upon return from the signal handler.

This is but one example to point out the obvious: if you make
a context switch from a signal handler to another regular
thread with setcontext(), the ultimate return to the original
thread (the one interrupted by a signal) must be done
properly _even_ if it is in the middle of munging any user
modifiable register or stack.

In other words, a signal handler *must* not make _any_
assumptions about the state of a regular thread.  With
setcontext() and getcontext() things get worse because now a
thread interrupted by a signal may be restored from any other
thread.

To deal with this, you can either take a pessimistic approach
and save/restore everything on get/setcontext() or allow for
a varying amount of context and a way to decipher them.  As
an example, a getcontext() done from regular C code can be
"lean" and only save a few registers. A getcontext()
equivalent done as part of a signal delivery can be "fat" and
save more things.  If the signal arrives in the middle of a
user mode getcontext(), you throw away what getcontext() did
and save a fat context.  But to do that, you need a way to
signal you are in the middle of getcontext().  If a signal is
delivered in the middle of a setcontext(), it is not even
clear *which* thread should be receiving the signal --
perhaps it should be the one doing the setcontext().  The
kernel must *backout* a partial setcontext before delivering
the signal.  So again you need to indicate you are in middle
of setcontext() or do it atomically.

I am not prepared to speculate on the use of FP & SSE
registers at this point except for one thing: an FP exception
*must* be delivered to whichever thread caused it.  Any bugs
in SIGFPE delivery is a separate discussion!

Note: I used the term "regular thread" to distinguish them
from my "simulation threads". A regular thread is the one on
which you can do {get,set}context().

BTW, it is perfectly legitimate and actually very useful to
implement simulation threads within a regular thread.  To
give you an idea, on an Athlon XP 1700+ I get a simulation
thread context switch time of about 17ns best case (both
contexts in primary cache) to 480ns worst case (both contexts
in memory + other effects when you have over a million
threads).  I can never get this sort of speed with a generic
regular thread system and this speed is what make it
practical to simulate an ASIC at a register transfer level or
even a whole system in C/C++.  On the other hand, simulation
threads live in simulation time and interfacting them to the
real world is painful.

-- bakul

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200201112141.QAA25529>