Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 24 Nov 1999 09:03:29 -0500
From:      "Daniel M. Eischen" <eischen@vigrid.com>
To:        Julian Elischer <julian@whistle.com>
Cc:        freebsd-arch@freebsd.org
Subject:   Re: Threads
Message-ID:  <383BF031.B52BC41F@vigrid.com>
References:  <Pine.BSF.4.10.9911232348550.11412-100000@current1.whistle.com>

next in thread | previous in thread | raw e-mail | index | archive | help
Julian Elischer wrote:
> 
> I think that the easiest context to create is one that you create by just
> being there. It's self correcting in the face of compiler changes etc.

Well, that's how getcontext and makecontext work also, except the application
supplies the stack to use, as opposed to using the current stack.  I don't
see there being much difference between our ideas.

> > > I'm not that fussed about it but it just seems to me that the information
> > > being passed back and forth is DIFFERENT than that being passed back and
> > > forth in the non-threaded world.
> >
> > True, but it is passed back and forth in NEW ways.  It doesn't affect
> > non-MT system calls.
> 
> That's where I disagree.
> I think nearly all syscalls can block given page faults etc. and having all
> syscalls potentially return via the UTS is going to mean some change
> in the kernel/process protocol.

I guess we just disagree on how the kernel is entered.  I just don't see
why we need to change the method of entering the kernel.  We just want
to switch to a new context (UTS) when a KSE blocks, and that can be done
from within the kernel without changing the method entering the kernel.

> If a blocked syscall returns, then when it returns the UTS needs to
> be able to decide whether it is the most important thread to continue or not.
> So it can't just 'return', but has to come back via the UTS. This requires
> that things be considerably different. At least this is how I see it.

Right.  And just because it woke up from a tsleep doesn't mean that it
will eventually be able to finish and return to userland.  It may
encounter more tsleeps before leaving the kernel.  The UTS needs
to enter the kernel in order to resume the thread.  And it needs a
way of telling the kernel which blocked KSE to resume.

The UTS is notified that a KSE has unblocked, but it doesn't have to
immediately resume it - other threads may have higher priority.  I think
we are in agreement here.  I'm just advocating using the stack of the
UTS event handler context (in the form of parameters to the event handlers)
to tell the UTS that threads have blocked/unblocked in the kernel.  There
doesn't have to be any magic/wizardry in the system calling convention
to do this.  The kernel can return directly to the predefined UTS event
handlers (also on a predefined stack) and totally bypass the original system
call in which it entered the kernel.  At some point later, the UTS resumes
the (now unblocked) KSE and returns the same way it entered.

You also want the ability to inform the UTS of _more_ than just one
event at a time.  Several KSEs may unblock before a subprocess is run.
You should be able to notify the UTS of them all at once.  How does
that work in your method?

> > The UTS knows what thread was running and marks it as blocked
> > in the kernel and saves the unique KSE ID.
> >
> 
> How does it know what was running?

How can it not know?  It was the last thread scheduled.

It _has_ to know which threads are running on which processes in
order to effectively schedule them.  Our current threads library
knows what thread is currently running - it is kept in _thread_run.

We need to be able to retrieve TSD from a register, or perhaps
per-process data mapped at the same address but still accessible
to other subprocesses.  Can we play games with %gs and/or LDTs?
On the Alpha, can we just use an S register?  I dunno.  Another
problem that really needs to be solved.

> > When the process runs again (or the next subprocess, since you
> > can have more than 1 cooperating processes), a new KSE is
> > allocated and context is set to the relevent UTS event handler.
> > Event information is copied out to the top of the predefined
> > user stack, parameters set accordingly, and the kernel returns
> > to the UTS event handler.  If a thread was preempted for the
> > notification, then its context (just like getcontext(2)) is
> > also copied out to the UTS event handler user stack.
> 
> I think we agree here.
> My only point is that a lot of this can be achieved using stack munging and
> that we don't need to create a lot of special frame handling and
> context saving if we use the saved state that si already existant in the stacks.

I think we can do this with just an ID for a KSE.  The kernel will
save it's own registers, and it knows where the trapframe is.  Can't
it just save a pointer to the trapframe in the KSE, switch to a new
KSE and the UTS eventhandler frame, and pass an ID for the blocked
KSE back out to the UTS event handler?

> > The UTS resumes the blocked thread in one of two ways.  A new
> > system call to resume the KSE identified by it's unique ID is
> > one way.  The other way is to have the kernel copy the context
> > of the unblocked KSE out to the UTS event handler.  It can be
> > resumed with setcontext(2).
> 
> I think that I'd like to see this shown with simulated stacks and such
> in pictures..  I think you and I are in agreement, but having
> trouble saying that.

:-)  Pictures would be nice.  I'll work on some over the Thanksgiving
break.

Dan Eischen
eischen@vigrid.com




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?383BF031.B52BC41F>