Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 10 Jan 2002 00:57:38 -0800
From:      Peter Wemm <peter@wemm.org>
To:        Dan Eischen <eischen@vigrid.com>
Cc:        Archie Cobbs <archie@dellroad.org>, Alfred Perlstein <bright@mu.org>, arch@FreeBSD.ORG
Subject:   Re: Request for review: getcontext, setcontext, etc 
Message-ID:  <20020110085738.AC1D538CC@overcee.netplex.com.au>
In-Reply-To: <3C390746.5FE7648C@vigrid.com> 

next in thread | previous in thread | raw e-mail | index | archive | help
Dan Eischen wrote:
> Peter Wemm wrote:
> > 
> > Archie Cobbs wrote:
> > > Alfred Perlstein writes:
> > > > > Is there a reason that getcontext and setcontext need to be
> > > > > system calls?
> > > >
> > > > Atomicity?
> > >
> > > That can't be why.. otherwise this would imply that just because
> > > something is written in assembly instead of C that it could have
> > > atomicity problems.
> > 
> > Well, consider that setjmp()/longjmp() have embedded system calls (ie:
> > sigprocmask)..  SVR4 (ie: including Solaris) use setcontext etc to return
> > from signals and it needs to restore the signal masks etc. The posted
> > patches also have sigprocmask(2) syscalls in the get/setcontext
> > implementations. Since it is going to make a syscall anyway, why not push
> > it all to a syscall?
> 
> It's not a syscall in the threads library since these functions use
> _sigprocmask (not __sys_sigprocmask), and the threads library overrides
> the weak definition of it in libc with a strong definition in libc_r.
> It has to do this because the signal mask is on a per-thread basis and
> the kernel only knows about the process signal mask.

Who said that get/set/swapcontext() had to be used with libc_r with a
userland reimplementation of sigprocmask?

> > It would also allow you to return to a VM86 context.
> > The context argument passed in to signal handlers should be able to be used
> > with setcontext() to return from the signal handler as an alternative to
> > sigreturn().  Doing it in libc wont work there because you race with
> > restoring the signal mask before you've finished setting the application
> > state.
> 
> Yes, it will.  We know when a signal occurs, and we manually restore
> the process signal mask in the signal handler.

Not when you use get/set/swapcontext() in non-libc_r apps.

> > Also, I noticed that the i386 patch doesn't save FP state (!) which is
> > one of the primary reasons for get/setcontext().  I'm not sure if this
> > can be efficiently done since this user-level function will not know if
> > the current context has touched the FPU yet..
> 
> Neither does the kernel, does it?  I thought I saw comments in the
> kernel (was it alpha?) about it being too bad that we couldn't tell
> if the FPU was used.  In libc_r, we currently only save and restore the
> FP state when the context is generated from a signal handler (or perhaps
> in the case of KSEs, when the thread was preempted).  If the context
> were from library thread switches, we assume the FP state is no longer
> needed since the application made a library call and hit a blocking or
> yielding condition.

Yes, the kernel does know.  When a process accesses the fpu (even to save
or restore its context), it traps into the kernel and the npx device
assigns the fpu to the process.

> > eg, the kernel can do this in getcontext:
> >         /* save machine state */
> >         getgregs(p, ucp->uc_mcontext.gregs);
> >         /* If we are using the floating point unit, save state */
> >         if (p->p_pcb.pcb_fpu.fpu_flags & FPU_EN)
> >                 getfpregs(p, &ucp->uc_mcontext.fpregs);
> >         else
> >                 ucp->uc_flags &= ~UC_FPU;
> > Secondly, it may be that the process has got a saved fp state, but it may
> > not be loaded into the FPU registers.. It may be stashed in pcb_fpusave
> > still and waiting for the first reference to fault into the kernel so that
> > it can load them into the fpu registers again.  If the context save was don
    e
> > in the kernel then it could copy the fpu registers from the pcb if that is
> > their current official location.
> > 
> > Solaris seems to have getsetcontext(int cmd, ucontext_t *ucp), where
> > cmd == GETCONTEXT, SETCONTEXT etc.  I think they use this as a helper for
> > the library routines.  They'd call that instead of sigprocmask() and manual
    ly
> > saving the regsters.  The libc functions would probably deal with the link
> > stuff.
> > 
> > BTW2; the i386 implementation doesn't have the full FPU state.. ie: no
> > SSE or SSE2 context.  It should be using fxsave/fxrstor if present, which
> > is an additional reason to do this in the kernel.
> 
> I don't think that what's currently implemented for i386 is any
> different than setjmp/longjmp, and libc_r has been using those since
> the beginning without any problems.  It does save the FP state when it
> gets a signal and restores it when resuming a thread interrupted by a
> signal (like I mentioned above).

setjmp/longjmp work standalone without depending on userland libc_r
wrappers. Your implementation of get/set/swapcontext() cannot if there is a
pending signal involved.

> > BTW3; the ia64 has got some "interesting" handling required here.  Having
> > libc_r use these new functions means that libc_r will be a step closer
> > to working on ia64.  I suspect that fpu state handling on the ia64 will
> > require a syscall to do it efficiently.
> 
> I'd like to avoid the overhead of a syscall to switch threads if
> at all possible.

You may have no choice.  The jury is out there for the moment though.

Cheers,
-Peter
--
Peter Wemm - peter@FreeBSD.org; peter@yahoo-inc.com; peter@netplex.com.au
"All of this is for nothing if we don't go to the stars" - JMS/B5


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?20020110085738.AC1D538CC>