Skip to content
Erlend Eriksen edited this page Dec 22, 2021 · 3 revisions

The ipc (Inter-Process-Synchronisation) system is based on Linux shared memory, with lock-less synchronisation.

The shmem abstraction handles creation and access of shared memory. In addition to construction and destruction, it defines a read and write function, to read and write messages passed over ipc. The synchronisation method is plugged in through the shmem_data_structure concept. The synchronisation method defines a state structure which is kept in the shmem. The state is used to detect if there have been a new message etc.

The default synchronisation is the sequence lock, as described in the linux kernel: https://lwn.net/Articles/21355/ . The lock-less building blocks are defined in https://github.com/BluEye-Robotics/tyndall/blob/master/tyndall/ipc/smp.h , which mirrors the relevant macros in the smp (Symmetric Multi-Processing) subsystem in the linux kernel.

The ipc abstraction defines two different interfaces to the shmem / seq_lock logic. The create_ipc_writer / reader macros just parses a message id / address using https://github.com/BluEye-Robotics/tyndall/blob/master/tyndall/ipc/id.h , and creates a shmem object. This object can be used by calling .read() and .write() on it.

The second interface is a lazy interface, allowing the caller to skip the creation step and just call ipc_read and ipc_write. The shmem object will be created on the first call with a new unique combination of parameters, because it is defined with the static keyword in a function template templated on both parameters. So subsequent calls with the same id and message type will use the same shmem object without creating a new one.

One important point about both interfaces is that access to the state used to determine if there are new messages is not synchronised. So regardless of the safety of the synchronisation used to protect the message passing across shared memory, the return code and errno values indicating if there was a new message or not could still be subject to races with concurrent calls using the same shmem object. In the case where you need to read a message from the same address / id on two different threads in the same process / translation unit, and you care about detecting new messages, you should create a shmem object for each thread using create_ipc_reader. Or use mutexes.

The two interfaces above relies on the message id / address being specified at compile time. If you need to specify the ids on runtime, then there is a identical interface taking normal c-strings in https://github.com/BluEye-Robotics/tyndall/blob/master/tyndall/ipc/ipc_rtid.h .

Examples of usage of the different interfaces can be found in https://github.com/BluEye-Robotics/tyndall/tree/master/examples/ipc and https://github.com/BluEye-Robotics/tyndall/blob/master/tests/ipc/ipc.cpp .

Clone this wiki locally