D-Bus  1.13.16
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() */
30 static int thread_init_generation = 0;
31 
53 void
55 {
56  _dbus_assert (location_p != NULL);
57 
59  {
60  *location_p = NULL;
61  return;
62  }
63 
64  *location_p = _dbus_platform_rmutex_new ();
65 }
66 
77 void
79 {
80  _dbus_assert (location_p != NULL);
81 
83  {
84  *location_p = NULL;
85  return;
86  }
87 
88  *location_p = _dbus_platform_cmutex_new ();
89 }
90 
94 void
96 {
97  if (location_p == NULL)
98  return;
99 
100  if (*location_p != NULL)
101  _dbus_platform_rmutex_free (*location_p);
102 }
103 
107 void
109 {
110  if (location_p == NULL)
111  return;
112 
113  if (*location_p != NULL)
114  _dbus_platform_cmutex_free (*location_p);
115 }
116 
122 void
124 {
125  if (mutex == NULL)
126  return;
127 
128  _dbus_platform_rmutex_lock (mutex);
129 }
130 
136 void
138 {
139  if (mutex == NULL)
140  return;
141 
142  _dbus_platform_cmutex_lock (mutex);
143 }
144 
150 void
152 {
153  if (mutex == NULL)
154  return;
155 
156  _dbus_platform_rmutex_unlock (mutex);
157 }
158 
164 void
166 {
167  if (mutex == NULL)
168  return;
169 
170  _dbus_platform_cmutex_unlock (mutex);
171 }
172 
181 DBusCondVar *
183 {
185  return NULL;
186 
187  return _dbus_platform_condvar_new ();
188 }
189 
190 
199 void
201 {
202  _dbus_assert (location_p != NULL);
203 
204  *location_p = _dbus_condvar_new();
205 }
206 
207 
212 void
214 {
215  if (cond == NULL)
216  return;
217 
218  _dbus_platform_condvar_free (cond);
219 }
220 
224 void
226 {
227  if (location_p == NULL)
228  return;
229 
230  if (*location_p != NULL)
231  _dbus_platform_condvar_free (*location_p);
232 }
233 
240 void
242  DBusCMutex *mutex)
243 {
244  if (cond == NULL || mutex == NULL)
245  return;
246 
247  _dbus_platform_condvar_wait (cond, mutex);
248 }
249 
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 
278 void
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() */
288 static DBusRMutex *global_locks[_DBUS_N_GLOBAL_LOCKS] = { NULL };
289 
290 static void
291 shutdown_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 
303 static dbus_bool_t
304 init_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 
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 &&
346  return FALSE;
347 
348  _dbus_platform_rmutex_lock (global_locks[lock]);
349  return TRUE;
350 }
351 
352 void
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 
394 {
396 
397  if (thread_init_generation == _dbus_current_generation)
398  {
400  return TRUE;
401  }
402 
404  !init_global_locks ())
405  {
407  return FALSE;
408  }
409 
410  thread_init_generation = _dbus_current_generation;
411 
413  return TRUE;
414 }
415 
416 
417 
418 /* Default thread implemenation */
419 
441 {
442  return dbus_threads_init (NULL);
443 }
444 
445 
448 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
449 
450 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */
DBusRMutex
Definition: dbus-sysdeps-pthread.c:49
_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
DBusThreadFunctions
Functions that must be implemented to make the D-Bus library thread-aware.
Definition: dbus-threads.h:152
_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
DBusCMutex
Definition: dbus-sysdeps-pthread.c:53
_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:784
_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
DBusCondVar
Definition: dbus-sysdeps-pthread.c:57
_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
DBusCMutex::lock
pthread_mutex_t lock
the lock
Definition: dbus-sysdeps-pthread.c:54
_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_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
TRUE
#define TRUE
_dbus_cmutex_unlock
void _dbus_cmutex_unlock(DBusCMutex *mutex)
Unlocks a mutex.
Definition: dbus-threads.c:165
_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_rmutex_unlock
void _dbus_rmutex_unlock(DBusRMutex *mutex)
Unlocks a mutex.
Definition: dbus-threads.c:151
FALSE
#define FALSE
_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_cmutex_lock
void _dbus_cmutex_lock(DBusCMutex *mutex)
Locks a mutex.
Definition: dbus-threads.c:137
dbus_threads_init_default
dbus_bool_t dbus_threads_init_default(void)
Initializes threads.
Definition: dbus-threads.c:440
_dbus_rmutex_lock
void _dbus_rmutex_lock(DBusRMutex *mutex)
Locks a mutex.
Definition: dbus-threads.c:123
_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_assert
#define _dbus_assert(condition)
Definition: dbus-internals.h:153
_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_threads_init
dbus_bool_t dbus_threads_init(const DBusThreadFunctions *functions)
Initializes threads, like dbus_threads_init_default().
Definition: dbus-threads.c:393
_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_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_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_bool_t
dbus_uint32_t dbus_bool_t
Definition: dbus-types.h:35
NULL
#define NULL