@@ -543,6 +543,136 @@ lookup. The lookup function is particularly useful to allow an ODP application
that is divided into multiple processes to obtain the handle for the common
resource.
+== Shared memory
+=== Allocating shared memory
+Blocks of shared memory can be created using the +odp_shm_reserve()+ API
+call. The call expects a shared memory block name, a block size, an alignment
+requirement, and optional flags as parameters. It returns a +odp_shm_t+
+handle. The size and alignment requirement are given in bytes.
+
+.creating a block of shared memory
+[source,c]
+----
+#define ALIGNMENT 128
+#define BLKNAME "shared_items"
+
+odp_shm_t shm;
+uint32_t shm_flags = 0;
+
+typedef struct {
+...
+} shared_data_t;
+
+shm = odp_shm_reserve(BLKNAME, sizeof(shared_data_t), ALIGNMENT, shm_flags);
+----
+
+=== Getting the shared memory block address
+The returned odp_shm_t handle can then be used to retrieve the actual
+address (in the caller's ODP thread virtual address space) of the created
+shared memory block.
+
+.getting the address of a shared memory block
+[source,c]
+----
+shared_data_t *shared_data;
+shared_data = odp_shm_addr(shm);
+----
+
+The address returned by +odp_shm_addr()+ is valid only in the calling ODP
+thread space: odp_shm_t handles can be shared between ODP threads and remain
+valid within any threads, whereas the address returned by +odp_shm_addr(shm)+
+may differ from ODP threads to ODP threads (for the same 'shm' block), and
+should therefore not be shared between ODP threads.
+For instance, it would be correct to send a shm handle using IPC between two
+ODP threads and let each of these thread do their own +odp_shm_addr()+ to
+get the block address. Directly sending the address returned by
++odp_shm_addr()+ from one ODP thread to another would however possibly fail
+(the address may have no sense in the receiver address space).
+
+The address returned by +odp_shm_addr()+ is nevertheless guaranteed to be
+aligned according to the alignment requirements provided at block creation
+time, even if the call to +odp_shm_addr()+ is performed by a different ODP
+thread than the one which originally called +odp_shm_reserve()+.
+
+All shared memory blocks are contiguous in any ODP thread addressing space:
+'address' to 'address'\+'size' (where 'size' is the shared memory block size,
+as provided in the +odp_shm_reserve()+ call) is read and writeable and
+mapping the shared memory block. There is no fragmentation.
+
+=== Memory behaviour
+By default ODP threads are assumed to behave as cache coherent systems:
+Any change performed on a shared memory block is guaranteed to eventually
+become visible to other ODP threads sharing this memory block.
+(this behaviour may be altered by flags to +odp_shm_reserve()+ in the future).
+Nevertheless, there is no implicit memory barrier associated with any action
+on shared memories: *When* a change performed by an ODP thread becomes visible
+to another ODP thread is not known: An application using shared memory
+blocks has to use some memory barrier provided by ODP to guarantee shared data
+validity between ODP threads.
+
+=== Lookup by name
+As mentioned, shared memory handles can be sent from ODP threads to ODP
+threads using any IPC mechanism, and then the block address retrieved.
+A simpler approach to get the shared memory block handle of an already created
+block is to use the +odp_shm_lookup()+ API function call.
+This nevertheless requires the calling ODP thread to provide the name of the
+shared memory block:
++odp_shm_lookup()+ will return +ODP_SHM_INVALID+ if no shared memory block
+with the provided name is known by ODP.
+
+.retrieving a block handle and address from another ODP task
+[source,c]
+----
+#define BLKNAME "shared_items"
+
+odp_shm_t shm;
+shared_data_t *shared_data;
+
+shm = odp_shm_lookup(BLKNAME);
+if (shm != ODP_SHM_INVALID) {
+ shared_data = odp_shm_addr(shm);
+ ...
+}
+----
+
+=== Freeing memory
+Freeing shared memory is performed using the +odp_shm_free()+ API call.
++odp_shm_free()+ takes one single argument, the shared memory block handle.
+Any ODP thread is allowed to perform a +odp_shm_free()+ on a shared memory
+block (i.e. the thread performing the +odp_shm_free()+ may be different
+from the thread which did the +odp_shm_reserve()+). Shared memory blocks should
+be freed only once, and once freed, a shared memory block should no longer
+be referenced by any ODP threads.
+
+.freeing a shared memory block
+[source,c]
+----
+if (odp_shm_free(shm) != 0) {
+ ...//handle error
+}
+----
+
+=== Memory creation flags
+The last argument to odp_shm_reserve() is a set of ORed flags.
+Two flags are supported:
+
+==== ODP_SHM_PROC
+When this flag is given, the allocated shared memory will become visible
+outside ODP. Non ODP threads (e.g. usual linux process or linux threads)
+will be able to access the memory using native (non ODP) OS calls such as
+'shm_open()' and 'mmap' (for linux).
+Each ODP implementation should provide a description on exactly how
+this mapping should be done on that specific platform.
+
+==== ODP_SHM_SW_ONLY
+This flag tells ODP that the shared memory will be used by the ODP application
+software only: no HW (such as DMA, or other accelerator) will ever
+try to access the memory. No other ODP call will be involved on this memory
+(as ODP calls could implicitly involve HW, depending on the ODP
+implementation), except for +odp_shm_lookup()+ and +odp_shm_free()+.
+ODP implementations may use this flag as a hint for performance optimization,
+or may as well ignore this flag.
+
== Queues
Queues are the fundamental event sequencing mechanism provided by ODP and all
ODP applications make use of them either explicitly or implicitly. Queues are
section regarding shared memo added. Signed-off-by: Christophe Milard <christophe.milard@linaro.org> Reviewed-and-tested-by: Bill Fischofer <bill.fischofer@linaro.org> --- doc/users-guide/users-guide.adoc | 130 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+)