Hi Everyone,
I've some questions with regards to Genode synchronization features between threads and components.
First a question about packet streams:
1) Can we expect the packet streams to deliver packets in order to the other component as a FIFO? Thus: can we expect the packet submitted first, to be delivered first at the other component? Also when bursts of packets are send through the packet stream?
Other questions are with regards to synchronization between multiple threads within the same component:
2) Say we have 2 threads in the same component, where Thread A needs to sleep until an event occurs in Thread B. How to address this? If A and B were components, signals would be the answer. Would signals also work between threads within the same component or is there some other approach?
3) What if those same 2 threads need to exchange data? When data is shared between components, shared memory would be the answer. How to approach this with 2 threads within the same component. Setup a shared data space? Do those 2 threads share the same heap which we can use for this exchange?
Thanks for thinking along.
Kind regards, Menno
PS. The first question is a repost, I noticed in my previous email the subject was partially discarded. Sorry about that.
Hello Menno,
First a question about packet streams:
- Can we expect the packet streams to deliver packets in order to the
other component as a FIFO? Thus: can we expect the packet submitted first, to be delivered first at the other component? Also when bursts of packets are send through the packet stream?
each packet stream has two ring buffers located within the dataspace shared between the packet source and packet sink.
* One ring buffer contains the packet descriptors of the submitted packets (submit queue). It is populated by the packet source and consumed by the packet sink.
* The other ring buffer contains the packet descriptors that were processed by the sink (acknowledgement queue). It is populated by the sink and consumed by the source.
Each of both queues are fifo queues. Hence the order of packets submitted is exactly the same as the order of packets observed at the receiving side.
However, both queues are independent from each other. E.g., a sink may take a whole batch of packets out of the submit queue and process the requests out of order. In this case, the order of packets descriptors the source receives in the acknowledgement queue will differ from the order of submissions.
Other questions are with regards to synchronization between multiple threads within the same component:
- Say we have 2 threads in the same component, where Thread A needs to
sleep until an event occurs in Thread B. How to address this? If A and B were components, signals would be the answer. Would signals also work between threads within the same component or is there some other approach?
Signals can be used between threads of the same component. In some situations, this is the simplest approach.
Alternatively, you can use a 'Genode::Lock' for the synchronization. E.g., one thread may wait for another one releasing a blockade using a 'Lock' that is initialized to be in locked state:
Lock lock(Lock::LOCKED);
The to-be sleeping thread A would block on the lock by calling:
lock.lock();
Because the lock was already locked, the attempt to lock it twice will result in the thread A to block.
The thread B can wake up thread A by releasing the lock:
lock.unlock();
Internally within Genode, we use this approach to synchronize the startup of threads and in other situations. Please grep for "Lock::LOCKED" in the source tree to get many examples for this pattern.
- What if those same 2 threads need to exchange data? When data is
shared between components, shared memory would be the answer. How to approach this with 2 threads within the same component. Setup a shared data space? Do those 2 threads share the same heap which we can use for this exchange?
Within a component, all memory is shared between threads. So there is no need to use a dataspace. You can simply pass a pointer or a reference for a component-local object to multiple threads. All threads can directly access it. However, great care must be taken for the synchronization of such shared state, usually by enforcing mutually exclusive access to the shared state via a lock.
Cheers Norman
On Thu, Apr 14, 2016 at 11:48:58AM +0200, Menno Valkema wrote:
Hi Everyone,
I've some questions with regards to Genode synchronization features between threads and components.
First a question about packet streams:
- Can we expect the packet streams to deliver packets in order to the
other component as a FIFO? Thus: can we expect the packet submitted first, to be delivered first at the other component? Also when bursts of packets are send through the packet stream?
There is a FIFO queue of packets from the source to the sink, and a FIFO queue of acknowledge packets from the sink back to the source. However, the sink could dequeue a number of packets and then acknowledge them out of order. A good component will strive to have minimal state, so it should be safe to assume that packets will be processed and acknowledged FIFO. Even if you get into the cases of network coding or disk head seek optimization, that sort of work would probably be done in a second buffer at the sink component and you'll still see FIFO behaviour.
- Say we have 2 threads in the same component, where Thread A needs to
sleep until an event occurs in Thread B. How to address this? If A and B were components, signals would be the answer. Would signals also work between threads within the same component or is there some other approach?
Signals would work between threads in the same component, but using simple primatives like locks and semaphores will give you better performance, because issueing signal capabilities and exchanging signals requires work outside the component.
- What if those same 2 threads need to exchange data? When data is
shared between components, shared memory would be the answer. How to approach this with 2 threads within the same component. Setup a shared data space? Do those 2 threads share the same heap which we can use for this exchange?
Multiple threads within a component use the same address space, there shouldn't be any extra work in shared data between threads. You have the option of using independent heaps on different RAM sessions, but the mapping is still in the same space.
Correct me anyone if I am wrong, Emery
Hi Norman and Emery,
Thank you for helping me out here! I'll start working with the techniques you've described.
Cheers, Menno
On 14-04-16 13:43, Emery wrote:
On Thu, Apr 14, 2016 at 11:48:58AM +0200, Menno Valkema wrote:
Hi Everyone,
I've some questions with regards to Genode synchronization features between threads and components.
First a question about packet streams:
- Can we expect the packet streams to deliver packets in order to the
other component as a FIFO? Thus: can we expect the packet submitted first, to be delivered first at the other component? Also when bursts of packets are send through the packet stream?
There is a FIFO queue of packets from the source to the sink, and a FIFO queue of acknowledge packets from the sink back to the source. However, the sink could dequeue a number of packets and then acknowledge them out of order. A good component will strive to have minimal state, so it should be safe to assume that packets will be processed and acknowledged FIFO. Even if you get into the cases of network coding or disk head seek optimization, that sort of work would probably be done in a second buffer at the sink component and you'll still see FIFO behaviour.
- Say we have 2 threads in the same component, where Thread A needs to
sleep until an event occurs in Thread B. How to address this? If A and B were components, signals would be the answer. Would signals also work between threads within the same component or is there some other approach?
Signals would work between threads in the same component, but using simple primatives like locks and semaphores will give you better performance, because issueing signal capabilities and exchanging signals requires work outside the component.
- What if those same 2 threads need to exchange data? When data is
shared between components, shared memory would be the answer. How to approach this with 2 threads within the same component. Setup a shared data space? Do those 2 threads share the same heap which we can use for this exchange?
Multiple threads within a component use the same address space, there shouldn't be any extra work in shared data between threads. You have the option of using independent heaps on different RAM sessions, but the mapping is still in the same space.
Correct me anyone if I am wrong, Emery
Find and fix application performance issues faster with Applications Manager Applications Manager provides deep performance insights into multiple tiers of your business applications. It resolves application problems quickly and reduces your MTTR. Get your free trial! https://ad.doubleclick.net/ddm/clk/302982198;130105516;z
genode-main mailing list genode-main@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/genode-main