Hi all,
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) - pass the send capability for such a channel to another task via IPC
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)?
Thanks in advance for any help!
Robert
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
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.
- 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.
Cheers, Bjoern
On Mon Nov 25, 2013 at 20:21:07 +0100, Bjoern Doebel wrote:
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:
Another possibility regarding wakeups/notifications is to use L4::Irq's. They transfer no payload but allow to notify someone else without requiring an IPC channel. Maybe that's also ok for your use-case?
Adam
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@os.inf.tu-dresden.de http://os.inf.tu-dresden.de/mailman/listinfo/l4-hackers
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Hi Robert,
[..]
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.
Would you mind sharing your example code? This would make it easier to understand what's going on.
[..] 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?
Yes, it is. The lower two bits of the receive label contain the rights with which the respective capability was mapped into the sender's capability space.
As an example, this is used by memory managers to determine if a page fault shall be served read-only or writable. If you have the respective dataspace capability mapped with RW rights and call Dataspace::map(), the dataspace server sees this and gives you a writable memory mapping. If you have the Dataspace cap mapped RO, this call will result in a read-only memory mapping.
The whole capability-rights concept is unfortunately not well documented. :( Luckily, most of the time you won't need this feature at all. In this case the rule of thumb is to simply use labels that have the lower 2 bits set to 0 and mask those bits after receiving a message, which should give you the original label.
Bjoern
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256
Hi Björn,
Thanks for your response.
Am 12.12.2013 09:56, schrieb Björn Döbel:
Hi Robert,
[..]
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.
Would you mind sharing your example code? This would make it easier to understand what's going on.
I hope it is OK to send mails with attachments to the mailing list? If so, you'll find my source code attached. In file client_c.c, line 85/85, you'll find a commented-out ipc_receive() call followed by an ipc_wait() call.
In this version, the program produces following output:
.... Ned says: Hi World! Ned: loading file: 'rom/chanmap.cfg' server | Welcome to the C channel map example server! client | Channel map C client client | Passing response channel to server client | Sending item: Item received: 413008:413031 server | respthread: waiting 3 secs server | reply cap: 0x414000 server | Do_respond received server | # of words: 2 server | # of items: 1 server | Item received: 413038:1000260 server | Sending ack to client server | calling reply and wait client | Awaiting response from server server | respthread: sending message: 6 words client | Back from receive server | respthread: message sent server | respthread: hang forever client | It worked! Message received: Hello from the server
However, if I use ipc_receive() instead of ipc_wait() it hangs after "server | respthread: sending message: 6 words".
[..] 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?
Yes, it is. The lower two bits of the receive label contain the rights with which the respective capability was mapped into the sender's capability space.
Ahh, OK.
As an example, this is used by memory managers to determine if a page fault shall be served read-only or writable. If you have the respective dataspace capability mapped with RW rights and call Dataspace::map(), the dataspace server sees this and gives you a writable memory mapping. If you have the Dataspace cap mapped RO, this call will result in a read-only memory mapping.
The whole capability-rights concept is unfortunately not well documented. :(
I'm afraid, I'll have to agree here ;-)
Luckily, most of the time you won't need this feature at all. In this case the rule of thumb is to simply use labels that have the lower 2 bits set to 0 and mask those bits after receiving a message, which should give you the original label.
In fact that is what I did (unwittingly) by using the address of a word variable as label.
Cheers
Robert
Bjoern
l4-hackers mailing list l4-hackers@os.inf.tu-dresden.de http://os.inf.tu-dresden.de/mailman/listinfo/l4-hackers
Hello,
On Thu, 2013-12-12 at 17:57 +0100, Robert Kaiser wrote:
Hi Björn,
Thanks for your response.
Am 12.12.2013 09:56, schrieb Björn Döbel:
Hi Robert,
[..]
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.
Would you mind sharing your example code? This would make it easier to understand what's going on.
I hope it is OK to send mails with attachments to the mailing list? If so, you'll find my source code attached. In file client_c.c, line 85/85, you'll find a commented-out ipc_receive() call followed by an ipc_wait() call.
I think the problem is the first parameter of ipc_receive. The parameter specifies the object from which you would like to receive a message.
You wrote that you would like to receive a message from the IPC gate, but IMO you have to specify the thread from which you would like to receive a message.
Have a look on the following examples examples/sys/utcb-ipc/main.c examples/sys/aliens/main.c
Best regards, Tobias
l4-hackers@os.inf.tu-dresden.de