messaging questions...
David Leimbach
leimy2k at mac.com
Mon Nov 24 17:24:16 PST 2003
Cool.. So now that I've actually got DragonFly running and I have the
kernel
source I can happily dig around in the messaging code and write some
examples.
If/when I get around to it would some example code be useful for the
website?
Dave
On Nov 19, 2003, at 3:32 PM, Matthew Dillon wrote:
:So, in essence, we are differentiating between a blocking call [there
:is no blocking call per-se] and
:whether the receiver can process the request in a blocking manner. If
:it requires blocking processing
:then we complete the request asynchronously and tell the caller to
move
:on.
:
:Essentially everything is "non-blocking" from the users perspective
due
:to the ability to queue work
:up internally on a thread's work queue. That thread is not
interacting
:with users directly though I would
:assume except maybe to deal with the reply port?
:
:How am I doing? :)
:
:This is a bit different from message passing as I am used to... but
:then I work with MPI all the time.
Yes, in a nutshell. Of course, there's some flexibility there.
For
example, in order to make incremental commits DragonFly's current
syscall messaging actually will block (because we haven't
rewritten the
kernel syscall backend to deal with the sync/async nature of the
messaging API). But eventually it will follow the semantics
correctly.
Also, even if a target could execute something synchronously
without
blocking it might decide to queue it anyway due to the complexity
of the operation.
So now you know what the target port's mp_beginmsg() function
does, going
back to the front end API lwkt_domsg() and lwkt_sendmsg()... these
functions abstract the interface to the client so the client does
not
have to worry about whether something returns EASYNC or not.
lwkt_domsg() looks like this. It basically always returns
synchrously
and is allowed to block. If it sees an async result from the
target
port function it will then wait for the message to be replied
synchronously, so EASYNC is never returned to the caller.
int
lwkt_domsg(lwkt_port_t port, lwkt_msg_t msg)
{
int error;
msg->ms_flags &= ~(MSGF_ASYNC | MSGF_REPLY | MSGF_QUEUED);
msg->ms_reply_port = &curthread->td_msgport;
msg->ms_abortreq = 0;
if ((error = lwkt_beginmsg(port, msg)) == EASYNC) {
error = lwkt_waitmsg(msg);
}
return(error);
}
lwkt_sendmsg() looks like this. The caller is always able to
assume
EASYNC when they call lwkt_sendmsg(). If the target port function
in
fact is able to run the message synchrously, lwkt_sendmsg() will
'fake'
asynchronous operation by replying the message itself.
void
lwkt_sendmsg(lwkt_port_t port, lwkt_msg_t msg)
{
int error;
msg->ms_flags |= MSGF_ASYNC;
msg->ms_flags &= ~(MSGF_REPLY | MSGF_QUEUED);
msg->ms_reply_port = &curthread->td_msgport;
msg->ms_abortreq = 0;
if ((error = lwkt_beginmsg(port, msg)) != EASYNC) {
lwkt_replymsg(msg, error);
}
}
The MSGF_ASYNC flag in the above functions serves only as a 'hint'
to
the target port's mp_beginmsg function. The target port is free to
return a synchronous or asynchronous result code regardless of what
the client has requested. The client uses the lwkt_domsg() and
lwkt_sendmsg() API to properly abstract the client's wishes and to
get
a deterministic 'always asynchronous' or 'always synchronous'
result
independant of how the target port actually decides to deal with
the
request.
-Matt
More information about the Kernel
mailing list