The first kse_create call

Daniel Eischen eischen at vigrid.com
Wed Jun 18 09:34:34 PDT 2003


On Wed, 18 Jun 2003, Sergey Kosyakov wrote:
> --- Daniel Eischen <eischen at vigrid.com> wrote:
> > 
> > You have to have both a thread mailbox pointer set in the
> > KSE mailbox and you have to expire the quantum.  The quantum
> > is system plus user time.  It is not real time (e.g., a nanosleep()
> > does not expire quantum while it sleeps).
> 
> I'm trying to do this:
> 
>   mbx.km_version=KSE_VER_0;
>   mbx.km_func=uc_1;
>   mbx.km_stack.ss_sp=stack_1;
>   mbx.km_stack.ss_size=SIGSTKSZ;
>   mbx.km_stack.ss_flags=SS_ONSTACK;
> 
>   ret=getcontext(&(thr_mbx.tm_context));
>   printf("getcontext %d\n",ret);

If thr_mbx is the initial thread mailbox, you don't need
to get a context for it.  The kernel will give you back
its context on an upcall when the thread resumes after
being blocked or after quantum expires; the thread mailbox
will be in the KSE mailbox completed list.

>   thr_mbx.tm_context.uc_link=NULL;
>   thr_mbx.tm_context.uc_stack.ss_sp=thr_stack_1;
>   thr_mbx.tm_context.uc_stack.ss_size=SIGSTKSZ;
>   thr_mbx.tm_context.uc_stack.ss_flags=SS_ONSTACK;
>   makecontext(&(thr_mbx.tm_context),func,0);

Again, you only need to do the above for new threads so that
you can start them when you get an upcall and the current
thread is either not runnable or you choose to swap it out
for another thread.

>   thr_mbx.tm_uticks=10;
>   thr_mbx.tm_sticks=0;  

You (application) don't set tm_uticks or tm_sticks.  The kernel
does that to let you know how much time the thread has consumed.

>   mbx.km_curthread=&thr_mbx;
>   ret=kse_create(&mbx,0);
>   do
>    {
>     ++i;
>    }while(1);
> 
> And never got upcall. (But if I put printf in the loop I got the
> upcall).

You're not setting km_quantum.  It has to be done before the
kse_create() and cannot be changed afterwards (kernel only reads
it once I believe).  You also have to make sure km_flags is 0.

You get the upcall with a printf() because the thread eventually
blocks in the kernel.  The above spin loop makes no system calls
and won't block.

Using KSEs on your own is tricky.  There is a lot to keep
track of.  You've got to handle signals on upcalls, keep
track of whether the current thread has blocked or not,
and atomically set the thread mbx pointer in the KSE when
you switch to another thread (If you set the mbx pointer
before you switch to the new thread, then if you get
an upcall before switching, the kernel may overwrite the
thread context before you've finished with it.  And it
might contain partial context of the KSE context).
See src/lib/libpthread/i386/i386/thr_switch.S.

It is much easier to just use libpthread^Wlibkse :-)

-- 
Dan Eischen



More information about the freebsd-threads mailing list