D-Bus: dbus-threads.c Source File

D-Bus 1.14.10

dbus-threads.c
1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2/* dbus-threads.h D-Bus threads handling
3 *
4 * Copyright (C) 2002, 2003, 2006 Red Hat Inc.
5 *
6 * Licensed under the Academic Free License version 2.1
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 */
23#include <config.h>
24#include "dbus-threads.h"
25#include "dbus-internals.h"
26#include "dbus-threads-internal.h"
27#include "dbus-list.h"
28
29/* Protected by _dbus_threads_lock_platform_specific() */
30static int thread_init_generation = 0;
31
53void
54_dbus_rmutex_new_at_location (DBusRMutex **location_p)
55{
56 _dbus_assert (location_p != NULL);
57
58 if (!dbus_threads_init_default ())
59 {
60 *location_p = NULL;
61 return;
62 }
63
64 *location_p = _dbus_platform_rmutex_new ();
65}
66
77void
78_dbus_cmutex_new_at_location (DBusCMutex **location_p)
79{
80 _dbus_assert (location_p != NULL);
81
82 if (!dbus_threads_init_default ())
83 {
84 *location_p = NULL;
85 return;
86 }
87
88 *location_p = _dbus_platform_cmutex_new ();
89}
90
94void
95_dbus_rmutex_free_at_location (DBusRMutex **location_p)
96{
97 if (location_p == NULL)
98 return;
99
100 if (*location_p != NULL)
101 _dbus_platform_rmutex_free (*location_p);
102}
103
107void
108_dbus_cmutex_free_at_location (DBusCMutex **location_p)
109{
110 if (location_p == NULL)
111 return;
112
113 if (*location_p != NULL)
114 _dbus_platform_cmutex_free (*location_p);
115}
116
122void
123_dbus_rmutex_lock (DBusRMutex *mutex)
124{
125 if (mutex == NULL)
126 return;
127
128 _dbus_platform_rmutex_lock (mutex);
129}
130
136void
137_dbus_cmutex_lock (DBusCMutex *mutex)
138{
139 if (mutex == NULL)
140 return;
141
142 _dbus_platform_cmutex_lock (mutex);
143}
144
150void
151_dbus_rmutex_unlock (DBusRMutex *mutex)
152{
153 if (mutex == NULL)
154 return;
155
156 _dbus_platform_rmutex_unlock (mutex);
157}
158
164void
165_dbus_cmutex_unlock (DBusCMutex *mutex)
166{
167 if (mutex == NULL)
168 return;
169
170 _dbus_platform_cmutex_unlock (mutex);
171}
172
181 DBusCondVar *
182_dbus_condvar_new (void)
183{
184 if (!dbus_threads_init_default ())
185 return NULL;
186
187 return _dbus_platform_condvar_new ();
188}
189
190
199void
200_dbus_condvar_new_at_location (DBusCondVar **location_p)
201{
202 _dbus_assert (location_p != NULL);
203
204 *location_p = _dbus_condvar_new();
205}
206
207
212void
213_dbus_condvar_free (DBusCondVar *cond)
214{
215 if (cond == NULL)
216 return;
217
218 _dbus_platform_condvar_free (cond);
219}
220
224void
225_dbus_condvar_free_at_location (DBusCondVar **location_p)
226{
227 if (location_p == NULL)
228 return;
229
230 if (*location_p != NULL)
231 _dbus_platform_condvar_free (*location_p);
232}
233
240void
241_dbus_condvar_wait (DBusCondVar *cond,
242 DBusCMutex *mutex)
243{
244 if (cond == NULL || mutex == NULL)
245 return;
246
247 _dbus_platform_condvar_wait (cond, mutex);
248}
249
261dbus_bool_t
262_dbus_condvar_wait_timeout (DBusCondVar *cond,
263 DBusCMutex *mutex,
264 int timeout_milliseconds)
265{
266 if (cond == NULL || mutex == NULL)
267 return TRUE;
268
269 return _dbus_platform_condvar_wait_timeout (cond, mutex,
270 timeout_milliseconds);
271}
272
278void
279_dbus_condvar_wake_one (DBusCondVar *cond)
280{
281 if (cond == NULL)
282 return;
283
284 _dbus_platform_condvar_wake_one (cond);
285}
286
287/* Protected by _dbus_threads_lock_platform_specific() */
288static DBusRMutex *global_locks[_DBUS_N_GLOBAL_LOCKS] = { NULL };
289
290static void
291shutdown_global_locks (void *nil)
292{
293 int i;
294
295 for (i = 0; i < _DBUS_N_GLOBAL_LOCKS; i++)
296 {
297 _dbus_assert (global_locks[i] != NULL);
298 _dbus_platform_rmutex_free (global_locks[i]);
299 global_locks[i] = NULL;
300 }
301}
302
303static dbus_bool_t
304init_global_locks (void)
305{
306 int i;
307 dbus_bool_t ok;
308
309 for (i = 0; i < _DBUS_N_GLOBAL_LOCKS; i++)
310 {
311 _dbus_assert (global_locks[i] == NULL);
312
313 global_locks[i] = _dbus_platform_rmutex_new ();
314
315 if (global_locks[i] == NULL)
316 goto failed;
317 }
318
319 _dbus_platform_rmutex_lock (global_locks[_DBUS_LOCK_shutdown_funcs]);
320 ok = _dbus_register_shutdown_func_unlocked (shutdown_global_locks, NULL);
321 _dbus_platform_rmutex_unlock (global_locks[_DBUS_LOCK_shutdown_funcs]);
322
323 if (!ok)
324 goto failed;
325
326 return TRUE;
327
328 failed:
329 for (i = i - 1; i >= 0; i--)
330 {
331 _dbus_platform_rmutex_free (global_locks[i]);
332 global_locks[i] = NULL;
333 }
334
335 return FALSE;
336}
337
338dbus_bool_t
339_dbus_lock (DBusGlobalLock lock)
340{
341 _dbus_assert (lock >= 0);
342 _dbus_assert (lock < _DBUS_N_GLOBAL_LOCKS);
343
344 if (thread_init_generation != _dbus_current_generation &&
345 !dbus_threads_init_default ())
346 return FALSE;
347
348 _dbus_platform_rmutex_lock (global_locks[lock]);
349 return TRUE;
350}
351
352void
353_dbus_unlock (DBusGlobalLock lock)
354{
355 _dbus_assert (lock >= 0);
356 _dbus_assert (lock < _DBUS_N_GLOBAL_LOCKS);
357
358 _dbus_platform_rmutex_unlock (global_locks[lock]);
359}
360
/* end of internals */
362
392dbus_bool_t
393dbus_threads_init (const DBusThreadFunctions *functions)
394{
395 _dbus_threads_lock_platform_specific ();
396
397 if (thread_init_generation == _dbus_current_generation)
398 {
399 _dbus_threads_unlock_platform_specific ();
400 return TRUE;
401 }
402
403 if (!_dbus_threads_init_platform_specific() ||
404 !init_global_locks ())
405 {
406 _dbus_threads_unlock_platform_specific ();
407 return FALSE;
408 }
409
410 thread_init_generation = _dbus_current_generation;
411
412 _dbus_threads_unlock_platform_specific ();
413 return TRUE;
414}
415
416
417
418/* Default thread implemenation */
419
439dbus_bool_t
440dbus_threads_init_default (void)
441{
442 return dbus_threads_init (NULL);
443}
444
445
448#ifdef DBUS_ENABLE_EMBEDDED_TESTS
449
450#endif /* DBUS_ENABLE_EMBEDDED_TESTS */
_dbus_assert
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
Definition dbus-internals.h:153
NULL
#define NULL
A null pointer, defined appropriately for C or C++.
Definition dbus-macros.h:49
TRUE
#define TRUE
Expands to "1".
Definition dbus-macros.h:39
FALSE
#define FALSE
Expands to "0".
Definition dbus-macros.h:42
_dbus_current_generation
int _dbus_current_generation
_dbus_current_generation is used to track each time that dbus_shutdown() is called,...
Definition dbus-memory.c:772
_dbus_threads_lock_platform_specific
void _dbus_threads_lock_platform_specific(void)
Lock a static mutex used to protect _dbus_threads_init_platform_specific().
Definition dbus-sysdeps-pthread.c:294
_dbus_threads_unlock_platform_specific
void _dbus_threads_unlock_platform_specific(void)
Undo _dbus_threads_lock_platform_specific().
Definition dbus-sysdeps-pthread.c:300
_dbus_threads_init_platform_specific
dbus_bool_t _dbus_threads_init_platform_specific(void)
Initialize threads as in dbus_threads_init_default(), appropriately for the platform.
Definition dbus-sysdeps-pthread.c:279
_dbus_rmutex_new_at_location
void _dbus_rmutex_new_at_location(DBusRMutex **location_p)
Creates a new mutex or creates a no-op mutex if threads are not initialized.
Definition dbus-threads.c:54
_dbus_cmutex_free_at_location
void _dbus_cmutex_free_at_location(DBusCMutex **location_p)
Frees a DBusCMutex; does nothing if passed a NULL pointer.
Definition dbus-threads.c:108
_dbus_condvar_new
DBusCondVar * _dbus_condvar_new(void)
Creates a new condition variable using the function supplied to dbus_threads_init(),...
Definition dbus-threads.c:182
_dbus_condvar_free_at_location
void _dbus_condvar_free_at_location(DBusCondVar **location_p)
Frees a condition variable; does nothing if passed a NULL pointer.
Definition dbus-threads.c:225
_dbus_rmutex_unlock
void _dbus_rmutex_unlock(DBusRMutex *mutex)
Unlocks a mutex.
Definition dbus-threads.c:151
_dbus_condvar_wait
void _dbus_condvar_wait(DBusCondVar *cond, DBusCMutex *mutex)
Atomically unlocks the mutex and waits for the conditions variable to be signalled.
Definition dbus-threads.c:241
_dbus_condvar_new_at_location
void _dbus_condvar_new_at_location(DBusCondVar **location_p)
This does the same thing as _dbus_condvar_new.
Definition dbus-threads.c:200
_dbus_cmutex_new_at_location
void _dbus_cmutex_new_at_location(DBusCMutex **location_p)
Creates a new mutex or creates a no-op mutex if threads are not initialized.
Definition dbus-threads.c:78
_dbus_condvar_wake_one
void _dbus_condvar_wake_one(DBusCondVar *cond)
If there are threads waiting on the condition variable, wake up exactly one.
Definition dbus-threads.c:279
_dbus_condvar_wait_timeout
dbus_bool_t _dbus_condvar_wait_timeout(DBusCondVar *cond, DBusCMutex *mutex, int timeout_milliseconds)
Atomically unlocks the mutex and waits for the conditions variable to be signalled,...
Definition dbus-threads.c:262
_dbus_cmutex_lock
void _dbus_cmutex_lock(DBusCMutex *mutex)
Locks a mutex.
Definition dbus-threads.c:137
_dbus_cmutex_unlock
void _dbus_cmutex_unlock(DBusCMutex *mutex)
Unlocks a mutex.
Definition dbus-threads.c:165
_dbus_rmutex_free_at_location
void _dbus_rmutex_free_at_location(DBusRMutex **location_p)
Frees a DBusRMutex; does nothing if passed a NULL pointer.
Definition dbus-threads.c:95
_dbus_rmutex_lock
void _dbus_rmutex_lock(DBusRMutex *mutex)
Locks a mutex.
Definition dbus-threads.c:123
_dbus_condvar_free
void _dbus_condvar_free(DBusCondVar *cond)
Frees a conditional variable created with dbus_condvar_new(); does nothing if passed a NULL pointer.
Definition dbus-threads.c:213
dbus_threads_init_default
dbus_bool_t dbus_threads_init_default(void)
Initializes threads.
Definition dbus-threads.c:440
dbus_threads_init
dbus_bool_t dbus_threads_init(const DBusThreadFunctions *functions)
Initializes threads, like dbus_threads_init_default().
Definition dbus-threads.c:393
DBusCMutex
Definition dbus-sysdeps-pthread.c:53
DBusCondVar
Definition dbus-sysdeps-pthread.c:57
DBusRMutex
Definition dbus-sysdeps-pthread.c:49
DBusThreadFunctions
Functions that must be implemented to make the D-Bus library thread-aware.
Definition dbus-threads.h:153