- 01 Mar, 2021 1 commit
-
-
Philippe Gerum authored
A receiver could get a spurious empty tube status, due to receive_tube() racing with send_tube(). See the added comments into the code for details about the resolution. At this chance, guard against load/store tearing on shared pointers. Pending issue: we still have a potential connectivity issue between the prep and finish ops when pushing to a tube. Signed-off-by:
Philippe Gerum <rpm@xenomai.org>
-
- 12 Dec, 2020 1 commit
-
-
Philippe Gerum authored
In user-space at least, we'd be better off trusting the CPU's branch predictor, instead of relying on our limited perception when it comes to determining the likeliness of a condition, or every compiler to do the right thing with respect to efficient branching. We only have a couple of likely predictions in-tree on straightforward conditions from the tube implementation code, which we can remove safely. Signed-off-by:
Philippe Gerum <rpm@xenomai.org>
-
- 26 Mar, 2020 1 commit
-
-
Philippe Gerum authored
Signed-off-by:
Philippe Gerum <rpm@xenomai.org>
-
- 03 Dec, 2019 2 commits
-
-
Philippe Gerum authored
No need to mention TUBE in canister macro declarators, there is no other type of canisters in the API but those flowing through tubes anyway.
-
Philippe Gerum authored
Just like DECLARE_EVL_TUBE_CANISTER() should be used explicitly for declaring a new canister type for a local tube, the same should be done with DECLARE_EVL_TUBE_CANISTER_REL() for a shared tube. Stop calling the latter implicitly from DECLARE_EVL_TUBE_REL(), to remain consist with DECLARE_EVL_TUBE() usage.
-
- 28 Nov, 2019 1 commit
-
-
Philippe Gerum authored
Signed-off-by:
Philippe Gerum <rpm@xenomai.org>
-
- 27 Nov, 2019 1 commit
-
-
Philippe Gerum authored
We need concurrent readers to always observe consistent ->next pointer values. We don't want the compiler to combine updates to it.
-
- 19 Nov, 2019 1 commit
-
-
Philippe Gerum authored
A lighweight, lockless multi-reader/multi-writer FIFO with a base-offset variant which can work over a memory segment shared between processes. Scalar data or simple (small!) aggregates are conveyed though a tube inside canisters which exactly fit their type. By design, a tube is meant to be a basic, spartan mechanism: it imposes no usage policy whatsoever on users. As a result, a tube is strictly non-blocking, it solely detects and notifies the caller on return about empty input (no message in) and output contention (no buffer space for output). If required, the caller can implement blocking states, typically with a pair of EVL semaphores, e.g. setting up a tube conveying integers which supports blocking mode: DECLARE_EVL_TUBE_CANISTER(canister_type, int); /* defines struct canister_type */ DECLARE_EVL_TUBE(tube_type, cannister_type) tube; struct cannister_type items[1024]; evl_init_tube(&tube, items, 1024); evl_new_sem(&in, ...); evl_new_sem_any(&out, CLOCK_MONOTONIC, tube.max_items, ...); evl_get_sem(&in, ...); @ evl_get_sem(&out); evl_tube_receive(&tube, ...); @ evl_tube_send(&tube, ...); evl_put_sem(&out); @ evl_put_sem(&in, ...);
-