lkml.org 
[lkml]   [1998]   [Jun]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: Thread implementations...


On Tue, 23 Jun 1998, Richard Gooch wrote:

> Richard Gooch writes:
> > Dean Gaudet writes:
> > > On Tue, 23 Jun 1998, Richard Gooch wrote:
> > >
> > > > What exactly do you mean "you're told when it completes"?
> > >
> > > You write/read a buffer, and control returns immediately. Some
> > > unspecified time later, when the write/read completes, your program is
> > > informed either via a completion port (NT), or via a function you passed
> > > to the kernel (VMS).
> >
> > Can these NT completion ports multiple events from multiple FDs?
>
> Make that: "Can these NT completion ports multiplex events from
> multiple FDs?"

Yes.

A typical method of using them is to maintain a homogenous pool of worker
threads. Each worker thread can pick up a completed I/O, do further
processing on the request, and "suspend" the request when it next needs to
do I/O, and loop back to pick up some other completed I/O. To get an
event on the port you have to start an I/O and the kernel then registers
when the I/O has completed.

This is different from select/poll event processing. In this case the
events that the kernel delivers are of the form "if you read/write this FD
right now, it won't block". To get an event to occur you first try to
read/write and get EWOULDBLOCK and then you ask the kernel to tell you
when it wouldn't block.

Your proposal puts an event structure onto each FD, which the low level
driver updates to indicate read/write readiness. I'm advocating taking
that one step further and plop that readiness event onto a readiness
queue. In this way you can completely avoid the select/poll and all the
associated overhead -- instead you get a stream of "readiness" events from
the kernel.

Note that with sockets/pipes there is a read and write buffer, and it's
obvious how the above works for them (readiness indicates a
non-empty/non-full buffer as appropriate).

It's somewhat less critical for non-sockets, but something similar is
possible. Readiness for read means that a readahead completed... when the
app finally read()s the buffer may or may not be present -- if it isn't
present then return EWOULDBLOCK. For write, "readiness for write" means
that there is buffer space to take at least one page of data. And if the
app takes too long to issue the write(), return EWOULDBLOCK. i.e. just
pretend there is a read and write buffer... there is one, it's all the
buffer memory.

Now, completion ports and readiness queues are totally related. You can
implement a completion port in userland given a readiness queue... and you
can implement a completion port in userland given select/poll. At issue
is the efficiency of each solution.

BTW there's another class of problems with regular files which
applications like Squid run into (and which Apache will possibly run into
as we thread it... although I think I have an architecture to mostly avoid
the problems). open(), close(), unlink(), rename(), ... all the metadata
operations are synchronous. For example if I write a lean and mean single
threaded poll() based web server I'm still stuck with synchronous
open()... and to work around that I need to spawn multiple threads which
do the synchronous work. (This is how Squid works.) Making all of this
work without extra threads is a lot of trouble... and is probably not
worth it.

Dean



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu

\
 
 \ /
  Last update: 2005-03-22 13:43    [W:0.153 / U:0.544 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site