Monado OpenXR Runtime
ipc_server.h
Go to the documentation of this file.
1// Copyright 2020-2023, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Common server side code.
6 * @author Pete Black <pblack@collabora.com>
7 * @author Jakob Bornecrantz <jakob@collabora.com>
8 * @author Rylie Pavlik <rylie.pavlik@collabora.com>
9 * @ingroup ipc_server
10 */
11
12#pragma once
13
14#include "xrt/xrt_compiler.h"
15#include "xrt/xrt_limits.h"
16#include "xrt/xrt_space.h"
17#include "xrt/xrt_system.h"
18
19#include "os/os_threading.h"
20
21#include "util/u_logging.h"
22
23#include "shared/ipc_protocol.h"
25
26#include <stdio.h>
27
28
29#ifdef __cplusplus
30extern "C" {
31#endif
32
33/*
34 *
35 * Logging
36 *
37 */
38
39#define IPC_TRACE(d, ...) U_LOG_IFL_T(d->log_level, __VA_ARGS__)
40#define IPC_DEBUG(d, ...) U_LOG_IFL_D(d->log_level, __VA_ARGS__)
41#define IPC_INFO(d, ...) U_LOG_IFL_I(d->log_level, __VA_ARGS__)
42#define IPC_WARN(d, ...) U_LOG_IFL_W(d->log_level, __VA_ARGS__)
43#define IPC_ERROR(d, ...) U_LOG_IFL_E(d->log_level, __VA_ARGS__)
44
45
46/*
47 *
48 * Structs
49 *
50 */
51
52#define IPC_MAX_CLIENT_SEMAPHORES 8
53#define IPC_MAX_CLIENT_SWAPCHAINS (XRT_MAX_LAYERS * 2)
54#define IPC_MAX_CLIENT_SPACES 128
55
56struct xrt_instance;
57struct xrt_compositor;
59
60
61/*!
62 * Information about a single swapchain.
63 *
64 * @ingroup ipc_server
65 */
67{
68 uint32_t width;
69 uint32_t height;
70 uint64_t format;
71 uint32_t image_count;
72
73 bool active;
74};
75
76/*!
77 * Holds the state for a single client.
78 *
79 * @ingroup ipc_server
80 */
82{
83 //! Link back to the main server.
85
86 //! Session for this client.
87 struct xrt_session *xs;
88
89 //! Compositor for this client.
91
92 //! Is the inputs and outputs active.
94
95 //! Number of swapchains in use by client
97
98 //! Ptrs to the swapchains
99 struct xrt_swapchain *xscs[IPC_MAX_CLIENT_SWAPCHAINS];
100
101 //! Data for the swapchains.
102 struct ipc_swapchain_data swapchain_data[IPC_MAX_CLIENT_SWAPCHAINS];
103
104 //! Number of compositor semaphores in use by client
106
107 //! Ptrs to the semaphores.
108 struct xrt_compositor_semaphore *xcsems[IPC_MAX_CLIENT_SEMAPHORES];
109
110 struct
111 {
112 uint32_t root;
113 uint32_t local;
114 uint32_t stage;
115 uint32_t unbounded;
116 } semantic_spaces;
117
118 //! Number of spaces.
119 uint32_t space_count;
120 //! Index of localspace in ipc client.
122 //! Index of localspace in space overseer.
124 //! Index of localfloorspace in ipc client.
126 //! Index of localfloorspace in space overseer.
128
129 //! Ptrs to the spaces.
130 struct xrt_space *xspcs[IPC_MAX_CLIENT_SPACES];
131
132 //! Which of the references spaces is the client using.
134
135 //! Which of the device features is the client using.
136 bool device_feature_used[XRT_DEVICE_FEATURE_MAX_ENUM];
137
138 //! Socket fd used for client comms
140
141 struct ipc_app_state client_state;
142
143
144 uint64_t plane_detection_size;
145 uint64_t plane_detection_count;
146
147 //! Array of plane detection ids with plane_detection_size entries.
149
150 //! Array of xrt_devices with plane_detection_size entries.
152
153 int server_thread_index;
154};
155
156enum ipc_thread_state
157{
158 IPC_THREAD_READY,
159 IPC_THREAD_STARTING,
160 IPC_THREAD_RUNNING,
161 IPC_THREAD_STOPPING,
162};
163
165{
166 struct os_thread thread;
167 volatile enum ipc_thread_state state;
168 volatile struct ipc_client_state ics;
169};
170
171
172/*!
173 *
174 */
176{
177 //! The actual device.
179
180 //! Is the IO suppressed for this device.
182};
183
184/*!
185 * Platform-specific mainloop object for the IPC server.
186 *
187 * Contents are essentially implementation details, but are listed in full here so they may be included by value in the
188 * main ipc_server struct.
189 *
190 * @see ipc_design
191 *
192 * @ingroup ipc_server
193 */
195{
196
197#if defined(XRT_OS_ANDROID) || defined(XRT_OS_LINUX) || defined(XRT_DOXYGEN)
198 //! For waiting on various events in the main thread.
200#endif
201
202#if defined(XRT_OS_ANDROID) || defined(XRT_DOXYGEN)
203 /*!
204 * @name Android Mainloop Members
205 * @{
206 */
207
208 //! File descriptor for the read end of our pipe for submitting new clients
210
211 /*!
212 * File descriptor for the write end of our pipe for submitting new clients
213 *
214 * Must hold client_push_mutex while writing.
215 */
217
218 /*!
219 * Mutex for being able to register oneself as a new client.
220 *
221 * Locked only by threads in `ipc_server_mainloop_add_fd()`.
222 *
223 * This must be locked first, and kept locked the entire time a client is attempting to register and wait for
224 * confirmation. It ensures no acknowledgements of acceptance are lost and moves the overhead of ensuring this
225 * to the client thread.
226 */
227 pthread_mutex_t client_push_mutex;
228
229
230 /*!
231 * The last client fd we accepted, to acknowledge client acceptance.
232 *
233 * Also used as a sentinel during shutdown.
234 *
235 * Must hold accept_mutex while writing.
236 */
238
239 /*!
240 * Condition variable for accepting clients.
241 *
242 * Signalled when @ref last_accepted_fd is updated.
243 *
244 * Associated with @ref accept_mutex
245 */
246 pthread_cond_t accept_cond;
247
248 /*!
249 * Mutex for accepting clients.
250 *
251 * Locked by both clients and server: that is, by threads in `ipc_server_mainloop_add_fd()` and in the
252 * server/compositor thread in an implementation function called from `ipc_server_mainloop_poll()`.
253 *
254 * Exists to operate in conjunction with @ref accept_cond - it exists to make sure that the client can be woken
255 * when the server accepts it.
256 */
257 pthread_mutex_t accept_mutex;
258
259
260 /*! @} */
261#define XRT_IPC_GOT_IMPL
262#endif
263
264#if (defined(XRT_OS_LINUX) && !defined(XRT_OS_ANDROID)) || defined(XRT_DOXYGEN)
265 /*!
266 * @name Desktop Linux Mainloop Members
267 * @{
268 */
269
270 //! Socket that we accept connections on.
272
273 //! Were we launched by socket activation, instead of explicitly?
275
276 //! The socket filename we bound to, if any.
278
279 /*! @} */
280
281#define XRT_IPC_GOT_IMPL
282#endif
283
284#if defined(XRT_OS_WINDOWS) || defined(XRT_DOXYGEN)
285 /*!
286 * @name Desktop Windows Mainloop Members
287 * @{
288 */
289
290 //! Named Pipe that we accept connections on.
292
293 //! Name of the Pipe that we accept connections on.
295
296 /*! @} */
297
298#define XRT_IPC_GOT_IMPL
299#endif
300
301#ifndef XRT_IPC_GOT_IMPL
302#error "Need port"
303#endif
304};
305
306/*!
307 * De-initialize the mainloop object.
308 * @public @memberof ipc_server_mainloop
309 */
310void
312
313/*!
314 * Initialize the mainloop object.
315 *
316 * @return <0 on error.
317 * @public @memberof ipc_server_mainloop
318 */
319int
321
322/*!
323 * @brief Poll the mainloop.
324 *
325 * Any errors are signalled by calling ipc_server_handle_failure()
326 * @public @memberof ipc_server_mainloop
327 */
328void
330
331/*!
332 * Main IPC object for the server.
333 *
334 * @ingroup ipc_server
335 */
337{
338 struct xrt_instance *xinst;
339
340 //! Handle for the current process, e.g. pidfile on linux
342
343 struct u_debug_gui *debug_gui;
344
345 //! The @ref xrt_iface level system.
347
348 //! System devices.
350
351 //! Space overseer.
353
354 //! System compositor.
356
359
360 struct ipc_shared_memory *ism;
361 xrt_shmem_handle_t ism_handle;
362
363 struct ipc_server_mainloop ml;
364
365 // Is the mainloop supposed to run.
366 volatile bool running;
367
368 // Should we exit when a client disconnects.
369 bool exit_on_disconnect;
370
371 enum u_logging_level log_level;
372
373 struct ipc_thread threads[IPC_MAX_CLIENTS];
374
375 volatile uint32_t current_slot_index;
376
377 //! Generator for IDs.
378 uint32_t id_generator;
379
380 struct
381 {
382 int active_client_index;
383 int last_active_client_index;
384
385 struct os_mutex lock;
386 } global_state;
387};
388
389
390/*!
391 * Get the current state of a client.
392 *
393 * @ingroup ipc_server
394 */
396ipc_server_get_client_app_state(struct ipc_server *s, uint32_t client_id, struct ipc_app_state *out_ias);
397
398/*!
399 * Set the new active client.
400 *
401 * @ingroup ipc_server
402 */
404ipc_server_set_active_client(struct ipc_server *s, uint32_t client_id);
405
406/*!
407 * Toggle the io for this client.
408 *
409 * @ingroup ipc_server
410 */
412ipc_server_toggle_io_client(struct ipc_server *s, uint32_t client_id);
413
414/*!
415 * Called by client threads to set a session to active.
416 *
417 * @ingroup ipc_server
418 */
419void
421
422/*!
423 * Called by client threads to set a session to deactivate.
424 *
425 * @ingroup ipc_server
426 */
427void
429
430/*!
431 * Called by client threads to recalculate active client.
432 *
433 * @ingroup ipc_server
434 */
435void
437
438/*!
439 * Thread function for the client side dispatching.
440 *
441 * @ingroup ipc_server
442 */
443void *
444ipc_server_client_thread(void *_ics);
445
446/*!
447 * This destroys the native compositor for this client and any extra objects
448 * created from it, like all of the swapchains.
449 */
450void
452
453/*!
454 * @defgroup ipc_server_internals Server Internals
455 * @brief These are only called by the platform-specific mainloop polling code.
456 * @ingroup ipc_server
457 * @{
458 */
459/*!
460 * Called when a client has connected, it takes the client's ipc handle.
461 * Handles all things needed to be done for a client connecting, like starting
462 * it's thread.
463 *
464 * @param vs The IPC server.
465 * @param ipc_handle Handle to communicate over.
466 * @memberof ipc_server
467 */
468void
470
471/*!
472 * Perform whatever needs to be done when the mainloop polling encounters a failure.
473 * @memberof ipc_server
474 */
475void
477
478/*!
479 * Perform whatever needs to be done when the mainloop polling identifies that the server should be shut down.
480 *
481 * Does something like setting a flag or otherwise signalling for shutdown: does not itself explicitly exit.
482 * @memberof ipc_server
483 */
484void
486
488ipc_server_get_system_properties(struct ipc_server *vs, struct xrt_system_properties *out_properties);
489//! @}
490
491/*
492 *
493 * Helpers
494 *
495 */
496
497/*!
498 * Get a xdev with the given device_id.
499 */
500static inline struct xrt_device *
501get_xdev(volatile struct ipc_client_state *ics, uint32_t device_id)
502{
503 return ics->server->idevs[device_id].xdev;
504}
505
506/*!
507 * Get a idev with the given device_id.
508 */
509static inline struct ipc_device *
510get_idev(volatile struct ipc_client_state *ics, uint32_t device_id)
511{
512 return &ics->server->idevs[device_id];
513}
514
515
516#ifdef __cplusplus
517}
518#endif
Generic typedef for platform-specific shared memory handle.
u_logging_level
Logging level enum.
Definition: u_logging.h:43
void ipc_server_handle_client_connected(struct ipc_server *vs, xrt_ipc_handle_t ipc_handle)
Called when a client has connected, it takes the client's ipc handle.
Definition: ipc_server_process.c:909
void ipc_server_handle_shutdown_signal(struct ipc_server *vs)
Perform whatever needs to be done when the mainloop polling identifies that the server should be shut...
Definition: ipc_server_process.c:903
void ipc_server_handle_failure(struct ipc_server *vs)
Perform whatever needs to be done when the mainloop polling encounters a failure.
Definition: ipc_server_process.c:896
xrt_result_t ipc_server_get_client_app_state(struct ipc_server *s, uint32_t client_id, struct ipc_app_state *out_ias)
Get the current state of a client.
Definition: ipc_server_process.c:806
void ipc_server_deactivate_session(volatile struct ipc_client_state *ics)
Called by client threads to set a session to deactivate.
Definition: ipc_server_process.c:870
void ipc_server_activate_session(volatile struct ipc_client_state *ics)
Called by client threads to set a session to active.
Definition: ipc_server_process.c:836
void * ipc_server_client_thread(void *_ics)
Thread function for the client side dispatching.
Definition: ipc_server_per_client_thread.c:362
void ipc_server_update_state(struct ipc_server *s)
Called by client threads to recalculate active client.
Definition: ipc_server_process.c:885
xrt_result_t ipc_server_set_active_client(struct ipc_server *s, uint32_t client_id)
Set the new active client.
Definition: ipc_server_process.c:816
xrt_result_t ipc_server_toggle_io_client(struct ipc_server *s, uint32_t client_id)
Toggle the io for this client.
Definition: ipc_server_process.c:826
#define XRT_SYSTEM_MAX_DEVICES
Maximum number of devices simultaneously usable by an implementation of xrt_system_devices.
Definition: xrt_system.h:142
#define XRT_SPACE_REFERENCE_TYPE_COUNT
The number of enumerations in xrt_reference_space_type.
Definition: xrt_defines.h:614
enum xrt_result xrt_result_t
Result type used across Monado.
IPC message channel functions.
Common protocol definition.
void ipc_server_client_destroy_session_and_compositor(volatile struct ipc_client_state *ics)
This destroys the native compositor for this client and any extra objects created from it,...
Definition: ipc_server_per_client_thread.c:331
static struct xrt_device * get_xdev(volatile struct ipc_client_state *ics, uint32_t device_id)
Get a xdev with the given device_id.
Definition: ipc_server.h:501
static struct ipc_device * get_idev(volatile struct ipc_client_state *ics, uint32_t device_id)
Get a idev with the given device_id.
Definition: ipc_server.h:510
Wrapper around OS threading native functions.
State for a connected application.
Definition: ipc_protocol.h:334
Holds the state for a single client.
Definition: ipc_server.h:82
uint32_t swapchain_count
Number of swapchains in use by client.
Definition: ipc_server.h:96
struct xrt_swapchain * xscs[(XRT_MAX_LAYERS *2)]
Ptrs to the swapchains.
Definition: ipc_server.h:99
struct xrt_session * xs
Session for this client.
Definition: ipc_server.h:87
struct ipc_message_channel imc
Socket fd used for client comms.
Definition: ipc_server.h:139
struct xrt_device ** plane_detection_xdev
Array of xrt_devices with plane_detection_size entries.
Definition: ipc_server.h:151
struct ipc_server * server
Link back to the main server.
Definition: ipc_server.h:84
uint32_t local_floor_space_index
Index of localfloorspace in ipc client.
Definition: ipc_server.h:125
struct ipc_swapchain_data swapchain_data[(XRT_MAX_LAYERS *2)]
Data for the swapchains.
Definition: ipc_server.h:102
uint32_t compositor_semaphore_count
Number of compositor semaphores in use by client.
Definition: ipc_server.h:105
uint32_t local_space_overseer_index
Index of localspace in space overseer.
Definition: ipc_server.h:123
struct xrt_space * xspcs[128]
Ptrs to the spaces.
Definition: ipc_server.h:130
uint32_t local_space_index
Index of localspace in ipc client.
Definition: ipc_server.h:121
bool ref_space_used[XRT_SPACE_REFERENCE_TYPE_COUNT]
Which of the references spaces is the client using.
Definition: ipc_server.h:133
struct xrt_compositor_semaphore * xcsems[8]
Ptrs to the semaphores.
Definition: ipc_server.h:108
uint32_t space_count
Number of spaces.
Definition: ipc_server.h:119
bool device_feature_used[XRT_DEVICE_FEATURE_MAX_ENUM]
Which of the device features is the client using.
Definition: ipc_server.h:136
bool io_active
Is the inputs and outputs active.
Definition: ipc_server.h:93
uint64_t * plane_detection_ids
Array of plane detection ids with plane_detection_size entries.
Definition: ipc_server.h:148
uint32_t local_floor_space_overseer_index
Index of localfloorspace in space overseer.
Definition: ipc_server.h:127
struct xrt_compositor * xc
Compositor for this client.
Definition: ipc_server.h:90
Definition: ipc_server.h:176
bool io_active
Is the IO suppressed for this device.
Definition: ipc_server.h:181
struct xrt_device * xdev
The actual device.
Definition: ipc_server.h:178
Wrapper for a socket and flags.
Definition: ipc_message_channel.h:30
Platform-specific mainloop object for the IPC server.
Definition: ipc_server.h:195
bool launched_by_socket
Were we launched by socket activation, instead of explicitly?
Definition: ipc_server.h:274
pthread_cond_t accept_cond
Condition variable for accepting clients.
Definition: ipc_server.h:246
char * pipe_name
Name of the Pipe that we accept connections on.
Definition: ipc_server.h:294
int last_accepted_fd
The last client fd we accepted, to acknowledge client acceptance.
Definition: ipc_server.h:237
int epoll_fd
For waiting on various events in the main thread.
Definition: ipc_server.h:199
void ipc_server_mainloop_deinit(struct ipc_server_mainloop *ml)
De-initialize the mainloop object.
Definition: ipc_server_mainloop_android.c:160
pthread_mutex_t accept_mutex
Mutex for accepting clients.
Definition: ipc_server.h:257
int pipe_read
File descriptor for the read end of our pipe for submitting new clients.
Definition: ipc_server.h:209
int listen_socket
Socket that we accept connections on.
Definition: ipc_server.h:271
int pipe_write
File descriptor for the write end of our pipe for submitting new clients.
Definition: ipc_server.h:216
int ipc_server_mainloop_init(struct ipc_server_mainloop *ml)
Initialize the mainloop object.
Definition: ipc_server_mainloop_android.c:142
char * socket_filename
The socket filename we bound to, if any.
Definition: ipc_server.h:277
pthread_mutex_t client_push_mutex
Mutex for being able to register oneself as a new client.
Definition: ipc_server.h:227
void ipc_server_mainloop_poll(struct ipc_server *vs, struct ipc_server_mainloop *ml)
Poll the mainloop.
Definition: ipc_server_mainloop_android.c:119
HANDLE pipe_handle
Named Pipe that we accept connections on.
Definition: ipc_server.h:291
Main IPC object for the server.
Definition: ipc_server.h:337
struct u_process * process
Handle for the current process, e.g. pidfile on linux.
Definition: ipc_server.h:341
struct xrt_system_compositor * xsysc
System compositor.
Definition: ipc_server.h:355
struct xrt_space_overseer * xso
Space overseer.
Definition: ipc_server.h:352
uint32_t id_generator
Generator for IDs.
Definition: ipc_server.h:378
struct xrt_system * xsys
The XRT interfaces level system.
Definition: ipc_server.h:346
struct xrt_system_devices * xsysd
System devices.
Definition: ipc_server.h:349
A big struct that contains all data that is shared to a client, no pointers allowed in this.
Definition: ipc_protocol.h:215
Information about a single swapchain.
Definition: ipc_server.h:67
Definition: ipc_server.h:165
A wrapper around a native mutex.
Definition: os_threading.h:55
A wrapper around a native thread.
Definition: os_threading.h:272
Definition: u_worker.c:37
Definition: u_process.c:43
Main compositor server interface.
Definition: xrt_compositor.h:2233
Compositor semaphore used for synchronization, needs to be as capable as a Vulkan pipeline semaphore.
Definition: xrt_compositor.h:793
Common compositor client interface/base.
Definition: xrt_compositor.h:997
A single HMD or input device.
Definition: xrt_device.h:245
This interface acts as a root object for Monado.
Definition: xrt_instance.h:114
The XRT representation of XrSession, this object does not have all of the functionality of a session,...
Definition: xrt_session.h:246
Object that oversees and manages spaces, one created for each XR system.
Definition: xrt_space.h:96
A space very similar to a OpenXR XrSpace but not a full one-to-one mapping, but used to power XrSpace...
Definition: xrt_space.h:31
Common swapchain interface/base.
Definition: xrt_compositor.h:541
The system compositor handles composition for a system.
Definition: xrt_compositor.h:2423
A collection of xrt_device, and an interface for identifying the roles they have been assigned.
Definition: xrt_system.h:222
Properties provided by the system.
Definition: xrt_system.h:45
A system is a collection of devices, policies and optionally a compositor that is organised into a ch...
Definition: xrt_system.h:63
A tracking system or device origin.
Definition: xrt_tracking.h:71
Basic logging functionality.
Header holding common defines.
int xrt_ipc_handle_t
The type for an IPC handle.
Definition: xrt_handles.h:74
Header for limits of the XRT interfaces.
Header defining xrt space and space overseer.
Header for system objects.