From 20c65e74e3703330b15119b7204dac86cba34351 Mon Sep 17 00:00:00 2001 From: Ryan Pavlik Date: Thu, 16 Jul 2020 11:21:13 -0500 Subject: [PATCH] ipc: Define shmem utilities for Linux and Android --- src/xrt/ipc/CMakeLists.txt | 2 + src/xrt/ipc/ipc_shmem.c | 116 +++++++++++++++++++++++++++++++++++++ src/xrt/ipc/ipc_shmem.h | 70 ++++++++++++++++++++++ src/xrt/ipc/meson.build | 4 +- 4 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 src/xrt/ipc/ipc_shmem.c create mode 100644 src/xrt/ipc/ipc_shmem.h diff --git a/src/xrt/ipc/CMakeLists.txt b/src/xrt/ipc/CMakeLists.txt index ccd5c0f93..6128fd092 100644 --- a/src/xrt/ipc/CMakeLists.txt +++ b/src/xrt/ipc/CMakeLists.txt @@ -24,6 +24,8 @@ proto_gen(${CMAKE_CURRENT_BINARY_DIR}/ipc_server_generated.c) set(IPC_COMMON_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/ipc_protocol_generated.h + ipc_shmem.c + ipc_shmem.h ipc_utils.c ipc_utils.h) ### diff --git a/src/xrt/ipc/ipc_shmem.c b/src/xrt/ipc/ipc_shmem.c new file mode 100644 index 000000000..a6736253f --- /dev/null +++ b/src/xrt/ipc/ipc_shmem.c @@ -0,0 +1,116 @@ +// Copyright 2020, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief IPC shared memory helpers + * @author Ryan Pavlik + * @author Pete Black + * @author Jakob Bornecrantz + * @ingroup ipc_internal + */ + +#include + +#include "ipc_shmem.h" + +#if defined(XRT_OS_UNIX) +#include +#include +#endif + +#if defined(XRT_OS_ANDROID) +#include +#elif defined(XRT_OS_UNIX) +// non-android unix +#include +#include +#endif + +#if defined(XRT_OS_ANDROID) + +#if __ANDROID_API__ < 26 +#error "Android API level 26 or higher needed for ASharedMemory_create" +#endif +xrt_result_t + +ipc_shmem_create(size_t size, xrt_shmem_handle_t *out_handle, void **out_map) +{ + + int fd = ASharedMemory_create("monado", size); + if (fd < 0) { + return XRT_ERROR_IPC_FAILURE; + } + xrt_result_t result = ipc_shmem_map(fd, size, out_map); + if (result != XRT_SUCCESS) { + close(fd); + return result; + } + *out_handle = fd; + return XRT_SUCCESS; +} + +#elif defined(XRT_OS_UNIX) + +#define MONADO_SHMEM_NAME "/monado_shm" +// Impl for non-Android Unix. +xrt_result_t +ipc_shmem_create(size_t size, xrt_shmem_handle_t *out_handle, void **out_map) +{ + *out_handle = -1; + int fd = + shm_open(MONADO_SHMEM_NAME, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); + if (fd < 0) { + return XRT_ERROR_IPC_FAILURE; + } + + if (ftruncate(fd, size) < 0) { + close(fd); + return XRT_ERROR_IPC_FAILURE; + } + xrt_result_t result = ipc_shmem_map(fd, size, out_map); + if (result != XRT_SUCCESS) { + close(fd); + return result; + } + + // Don't need the name entry anymore, we can share the FD. + shm_unlink(MONADO_SHMEM_NAME); + *out_handle = fd; + return XRT_SUCCESS; +} + +#else +#error "OS not yet supported" +#endif + +#if defined(XRT_OS_UNIX) +void +ipc_shmem_destroy(xrt_shmem_handle_t *handle_ptr) +{ + if (handle_ptr == NULL) { + return; + } + xrt_shmem_handle_t handle = *handle_ptr; + if (handle < 0) { + return; + } + close(handle); + *handle_ptr = -1; +} + +xrt_result_t +ipc_shmem_map(xrt_shmem_handle_t handle, size_t size, void **out_map) +{ + + const int access = PROT_READ | PROT_WRITE; + const int flags = MAP_SHARED; + void *ptr = mmap(NULL, size, access, flags, handle, 0); + if (ptr == NULL) { + return XRT_ERROR_IPC_FAILURE; + } + *out_map = ptr; + return XRT_SUCCESS; +} +#else +#error "OS not yet supported" +#endif diff --git a/src/xrt/ipc/ipc_shmem.h b/src/xrt/ipc/ipc_shmem.h new file mode 100644 index 000000000..fcf703ff1 --- /dev/null +++ b/src/xrt/ipc/ipc_shmem.h @@ -0,0 +1,70 @@ +// Copyright 2020, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Shared memory helpers + * @author Ryan Pavlik + * @ingroup ipc_internal + */ + +#pragma once + +#include +#include + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * @class xrt_shmem_handle_t + * @brief Generic typedef for platform-specific shared memory handle. + */ +/*! + * Create and map a shared memory region. + * + * @param[in] size Desired size of region + * @param[in,out] out_handle Pointer to the handle to populate. Receives the + * handle if this succeeds, or the invalid value if it fails. + * @param[in,out] out_map Pointer to the pointer to populate with the mapping of + * this shared memory region. On failure, contents are undefined. + * + * @public @memberof xrt_shmem_handle_t + */ +xrt_result_t +ipc_shmem_create(size_t size, xrt_shmem_handle_t *out_handle, void **out_map); + +/*! + * Map a shared memory region. + * + * @param[in] handle Handle for region + * @param[in] size Size of region + * @param[in,out] out_map Pointer to the pointer to populate with the mapping of + * this shared memory region. + * + * @public @memberof xrt_shmem_handle_t + */ +xrt_result_t +ipc_shmem_map(xrt_shmem_handle_t handle, size_t size, void **out_map); + +/*! + * Destroy a handle to a shared memory region. + * + * This probably does not destroy the underlying region, if other references to + * it (in this process or others) are still open. + * + * @param[in,out] handle_ptr Pointer to the handle to destroy - will be checked + * for validity, destroyed, and cleared. + * + * @public @memberof xrt_shmem_handle_t + */ +void +ipc_shmem_destroy(xrt_shmem_handle_t *handle_ptr); + +#ifdef __cplusplus +} +#endif diff --git a/src/xrt/ipc/meson.build b/src/xrt/ipc/meson.build index ec325547b..ec9e1e252 100644 --- a/src/xrt/ipc/meson.build +++ b/src/xrt/ipc/meson.build @@ -9,6 +9,8 @@ ipc_include = include_directories('.') prog_python = import('python').find_installation('python3') common_sources = [ + 'ipc_shmem.c', + 'ipc_shmem.h', 'ipc_utils.c', 'ipc_utils.h', ] @@ -44,7 +46,7 @@ lib_ipc_client = static_library( include_directories: [ xrt_include, ], - dependencies: [aux] + dependencies: [aux, rt] )