Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 10 Jan 2002 01:10:18 -0800
From:      Peter Wemm <peter@wemm.org>
To:        nate@yogotech.com (Nate Williams)
Cc:        Daniel Eischen <eischen@pcnet1.pcnet.com>, Dan Eischen <eischen@vigrid.com>, Archie Cobbs <archie@dellroad.org>, Alfred Perlstein <bright@mu.org>, arch@FreeBSD.ORG
Subject:   Re: Request for review: getcontext, setcontext, etc 
Message-ID:  <20020110091018.0788A38CC@overcee.netplex.com.au>
In-Reply-To: <15418.518.723982.571226@caddis.yogotech.com> 

next in thread | previous in thread | raw e-mail | index | archive | help
Nate Williams wrote:
> > > > > Nope, but you need to be able to get the FPU context saved in setcont
    ext.
> > > > 
> > > > Well, that's what I mean.  If somewhere else in the application
> > > > there was a setcontext that returned to the getcontext above...
> > > 
> > > I think I understand what you are asking.  Are you asking if there is
> > > application specific context that needs to be saved, such as GC state or
> > > somesuch?  Or, am I truly confused?
> > > 
> > > > What I'm asking is, is there any FP state (other than the FP
> > > > control word which does get saved/restored), from before the
> > > > getcontext call that needs to be reloaded after the call, or
> > > > does the compiler assume that state may have been changed
> > > > by the call itself?
> > 
> >   Thread 1:
> >   ---------
> >   /* munch some FP stuff */
> >   pthread_yield();  /* allow thread 2 to run */
> >   /* munch some more FP stuff */
> > 
> > Assume that pthread_yield only saves the FP control word (which
> > is what it does currently in libc_r).
> > 
> >   Thread 2:
> >   ---------
> >   /* FP munchy munchy */
> >   pthread_yield();   /* allow thread 1 to run */
> >   /* FP munchy munch munch */
> > 
> > 
> > What FP state exists in registers across the call to
> > pthread_yield().
> 
> *NOW* I understand.  Thanks for being patient with me.
> 
> Here is some code snippets on that note.  (It's been a *LONG* time since
> I looked at this, so be nice to me. :)
> 
> Basically, we do a 'fsave' on an 108 byte array (which is the amount of
> space required to save a complete processor state of the FPU unit on a
> 387), and then later restore the same state.

FWIW, this is no longer the case.  On all current CPUs, there are a whole
stack more registers.  The context save buffer is 512 bytes long. It isn't
all used yet, but will be at some point in the future as long as you use
the defined fxsave/fxrstor instructions.

struct  envxmm {
        u_int16_t       en_cw;          /* control word (16bits) */
        u_int16_t       en_sw;          /* status word (16bits) */
        u_int16_t       en_tw;          /* tag word (16bits) */
        u_int16_t       en_opcode;      /* opcode last executed (11 bits ) */
        u_int32_t       en_fip;         /* floating point instruction pointer */
        u_int16_t       en_fcs;         /* floating code segment selector */
        u_int16_t       en_pad0;        /* padding */
        u_int32_t       en_foo;         /* floating operand offset */
        u_int16_t       en_fos;         /* floating operand segment selector */
        u_int16_t       en_pad1;        /* padding */
        u_int32_t       en_mxcsr;       /* SSE sontorol/status register */
        u_int32_t       en_pad2;        /* padding */
};
struct fpacc87 {
        u_char  fp_bytes[10];
};
struct  xmmacc {
        u_char  xmm_bytes[16];
};
struct  savexmm {
        struct  envxmm  sv_env;
        struct {
                struct fpacc87  fp_acc;
                u_char          fp_pad[6];      /* padding */
        } sv_fp[8];
        struct xmmacc   sv_xmm[8];
        u_long sv_ex_sw;        /* status word for last exception */
        u_char sv_pad[220];
} __attribute__((aligned(16)));

There are eight 10-byte registers, and eight 16-byte registers.

union   savefpu {
        struct  save87  sv_87;
        struct  savexmm sv_xmm;
};

/* and this is what we save for userland state */
struct pcb {
...
        union   savefpu pcb_save;
};

When a userland application does a getcontext(), the kernel looks at
fpcurthread to see if the calling process/thread/whatever has got its
context stored in the pcb or in the live registers.  There is no need to
copy state to the FPU solely in order for the userland to save a copy.

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?20020110091018.0788A38CC>