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>
