Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 31 Aug 2002 15:59:44 -0700
From:      Jonathan Mini <mini@FreeBSD.org>
To:        Julian Elischer <julian@elischer.org>
Cc:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   Re: PERFORCE change 16871 for review
Message-ID:  <20020831225944.GR3751@elvis.mu.org>
In-Reply-To: <Pine.BSF.4.21.0208311500150.5605-100000@InterJet.elischer.org>
References:  <200208312153.g7VLrYd9023540@freefall.freebsd.org> <Pine.BSF.4.21.0208311500150.5605-100000@InterJet.elischer.org>

next in thread | previous in thread | raw e-mail | index | archive | help
Julian Elischer [julian@elischer.org] wrote :

> sounds good, but I'd apreciate a 3 or 4 paragraph description of what you
> are doing as it varies a little from what we discussed..
> 
> pitty you aren't in the bay area any more..
> A whiteboard would be good... 

Yeah. Whiteboards are nice.

Again, from the top:

The kse_mailbox and thread_mailboxe maintain a ucontext_t. This ucontext_t
has a bit of optional behaviour, which does this:
	- SKIPSIGMASK skips the signal mask get/sets, so that we can
	  swapcontext() w/o making any syscalls. Also, caught signals
	  will be handled via an upcall to the UTS later.
	- OBEYBUSY which makes setcontext() fail if uc_busy is set.
	  By now, I'm thinking we might not need this.
	- CLEARSTATE, which requests that setcontext() clear any state
	  flags.
The state flags are:
	- CRITICAL: in a critical section. This causes
	  thread_userret() to return to the thread instead of doing an
	  upcall, basically enforsing synchronous syscalls for that
	  thread for that time period. CRITICAL on the UTS's context
	  isn't honored. It's assumed that a uc_busy uts context is also
	  CRITICAL.
	- SWAPPED: used by swapcontext() isntead of the int swapped on the
	  stack. I think this is kind of broken at the moment. The reason
	  for this is related to objections by jake (among others) about
	  using the stack during swapcontext().
uc_busy is a seperate int because it needs to be set/checked atmoically.

These are optional so that default *context functions work just
like they do on solaris or wherever.

So, the way a thread is scheduled is like this:

1) An upcall is made, doing a thread_setcontext() on the ucontext_t
   in the kse_maibox in userland.
2) The UTS comes out of the state in the ucontext_t, either from the inital
   state set by makecontext() or the state saved the last time it
   swapcontext()'d out.
3) The UTS checks for any threads in the completed list, and adds them to
   the run queue.
4) The UTS grabs a thread from the run queue.
5) We know the thread wasn't in a CRITICAL state already, or it wouldn't
   have been passed in via the upcall, so we don't have to worry about
   stomping on the changes to CRITICAL made by the thread itself.
   We set CRITICAL and CLEARSTATE on it.
6) We set kse_mailbox.km_curthread to the thread_mailbox we selected.
7) We swapcontext() into the thread's ucontext_t:
	a) we getcontext() for the UTS context.
	b) then, we mark uc_busy 0, freeing the UTS for further calls.
	   However, at this point, we are seen by the kernel as in a
	   critical section for the thread we're about to switch to,
	   so any traps in the kernel (such as syscalls) will return to
	   us instead of doing another upcall.
	c) we setcontext() to the thread's ucontext_t, which restores machine
	   state, and clears the CRITICAL flag because it sees CLEARSTATE
	   set.
8) execution continues as the scheduled thread.

Upon reviewing this, I see that CLEARSTATE needs to be a flag,
not an option, so that it is also cleared when setcontext clears
the CRITICAL flag.

So, I guess the right terminoligy would be persistent/temporary, and not
option/flag.

My current plan is that signals will work like this:
1) The process will request signal delivery via the uts.
2) A catchable signal is delivered to the process and added to a sigset
   kept in the kse_mailbox.
1) An upcall is made to notify the UTS of the signal.
2) The uts sees the signals caught thus far, and selects a thread to
   receive the signal.
3) It adds a signal frame to the context of the thread by calling
   signalcontext(), which will do the same thing the kernel does to a
   ucontext_t when delivering a signal to a process on that arch.
4) It adds the signal to the runqueue, and it gets scheduled normally.

Signals are a bit more complex than that, because of sigaltstack, and a few
other complications, but you get the basic idea.

I hope all of that is clear.

-- 
Jonathan Mini <mini@freebsd.org>
http://www.freebsd.org/

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




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