Dynamic creation and passing of IPC channels
Robert Kaiser
robert.kaiser at hs-rm.de
Tue Dec 10 21:39:56 CET 2013
Hi Björn,
Thanks for your reply (and sorry it took me so long to respond).
Am 25.11.2013 20:21, schrieb Björn Döbel:
> > Hi Robert,
> >
>> >> I have two tasks running and communicating through an IPC
>> >> connection (basically the clntsrv demo). Now I would like to
>> >> extend this a bit:
> >
> >
>> >> Using an ipc_call(), the client (actually: multiple clients)
>> >> should be able to register with a server to receive a wakeup IPC
>> >> at individually different points in time in the future.
> >
>> >> (First, flawed idea to do this was to *not* use the combined
>> >> reply_and_wait call on the server side but instead to only do a
>> >> wait() call and then postpone the corresponding reply() until
>> >> when the client should be woken up. However, I learned that this
>> >> will not work because the implicit reply capability will be lost
>> >> as soon as another ipc call is done by the server.)
> >
>> >> Next idea now is to create another IPC channel in the client and
>> >> to pass (via IPC) the send capability for that channel to the
>> >> server. The client shall than block in an ipc_receive() on that
>> >> channel and the server can wake it by sending to that channel. I
>> >> guess this should be possible and for a seasoned Fiasco.OC/L4Re
>> >> expert it is probably quite easy to do, but I can't seem to find
>> >> how to:
> >
>> >> - create an IPC channel at client/server run time (so far, all
>> >> IPC channels I used were prepared by Ned through lua scripts)
> >
> > IPC channels (aka IPC gates) can be created using the
> > l4_factory_create_gate() method (or its C++ sibling
> > L4Re::Env::env()->factory()->create_gate()).
> >
> > * During creation you bind() a thread to this gate. This is the
> > thread that is then allowed to receive messages through it. *
> > Anyone possessing a capability to the gate may send messages.
OK, I got this to work.
> >
>> >> - pass the send capability for such a channel to another task via
>> >> IPC
> >
> > Capabilities are passed around through standard IPC. The
> > difference is that you don't put them into the UTCB's message
> > registers but instead you out a send flexpage into the UTCB buffer
> > registers. Note, that the receiver must be willing to receive and
> > therefore has to add a receive flexpage on its side beforehand.
> >
>> >> Can anyone point me to some helpful documentation or maybe an
>> >> example I could cannibalize to implement this (preferably in C,
>> >> but C++ code would surely be helpful too)?
> >
> > Unfortunately, there's no example that does exactly what you want.
> > But you might want to look at the following two:
> >
> > * l4/pkg/examples/libs/l4re/streammap demonstrates delegation of
> > resources (memory pages in this case) from a server to a client.
> > Sending cap fpages is similar - you basically replace
> > Rcv_fpage::mem() with Rcv_fpage::obj() etc.
> >
> > * l4/pkg/examples/libs/l4re/c++/clntsrv_ns is an adaptation of
> > l4/pkg/examples/clntsrv that passes capabilities the other way
> > round. The client creates an IPC gate, sends it to the server
> > through an L4Re namespace, and the server then obtains this
> > channel and binds a server-side thread to receive messages through
> > this channel.
I *sort of* got this working, however there is a problem which I don't
understand.
My setup is:
Client does an ipc_call() to server, passing a flexpage describing the
dynamically created IPC gate, then waits for server's acknowledge
reply. Server puts a send flexpage into the buffer regs, then does an
ipc_wait ()which returns once the client does the ipc_call(). Server
then creates a thread, passing to it the index to the capability it
has just received, and then sends an acknowledge to client with
ipc_reply_and wait(). The thread created by the server will sleep for
some time (two seconds) an will then do an ipc_send() using the
received capability. Meanwhile, client returns from ipc_call() after
receiving the server's acknowledge and subsequently waits for the
message from the server thread via the dynamically created IPC gate.
And here comes the problem: if the client does an open receive (i.e.
ipc_wait()) at this point, everything works: The server thread
finishes its ipc_send() and the client returns from the ipc_wait()
call. However, if the client instead does an ipc_receive() at this
point, specifying the dynamically created IPC gate as sole source of
the message to be recieved, then it blocks forever (and the server
thread never returns from the corresponding ipc_send()).
I also noticed that the label returned by ipc_wait() is not exactly
the same as the value that was bound to the IPC gate. It seems that a
1 was added or ORed to the value. Is this indended behaviour?
Cheers
Robert
> > Cheers, Bjoern
> >
> > _______________________________________________ l4-hackers mailing
> > list l4-hackers at os.inf.tu-dresden.de
> > http://os.inf.tu-dresden.de/mailman/listinfo/l4-hackers
> >
More information about the l4-hackers
mailing list