PS_BLOCKED

Daniel Eischen eischen at pcnet1.pcnet.com
Mon Apr 7 04:53:33 PDT 2003


On Sun, 6 Apr 2003, Julian Elischer wrote:
> 
> On Sun, 6 Apr 2003, Daniel Eischen wrote:
> 
> > On Sun, 6 Apr 2003, Julian Elischer wrote:
> > > 
> > > If you have this behaviour, please make it an option. Possibly
> > > One way to do this would be to call kse_create, with the
> > > 'new-ksegrp' flag set but the mailbox pointer set to NULL.
> > > 
> > > However why do you want to use kse_release for this.
> > > If you have only one thread in the KSEGRP then I'd call this
> > > "usleep()".
> > 
> > It's so that the common code (called by both scope system
> > threads and scope process threads) can be the same.  I don't
> > want to have to add checks all over the place to see if the
> > KSE is bound to a thread or not.  Also, nanosleep doesn't
> > work well because you can't wake it up with a KSE mailbox
> > (kse_wakeup), plus there's a race condition if you try and
> > wake it up before it actually gets to the kernel to sleep.
> > The kse_wakeup() call is latched, so if it gets to the kernel
> > first, the next kse_release() will notice it.
> 
> you cannot wake up a thread with no upcall mailbox using kse_wakeup
> because there is no thread mailbox address to match.

There is a kse mailbox, but no thread mailbox.  I'm trying to
wakeup a KSE.  What I do for multiple threaded KSEs is:

  upcall_start(struct kse_mailbox *kse_mbox)
  {
    struct kse *curkse = (struct kse *)kse_mbx->km_udata;

    check_completed(kse);
    check_waitq(kse);
    ...

    while ((td_run = runq_first(kse->k_kseg) == NULL) {
      get_smallest_thread_wakeup_time(kse, &time_to_sleep);
      kse->k_waiting = 1;
      kse_release(&time_to_sleep)
    }
    /* switch to thread td_run */
  }

Although, for multiple threaded KSEs, the "while" loop
only executes once because kse_release just causes another
upcall.  If another KSE makes a thread runnable in the
first KSEs KSEG's runq, then it wakes up that KSE:

  _thr_setrunnable(struct kse *curkse, struct pthread *thread)
  {
    SCHED_LOCK(curkse);
    runq_insert(thread->kseg, thread);
    SCHED_UNLOCK(curkse);
    if ((thread->kse->k_kseg != curkse->k_kseg) &&
        (thread->kse->k_waiting != 0)) {
      thread->kse->k_waiting = 0;
      kse_wakeup(&thread->kse->k_mbox);
    }
  }

or something like that.

For a single threaded KSE/KSEG, I don't want the upcall but I
still want to use kse_release().  I need to be able to wakeup
that KSE so that it may continue it's thread (it could be the
thread was in pthread_cond_wait() and it was signalled by
a thread in another KSE).  And I don't want upcalls on this
KSE because there is only one thread; I don't want the overhead
of the upcall and its stack.  And in order to prevent upcalls,
I have to make sure the kse mailbox has NULL in km_curthread.

That's the solution I'm looking for.  I think kse_wakeup()
should be tweakable so that I don't get an upcall.

-- 
Dan Eischen



More information about the freebsd-threads mailing list