[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Single-threading servers and select()
- From: David Given <dg@...>
- Date: Sun, 23 Jan 2005 15:38:06 +0000
skaller wrote:
[...]
In reality, the arguments about blocking I/O and threads
are all peculiar to Unix -- how to take the C/Unix API
and work around the fact it was never designed to
do anything in real time.
*nods*
intent, which is the RTOS I know best, has true asynchronous I/O: everything
is done using callbacks. When a device completes an operation, the appropriate
callback is pushed onto the process' callback FIFO; the next time the
scheduler needs to reschedule the process, the next item on the FIFO gets
popped and executed.
The advantage is that from a process' point of view, all I/O is O(1)
regardless of how many pending requests there are. Unfortunately, the
disadvantage is that all the work happens inside callbacks, so if you want
absolute top performance (i.e., your callback doesn't just kick another
process that's been blocked) you end up with state machines.
VxWorks, which is another RTOS I've dealt with, uses the traditional Unix
model of blocking I/O. You need one task per blocked operation. This is fairly
unpleasant, and it's amazingly hard to cancel a pending operation --- the only
technique I found was to delete the task; and that showed up a number of bugs
in the device drivers.
The *real* I/O on a decent
box is concurrent anyhow (using DMA etc) so the issue
isn't how to get asynch I/O .. but how to get rid of it.
Emulating sync I/O on top of async is *easy*...
function blockingio()
local semaphore = Semaphore.new()
local callback = function()
semaphore:post()
end
asyncio(callback)
semaphore:wait()
end
Doing it the other way round is not.
This is what Unix does .. gets rid of asychronous I/O
because it is too hard to program with, and inefficient
in the time sharing batch processing environment Unix
was designed for.
*nods, again*
In a way it's a shame that Unix took off so much. It's an amazingly flexible,
powerful system --- at least as originally planned; Plan9 is pretty much the
only Unix that followed the original design philosophy --- but it's terribly
suited for doing a lot of tasks that it's now being used for.
Asynchronous I/O is just one example. Another one is proper use of the memory
manager. There's no reason why you can't have a persistant pointer to a file;
dereference the pointer and the appropriate file is opened and a block read.
This would trivialise the bulk of most program's file I/O; MULTICS did it
years ago; but you can't do it on a Unix because the underlying design doesn't
let you do that sort of thing. Sigh.
In an attempt to bring the discussion back on topic: you know what would be
really, really useful for Lua? A standard scheduler. Coroutines are superb
things, but if you actually want to use them for anything non-trivial you
start having to write a scheduler. It would be really useful to have a simple,
extendable, standard scheduler that could be used as the core for servers and
the like. I know there are a number out there, but they're all tailored for a
particular application. Imagine how much code could be thrown away by having a
standard one.
--
[insert interesting .sig here]