Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 06 Jan 2002 21:26:14 -0500
From:      Dan Eischen <eischen@vigrid.com>
To:        Peter Wemm <peter@wemm.org>
Cc:        Archie Cobbs <archie@dellroad.org>, Alfred Perlstein <bright@mu.org>, arch@FreeBSD.ORG
Subject:   Re: Request for review: getcontext, setcontext, etc
Message-ID:  <3C390746.5FE7648C@vigrid.com>
References:  <20020106232937.9F87D38CC@overcee.netplex.com.au>

next in thread | previous in thread | raw e-mail | index | archive | help
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.

> 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.  The threads library
installs signal handlers so that all signals are blocked during a
handler.  Once the threads library has determined which thread is
suppose to get the signal and has set it up for handling the signal,
the process signal mask is restored.  Other signals may now occur,
but it is safe.

> 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.

> 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 done
> 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 manually
> 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).

> 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.

-- 
Dan Eischen

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?3C390746.5FE7648C>