The open source OpenXR runtime
1// Copyright 2020, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief IPC shared memory helpers
6 * @author Rylie Pavlik <rylie.pavlik@collabora.com>
7 * @author Pete Black <pblack@collabora.com>
8 * @author Jakob Bornecrantz <jakob@collabora.com>
9 * @ingroup ipc_shared
10 */
11
12#include <xrt/xrt_config_os.h>
13
14#include "shared/ipc_shmem.h"
15
16#if defined(XRT_OS_UNIX)
17#include <sys/mman.h>
18#include <unistd.h>
19#endif
20
21#if defined(XRT_OS_ANDROID)
22#include <android/sharedmem.h>
23#elif defined(XRT_OS_UNIX)
24// non-android unix
25#include <sys/stat.h>
26#include <fcntl.h>
27#endif
28
29#if defined(XRT_OS_ANDROID)
30
31#if __ANDROID_API__ < 26
32#error "Android API level 26 or higher needed for ASharedMemory_create"
33#endif
34xrt_result_t
35
36ipc_shmem_create(size_t size, xrt_shmem_handle_t *out_handle, void **out_map)
37{
38
39 int fd = ASharedMemory_create("monado", size);
40 if (fd < 0) {
41 return XRT_ERROR_IPC_FAILURE;
42 }
43 xrt_result_t result = ipc_shmem_map(fd, size, out_map);
44 if (result != XRT_SUCCESS) {
45 close(fd);
46 return result;
47 }
48 *out_handle = fd;
49 return XRT_SUCCESS;
50}
51
52#elif defined(XRT_OS_UNIX)
53
54#define MONADO_SHMEM_NAME "/monado_shm"
55// Impl for non-Android Unix.
56xrt_result_t
57ipc_shmem_create(size_t size, xrt_shmem_handle_t *out_handle, void **out_map)
58{
59 *out_handle = -1;
60 int fd = shm_open(MONADO_SHMEM_NAME, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
61 if (fd < 0) {
62 return XRT_ERROR_IPC_FAILURE;
63 }
64
65 if (ftruncate(fd, size) < 0) {
66 close(fd);
67 return XRT_ERROR_IPC_FAILURE;
68 }
69 xrt_result_t result = ipc_shmem_map(fd, size, out_map);
70 if (result != XRT_SUCCESS) {
71 close(fd);
72 return result;
73 }
74
75 // Don't need the name entry anymore, we can share the FD.
76 shm_unlink(MONADO_SHMEM_NAME);
77 *out_handle = fd;
78 return XRT_SUCCESS;
79}
80
81#elif defined(XRT_OS_WINDOWS)
82
83xrt_result_t
84ipc_shmem_create(size_t size, xrt_shmem_handle_t *out_handle, void **out_map)
85{
86 *out_handle = NULL;
87 LARGE_INTEGER sz = {.QuadPart = size};
88 HANDLE handle = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, sz.HighPart, sz.LowPart, NULL);
89 if (handle == NULL) {
90 return XRT_ERROR_IPC_FAILURE;
91 }
92
93 xrt_result_t result = ipc_shmem_map(handle, size, out_map);
94 if (result != XRT_SUCCESS) {
95 CloseHandle(handle);
96 return result;
97 }
98
99 *out_handle = handle;
100 return XRT_SUCCESS;
101}
102
103#else
104#error "OS not yet supported"
105#endif
106
107#if defined(XRT_OS_UNIX)
108
109void
110ipc_shmem_destroy(xrt_shmem_handle_t *handle_ptr, void **map_ptr, size_t size)
111{
112 // Checks for NULL.
113 ipc_shmem_unmap((void **)map_ptr, size);
114
115 if (handle_ptr == NULL) {
116 return;
117 }
118 xrt_shmem_handle_t handle = *handle_ptr;
119 if (handle < 0) {
120 return;
121 }
122 close(handle);
123 *handle_ptr = -1;
124}
125
126xrt_result_t
127ipc_shmem_map(xrt_shmem_handle_t handle, size_t size, void **out_map)
128{
129
130 const int access = PROT_READ | PROT_WRITE;
131 const int flags = MAP_SHARED;
132 void *ptr = mmap(NULL, size, access, flags, handle, 0);
133 if (ptr == NULL) {
134 return XRT_ERROR_IPC_FAILURE;
135 }
136 *out_map = ptr;
137 return XRT_SUCCESS;
138}
139
140void
141ipc_shmem_unmap(void **map_ptr, size_t size)
142{
143 if (map_ptr == NULL) {
144 return;
145 }
146 munmap(*map_ptr, size);
147 *map_ptr = NULL;
148}
149
150#elif defined(XRT_OS_WINDOWS)
151
152void
153ipc_shmem_destroy(xrt_shmem_handle_t *handle_ptr, void **map_ptr, size_t size)
154{
155 // Checks for NULL.
156 ipc_shmem_unmap((void **)map_ptr, size);
157
158 if (handle_ptr == NULL) {
159 return;
160 }
161 xrt_shmem_handle_t handle = *handle_ptr;
162 CloseHandle(handle);
163 *handle_ptr = NULL;
164}
165
166xrt_result_t
167ipc_shmem_map(xrt_shmem_handle_t handle, size_t size, void **out_map)
168{
169 void *ptr = MapViewOfFile(handle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, size);
170 if (ptr == NULL) {
171 return XRT_ERROR_IPC_FAILURE;
172 }
173 *out_map = ptr;
174 return XRT_SUCCESS;
175}
176
177void
178ipc_shmem_unmap(void **map_ptr, size_t size)
179{
180 if (map_ptr == NULL) {
181 return;
182 }
183 void *map = *map_ptr;
184 if (map == NULL) {
185 return;
186 }
187 UnmapViewOfFile(map);
188 *map_ptr = NULL;
189}
190
191#else
192#error "OS not yet supported"
193#endif