[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: synchronous RPCs vs. asynchronous RPCs
Re: synchronous RPCs vs. asynchronous RPCs
Fri, 5 Sep 2003 07:09:31 -0400 (EDT)
> Heretic claim of the day:
> "We should only do synchronous RPCs, and implement all asynchronous RPCs as
> synchronous RPCs performed by a helper thread."
Uh, I thought this was fundamental L4 dogma already.
> This applies to select()/poll(), asynchronous msync() and other operations
> like that.
msync with MS_ASYNC is just like e.g. file_sync with WAIT==0: it's a
synchronous RPC that requests an asynchronous action. It's not appropriate
to implement those things with asynchronous client use of synchronous RPC
interfaces. In those operations, there is a synchronous phase during which
errors can be diagnosed, and then asynchronous server work with no
completion notification to the client.
select/poll is one very special case. When I designed the io_select
interface in the first place, we understood from the beginning that the
style of multiplexing decoupled synchronous RPCs was exploiting specifics
of Mach IPC and the details of this interface would likely change using
significantly different IPC systems. Replacing io_select with an interface
that's substantially different for L4-Hurd is perfectly fine. (The
select-implementation RPCs we used in Fluke were very different from
> I don't think it should apply to notifications like task death
> notifications (although... I am still considering it! If we can restrict
> it to task death notifications, we only need one thread. Object death
> notifications for other capabilities can (from the servers point of view)
> safely deferred until the client actually tries to use the capability the
> next time - I have to check the Hurd code if other object death
> notifications are needed).
Haven't we covered this before? Long ago, in specifying the constraints of
what the Hurd needs from an underlying IPC system/object model we made it
very clear that we only need no-senders notifications for object
implementors (servers) to promptly know they have lost all attached
clients, and some form of timely task death handling that the proc server
(or moral equivalent) either uses or implements if it's in sufficient
control for that. We don't in general make use of dead-name notifications,
which are the general kind of object death notification Mach provides and
what serves as task death notification. In the places we do, it's to serve
some particular quirky need (and mostly those are side effects of Mach's
decouplable RPCs) and not a semantic model we insist on having.
> * An RPC consists of a send and a reply phase. The only way for a client
> to make sure it will reliably receive the reply is to go from the send
> to the receive operation atomically _and block_. The server just can
> sensibly assume that if the client doesn't care about the reply, it
> might be malicious and not sincere.
The latter presumption has some problems. Contrarily, blocking for a reply
exposes a client to potential malice or error from a server. In Mach, you
can use a simpleroutine and know that you will block until the server has
had a chance to get the message without possibility of dropping but not
block waiting for it to dick you around. Some of the Hurd's use of
simpleroutines relies on this security feature, and that would all have to
be checked and thought through carefully.
> * Consequence: This allows for a simple way to aviod DoS attacks on
This one is pretty meaningless to me. You can always create more threads.
Bottom line, this is just about resource constraint and you have to address
that in a more direct and general way rather than relying on quirky
> * Further consequence: Easy RPC interruption! If an RPC in a server is
> interrupted by the client (by the signal thread, usually), it can simply
> and uniquely be identified by the client's thread ID. No sequence numbers
> are needed to distinguish RPCs.
The notion that seemed appropriate when we thought about these issues for
Fluke was that the "alert" facility be a feature of the IPC system itself
rather than another layer like the Hurd's io_interrupt protocol. That is,
a client thread breaking out of an RPC sends a direct wakeup to the server
thread working for it, essentially the signal is translated across the RPC.
> * Good resource tracking: The client pays all costs associated with the RPC.
> This is not obvious, so here is an example: an asynchronous msync means
> that the client continues to run after the msync() invocation. But that
> means that the filesystem would have to pay for a copy of the synced page
> until the page is actually written back. This opens a DoS attack. By
> requiring the client to provide the page in a container with a synchronous
> msync(), the filesystem does not need to pay for a copy and can work on the
> client's resources.
You are thinking about the resource tracking the wrong way. The pages and
backing store are resources associated with the client by the mapping.
msync calls do not affect these resource allocations or enforcement.