From: peter@ferranti.com (peter da silva)
Subject: Re: Multi uP P5 systems
Organization: Xenix Support, FICC
Date: Wed, 4 Nov 1992 17:02:12 GMT

In article <1291@taniwha.UUCP> paul@taniwha.UUCP (Paul Campbell) writes:
> What I really mean is where do you hold the data between when the actual IO
> completes and the wait() is called .....

In the kernel. For a fairly common case where you abort the I/O on a timeout
that saves you copying to process space. You also get a lot more robust
implementation if you can't accidentally trash pending I/O requests.

Making the system tolerant of programming error (or more precisely, designing
it to that it's easy to separate interface problems from programming problems)
has saved my butt so many times I'm REALLY reluctant to move anything to user
address space before the user process is ready for it.

> >Another problem with ASTs is that you either have to buffer them (reimplement
> >the O/S queuing mechanism) if you have multiple waits outstanding, or
> >explicitly hold them off (which if you analyse it becomes equivalent to

> ever hear of lists?

i.e. "reimplement the O/S queuing mechanism".

> >the above call in some fashion) possibly with polling (enable all ASTs,
> >did anything happen? No... disable, wait, and retry).

> No you have a sleep() call that puts the process asleep untill either
> it's woken up or an AST is delivered etc etc

Which is equivalent to the mechanism I'm suggesting.

> An AST driven program has a main routine that sets everything up, starts
> all the I/Os and then sleeps untill everything's done - each I/O completion
> starts the next I/O - for example 'cu' would have one AST reading from the
> TTY and writing to the console and another reading from the console and
> writing to the TTY, the main program would just open the devices, set their
> modes and wait for the session to close.

Which is exactly equivalent to the mechanism I'm talking about, except you
don't have to worry about library routines issuing their own sleeps (for
whatever reason... open, for example, is likely to be implemented that way
in a general asynchronous O/S) and then having to hold your own ASTs until
you know it's safe to call the runtime. You've reduced the difficult task of
writing asynchronous software to nearly as easy as writing synchronous
software.

Having ASTs is useful, and occasionally necessary, but they should NOT be
the normal mechanism for asynchronous I/O.

> Currently Unix systems have to make 2
> processes/threads and take context switches between them to have the same
> effect.

That's a red herring. I'm not talking about current UNIX implementations.

> >Using statically allocated memory is cheaper, if you're doing something for
> >which this is a high cost. Then you can use your own buffering scheme (such
> >as simple double buffering).

> but paged VM is even cheaper still ?

In real-time software *any* VM is a questionable design decision.

> >Actually, it's because of the way waits are designed with a sleep address
> >rather than a queue. I don't think anyone else uses this particular kludge.

> No, many Unix systems either have a uio structure that's allocated on
> the kernel stack (in which case the IO request can't return without 
> deallocating the IO context) or the equivalent that's allocated staticly
> in the U. - Systems that have threads have one of these per kernel thread
> context.

That design decision was made possible by the wait-address kludge.

> Well to stop flogging a dead horse .... let's talk about sleep()/wakeup()
> which I think are the Unix kernel equivalent of read()/write() in making it
> easy for kernel-neophytes to start kernel programming - these synchronization
> primitivtes are very forgiving compared with semaphores etc (sort of like
> a shotgun compared with a rifle :-) On the bad side they are sometimes rather
> slow - and not always fair .... 

Well, I think a better way to make kernel programming easier is to build the
system as a microkernel. Then a "kernel" process (driver, file system, and
so on) differs only in authorisation from a user process, and you can make
all the same calls from it. This has proven spectacularly successful in the
Amiga (which is a baby microkernel design, since it doesn't use memory
protection), with hobbyist-written drivers and file systems coming out very
early in the freeware cycle.
-- 
% Peter da Silva % 77487-5012 % +1 713 274 5180 % Har du kramat din varg idag?
/M{moveto}def/H{newpath 0 19 M 0 6 R 4 -4 R 0 16 M 5 0 R 3 -3 R -4 0 R -3 3 R 8
8 M 0 5 R stroke}def/R{rlineto}def 24 24 scale 3 3 translate H newpath 10 6 M 2
2 R -4 0 R closepath stroke 20 0 translate -1 1 scale H showpage %    `-_-'
Newsgroups: comp.arch