Monado OpenXR Runtime
os_threading.h
Go to the documentation of this file.
1 // Copyright 2019, Collabora, Ltd.
2 // SPDX-License-Identifier: BSL-1.0
3 /*!
4  * @file
5  * @brief Wrapper around OS threading native functions.
6  * @author Jakob Bornecrantz <jakob@collabora.com>
7  *
8  * @ingroup aux_os
9  */
10 
11 #pragma once
12 
13 #include "xrt/xrt_config_os.h"
14 #include "util/u_misc.h"
15 
16 #ifdef XRT_OS_LINUX
17 #include <pthread.h>
18 #else
19 #error "OS not supported"
20 #endif
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 
27 /*!
28  * @ingroup aux_os
29  * @{
30  */
31 
32 /*
33  *
34  * Mutex
35  *
36  */
37 
38 /*!
39  * A wrapper around a native mutex.
40  */
41 struct os_mutex
42 {
43  pthread_mutex_t mutex;
44 };
45 
46 /*!
47  * Init.
48  */
49 static inline int
50 os_mutex_init(struct os_mutex *om)
51 {
52  return pthread_mutex_init(&om->mutex, NULL);
53 }
54 
55 /*!
56  * Lock.
57  */
58 static inline void
59 os_mutex_lock(struct os_mutex *om)
60 {
61  pthread_mutex_lock(&om->mutex);
62 }
63 
64 /*!
65  * Unlock.
66  */
67 static inline void
68 os_mutex_unlock(struct os_mutex *om)
69 {
70  pthread_mutex_unlock(&om->mutex);
71 }
72 
73 /*!
74  * Clean up.
75  */
76 static inline void
77 os_mutex_destroy(struct os_mutex *om)
78 {
79  pthread_mutex_destroy(&om->mutex);
80 }
81 
82 
83 /*
84  *
85  * Thread.
86  *
87  */
88 
89 
90 /*!
91  * A wrapper around a native mutex.
92  */
93 struct os_thread
94 {
95  pthread_t thread;
96 };
97 
98 /*!
99  * Run function.
100  */
101 typedef void *(*os_run_func)(void *);
102 
103 /*!
104  * Init.
105  */
106 static inline int
107 os_thread_init(struct os_thread *ost)
108 {
109  return 0;
110 }
111 
112 /*!
113  * Start thread.
114  */
115 static inline int
116 os_thread_start(struct os_thread *ost, os_run_func func, void *ptr)
117 {
118  return pthread_create(&ost->thread, NULL, func, ptr);
119 }
120 
121 /*!
122  * Join.
123  */
124 static inline void
125 os_thread_join(struct os_thread *ost)
126 {
127  void *retval;
128 
129  pthread_join(ost->thread, &retval);
130  U_ZERO(&ost->thread);
131 }
132 
133 /*!
134  * Destruction.
135  */
136 static inline void
137 os_thread_destroy(struct os_thread *ost)
138 {}
139 
140 
141 /*
142  *
143  * Fancy helper.
144  *
145  */
146 
147 /*!
148  * All in one helper that handles locking, waiting for change and starting a
149  * thread.
150  */
152 {
153  pthread_t thread;
154  pthread_mutex_t mutex;
155  pthread_cond_t cond;
156 
157  bool running;
158 };
159 
160 /*!
161  * Initialize the thread helper.
162  */
163 static inline int
164 os_thread_helper_init(struct os_thread_helper *oth)
165 {
166  int ret = pthread_mutex_init(&oth->mutex, NULL);
167  if (ret != 0) {
168  return ret;
169  }
170 
171  ret = pthread_cond_init(&oth->cond, NULL);
172  if (ret) {
173  pthread_mutex_destroy(&oth->mutex);
174  return ret;
175  }
176 
177  return 0;
178 }
179 
180 /*!
181  * Start the internal thread.
182  */
183 static inline int
184 os_thread_helper_start(struct os_thread_helper *oth,
185  os_run_func func,
186  void *ptr)
187 {
188  pthread_mutex_lock(&oth->mutex);
189 
190  if (oth->running) {
191  pthread_mutex_unlock(&oth->mutex);
192  return -1;
193  }
194 
195  int ret = pthread_create(&oth->thread, NULL, func, ptr);
196  if (ret != 0) {
197  pthread_mutex_unlock(&oth->mutex);
198  return ret;
199  }
200 
201  oth->running = true;
202 
203  pthread_mutex_unlock(&oth->mutex);
204 
205  return 0;
206 }
207 
208 /*!
209  * Stop the thread.
210  */
211 static inline int
212 os_thread_helper_stop(struct os_thread_helper *oth)
213 {
214  void *retval = NULL;
215 
216  // The fields are protected.
217  pthread_mutex_lock(&oth->mutex);
218 
219  if (!oth->running) {
220  pthread_mutex_unlock(&oth->mutex);
221  return 0;
222  }
223 
224  // Stop the thread.
225  oth->running = false;
226 
227  // Wake up the thread if it is waiting.
228  pthread_cond_signal(&oth->cond);
229 
230  // No longer need to protect fields.
231  pthread_mutex_unlock(&oth->mutex);
232 
233  // Wait for thread to finish.
234  pthread_join(oth->thread, &retval);
235 
236  return 0;
237 }
238 
239 /*!
240  * Destroy the thread helper, externally syncronizable.
241  */
242 static inline void
243 os_thread_helper_destroy(struct os_thread_helper *oth)
244 {
245  // Stop the thread.
246  os_thread_helper_stop(oth);
247 
248  // Destroy resources.
249  pthread_mutex_destroy(&oth->mutex);
250  pthread_cond_destroy(&oth->cond);
251 }
252 
253 /*!
254  * Lock the helper.
255  */
256 static inline void
257 os_thread_helper_lock(struct os_thread_helper *oth)
258 {
259  pthread_mutex_lock(&oth->mutex);
260 }
261 
262 /*!
263  * Unlock the helper.
264  */
265 static inline void
266 os_thread_helper_unlock(struct os_thread_helper *oth)
267 {
268  pthread_mutex_unlock(&oth->mutex);
269 }
270 
271 /*!
272  * Is the thread running, or suppised to be running.
273  *
274  * Must be called with the helper locked.
275  */
276 static inline bool
277 os_thread_helper_is_running_locked(struct os_thread_helper *oth)
278 {
279  return oth->running;
280 }
281 
282 /*!
283  * Wait for a signal.
284  *
285  * Must be called with the helper locked.
286  */
287 static inline void
288 os_thread_helper_wait_locked(struct os_thread_helper *oth)
289 {
290  pthread_cond_wait(&oth->cond, &oth->mutex);
291 }
292 
293 /*!
294  * Signal a waiting thread to wake up.
295  *
296  * Must be called with the helper locked.
297  */
298 static inline void
299 os_thread_helper_signal_locked(struct os_thread_helper *oth)
300 {
301  pthread_cond_signal(&oth->cond);
302 }
303 
304 
305 /*!
306  * @}
307  */
308 
309 
310 #ifdef __cplusplus
311 } // extern "C"
312 #endif
Auto detect OS and certain features.
pthread_t thread
Definition: os_threading.h:95
bool running
Definition: os_threading.h:157
pthread_t thread
Definition: os_threading.h:153
pthread_cond_t cond
Definition: os_threading.h:155
All in one helper that handles locking, waiting for change and starting a thread. ...
Definition: os_threading.h:151
pthread_mutex_t mutex
Definition: os_threading.h:154
pthread_mutex_t mutex
Definition: os_threading.h:43
#define U_ZERO(PTR)
Zeroes the correct amount of memory based on the type pointed-to by the argument. ...
Definition: u_misc.h:61
A wrapper around a native mutex.
Definition: os_threading.h:41
A wrapper around a native mutex.
Definition: os_threading.h:93
Very small misc utils.
void *(* os_run_func)(void *)
Run function.
Definition: os_threading.h:101