00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
#include "dbus-threads.h"
00024
#include "dbus-internals.h"
00025
00026
static DBusThreadFunctions thread_functions =
00027 {
00028 0,
00029
NULL,
NULL,
NULL,
NULL,
00030
NULL,
NULL,
NULL,
NULL,
NULL,
00031
00032
NULL,
NULL,
NULL,
NULL,
00033
NULL,
NULL,
NULL,
NULL
00034 };
00035
static int thread_init_generation = 0;
00036
00038
#define _DBUS_DUMMY_MUTEX ((DBusMutex*)0xABCDEF)
00039
00041
#define _DBUS_DUMMY_CONDVAR ((DBusCondVar*)0xABCDEF2)
00042
00061 DBusMutex*
00062 dbus_mutex_new (
void)
00063 {
00064
if (thread_functions.
mutex_new)
00065
return (* thread_functions.
mutex_new) ();
00066
else
00067
return _DBUS_DUMMY_MUTEX;
00068 }
00069
00074
void
00075 dbus_mutex_free (DBusMutex *mutex)
00076 {
00077
if (mutex && thread_functions.
mutex_free)
00078 (* thread_functions.
mutex_free) (mutex);
00079 }
00080
00087
dbus_bool_t
00088 dbus_mutex_lock (DBusMutex *mutex)
00089 {
00090
if (mutex && thread_functions.
mutex_lock)
00091
return (* thread_functions.
mutex_lock) (mutex);
00092
else
00093
return TRUE;
00094 }
00095
00101
dbus_bool_t
00102 dbus_mutex_unlock (DBusMutex *mutex)
00103 {
00104
if (mutex && thread_functions.
mutex_unlock)
00105
return (* thread_functions.
mutex_unlock) (mutex);
00106
else
00107
return TRUE;
00108 }
00109
00118 DBusCondVar *
00119 dbus_condvar_new (
void)
00120 {
00121
if (thread_functions.
condvar_new)
00122
return (* thread_functions.
condvar_new) ();
00123
else
00124
return _DBUS_DUMMY_CONDVAR;
00125 }
00126
00131
void
00132 dbus_condvar_free (DBusCondVar *cond)
00133 {
00134
if (cond && thread_functions.
condvar_free)
00135 (* thread_functions.
condvar_free) (cond);
00136 }
00137
00144
void
00145 dbus_condvar_wait (DBusCondVar *cond,
00146 DBusMutex *mutex)
00147 {
00148
if (cond && mutex && thread_functions.
condvar_wait)
00149 (* thread_functions.
condvar_wait) (cond, mutex);
00150 }
00151
00164
dbus_bool_t
00165 dbus_condvar_wait_timeout (DBusCondVar *cond,
00166 DBusMutex *mutex,
00167
int timeout_milliseconds)
00168 {
00169
if (cond && mutex && thread_functions.
condvar_wait)
00170
return (* thread_functions.
condvar_wait_timeout) (cond, mutex, timeout_milliseconds);
00171
else
00172
return TRUE;
00173 }
00174
00180
void
00181 dbus_condvar_wake_one (DBusCondVar *cond)
00182 {
00183
if (cond && thread_functions.
condvar_wake_one)
00184 (* thread_functions.
condvar_wake_one) (cond);
00185 }
00186
00192
void
00193 dbus_condvar_wake_all (DBusCondVar *cond)
00194 {
00195
if (cond && thread_functions.
condvar_wake_all)
00196 (* thread_functions.
condvar_wake_all) (cond);
00197 }
00198
00199
static void
00200 shutdown_global_locks (
void *data)
00201 {
00202 DBusMutex ***locks = data;
00203
int i;
00204
00205 i = 0;
00206
while (i < _DBUS_N_GLOBAL_LOCKS)
00207 {
00208
dbus_mutex_free (*(locks[i]));
00209 *(locks[i]) =
NULL;
00210 ++i;
00211 }
00212
00213
dbus_free (locks);
00214 }
00215
00216
static dbus_bool_t
00217 init_global_locks (
void)
00218 {
00219
int i;
00220 DBusMutex ***dynamic_global_locks;
00221
00222 DBusMutex **global_locks[] = {
00223
#define LOCK_ADDR(name) (& _dbus_lock_##name)
00224
LOCK_ADDR (list),
00225 LOCK_ADDR (connection_slots),
00226 LOCK_ADDR (pending_call_slots),
00227 LOCK_ADDR (server_slots),
00228 LOCK_ADDR (message_slots),
00229 LOCK_ADDR (atomic),
00230 LOCK_ADDR (bus),
00231 LOCK_ADDR (shutdown_funcs),
00232 LOCK_ADDR (system_users)
00233 #undef LOCK_ADDR
00234 };
00235
00236
_dbus_assert (_DBUS_N_ELEMENTS (global_locks) ==
00237 _DBUS_N_GLOBAL_LOCKS);
00238
00239 i = 0;
00240
00241 dynamic_global_locks =
dbus_new (DBusMutex**, _DBUS_N_GLOBAL_LOCKS);
00242
if (dynamic_global_locks ==
NULL)
00243
goto failed;
00244
00245
while (i <
_DBUS_N_ELEMENTS (global_locks))
00246 {
00247 *global_locks[i] =
dbus_mutex_new ();
00248
00249
if (*global_locks[i] ==
NULL)
00250
goto failed;
00251
00252 dynamic_global_locks[i] = global_locks[i];
00253
00254 ++i;
00255 }
00256
00257
if (!
_dbus_register_shutdown_func (shutdown_global_locks,
00258 dynamic_global_locks))
00259
goto failed;
00260
00261
return TRUE;
00262
00263 failed:
00264
dbus_free (dynamic_global_locks);
00265
00266
for (i = i - 1; i >= 0; i--)
00267 {
00268
dbus_mutex_free (*global_locks[i]);
00269 *global_locks[i] =
NULL;
00270 }
00271
return FALSE;
00272 }
00273
00274
00290
dbus_bool_t
00291 dbus_threads_init (
const DBusThreadFunctions *functions)
00292 {
00293
_dbus_assert (functions !=
NULL);
00294
00295
00296
00297
00298
_dbus_assert (functions->
mask & DBUS_THREAD_FUNCTIONS_MUTEX_NEW_MASK);
00299
_dbus_assert (functions->
mask & DBUS_THREAD_FUNCTIONS_MUTEX_FREE_MASK);
00300
_dbus_assert (functions->
mask & DBUS_THREAD_FUNCTIONS_MUTEX_LOCK_MASK);
00301
_dbus_assert (functions->
mask & DBUS_THREAD_FUNCTIONS_MUTEX_UNLOCK_MASK);
00302
_dbus_assert (functions->
mask & DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK);
00303
_dbus_assert (functions->
mask & DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK);
00304
_dbus_assert (functions->
mask & DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK);
00305
_dbus_assert (functions->
mask & DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK);
00306
_dbus_assert (functions->
mask & DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK);
00307
_dbus_assert (functions->
mask & DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK);
00308
_dbus_assert (functions->
mutex_new !=
NULL);
00309
_dbus_assert (functions->
mutex_free !=
NULL);
00310
_dbus_assert (functions->
mutex_lock !=
NULL);
00311
_dbus_assert (functions->
mutex_unlock !=
NULL);
00312
_dbus_assert (functions->
condvar_new !=
NULL);
00313
_dbus_assert (functions->
condvar_free !=
NULL);
00314
_dbus_assert (functions->
condvar_wait !=
NULL);
00315
_dbus_assert (functions->
condvar_wait_timeout !=
NULL);
00316
_dbus_assert (functions->
condvar_wake_one !=
NULL);
00317
_dbus_assert (functions->
condvar_wake_all !=
NULL);
00318
00319
00320
00321
00322
00323
_dbus_assert ((functions->
mask & ~DBUS_THREAD_FUNCTIONS_ALL_MASK) == 0);
00324
00325
if (thread_init_generation !=
_dbus_current_generation)
00326 thread_functions.
mask = 0;
00327
00328
if (thread_functions.
mask != 0)
00329 {
00330
00331
00332
00333
if (thread_functions.
mask == functions->
mask &&
00334 thread_functions.
mutex_new == functions->
mutex_new &&
00335 thread_functions.
condvar_new == functions->
condvar_new)
00336 {
00337
return TRUE;
00338 }
00339
else
00340 {
00341
_dbus_warn (
"dbus_threads_init() called twice with two different sets of functions\n");
00342
return FALSE;
00343 }
00344 }
00345
00346 thread_functions.
mutex_new = functions->
mutex_new;
00347 thread_functions.
mutex_free = functions->
mutex_free;
00348 thread_functions.
mutex_lock = functions->
mutex_lock;
00349 thread_functions.
mutex_unlock = functions->
mutex_unlock;
00350
00351 thread_functions.
condvar_new = functions->
condvar_new;
00352 thread_functions.
condvar_free = functions->
condvar_free;
00353 thread_functions.
condvar_wait = functions->
condvar_wait;
00354 thread_functions.
condvar_wait_timeout = functions->
condvar_wait_timeout;
00355 thread_functions.
condvar_wake_one = functions->
condvar_wake_one;
00356 thread_functions.
condvar_wake_all = functions->
condvar_wake_all;
00357
00358 thread_functions.
mask = functions->
mask;
00359
00360
if (!init_global_locks ())
00361
return FALSE;
00362
00363 thread_init_generation =
_dbus_current_generation;
00364
00365
return TRUE;
00366 }
00367
00370
#ifdef DBUS_BUILD_TESTS
00371
00372
typedef struct DBusFakeMutex DBusFakeMutex;
00374
struct DBusFakeMutex
00375 {
00376
dbus_bool_t locked;
00377 };
00378
00379
static DBusMutex * dbus_fake_mutex_new (
void);
00380
static void dbus_fake_mutex_free (DBusMutex *mutex);
00381
static dbus_bool_t dbus_fake_mutex_lock (DBusMutex *mutex);
00382
static dbus_bool_t dbus_fake_mutex_unlock (DBusMutex *mutex);
00383
static DBusCondVar* dbus_fake_condvar_new (
void);
00384
static void dbus_fake_condvar_free (DBusCondVar *cond);
00385
static void dbus_fake_condvar_wait (DBusCondVar *cond,
00386 DBusMutex *mutex);
00387
static dbus_bool_t dbus_fake_condvar_wait_timeout (DBusCondVar *cond,
00388 DBusMutex *mutex,
00389
int timeout_msec);
00390
static void dbus_fake_condvar_wake_one (DBusCondVar *cond);
00391
static void dbus_fake_condvar_wake_all (DBusCondVar *cond);
00392
00393
00394
static const DBusThreadFunctions fake_functions =
00395 {
00396 DBUS_THREAD_FUNCTIONS_MUTEX_NEW_MASK |
00397 DBUS_THREAD_FUNCTIONS_MUTEX_FREE_MASK |
00398 DBUS_THREAD_FUNCTIONS_MUTEX_LOCK_MASK |
00399 DBUS_THREAD_FUNCTIONS_MUTEX_UNLOCK_MASK |
00400 DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK |
00401 DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK |
00402 DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK |
00403 DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK |
00404 DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK|
00405 DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK,
00406 dbus_fake_mutex_new,
00407 dbus_fake_mutex_free,
00408 dbus_fake_mutex_lock,
00409 dbus_fake_mutex_unlock,
00410 dbus_fake_condvar_new,
00411 dbus_fake_condvar_free,
00412 dbus_fake_condvar_wait,
00413 dbus_fake_condvar_wait_timeout,
00414 dbus_fake_condvar_wake_one,
00415 dbus_fake_condvar_wake_all
00416 };
00417
00418
static DBusMutex *
00419 dbus_fake_mutex_new (
void)
00420 {
00421 DBusFakeMutex *mutex;
00422
00423 mutex =
dbus_new0 (DBusFakeMutex, 1);
00424
00425
return (DBusMutex *)mutex;
00426 }
00427
00428
static void
00429 dbus_fake_mutex_free (DBusMutex *mutex)
00430 {
00431 DBusFakeMutex *fake = (DBusFakeMutex*) mutex;
00432
00433
_dbus_assert (!fake->locked);
00434
00435
dbus_free (fake);
00436 }
00437
00438
static dbus_bool_t
00439 dbus_fake_mutex_lock (DBusMutex *mutex)
00440 {
00441 DBusFakeMutex *fake = (DBusFakeMutex*) mutex;
00442
00443
_dbus_assert (!fake->locked);
00444
00445 fake->locked =
TRUE;
00446
00447
return TRUE;
00448 }
00449
00450
static dbus_bool_t
00451 dbus_fake_mutex_unlock (DBusMutex *mutex)
00452 {
00453 DBusFakeMutex *fake = (DBusFakeMutex*) mutex;
00454
00455
_dbus_assert (fake->locked);
00456
00457 fake->locked =
FALSE;
00458
00459
return TRUE;
00460 }
00461
00462
static DBusCondVar*
00463 dbus_fake_condvar_new (
void)
00464 {
00465
return (DBusCondVar*)
_dbus_strdup (
"FakeCondvar");
00466 }
00467
00468
static void
00469 dbus_fake_condvar_free (DBusCondVar *cond)
00470 {
00471
dbus_free (cond);
00472 }
00473
00474
static void
00475 dbus_fake_condvar_wait (DBusCondVar *cond,
00476 DBusMutex *mutex)
00477 {
00478
00479 }
00480
00481
static dbus_bool_t
00482 dbus_fake_condvar_wait_timeout (DBusCondVar *cond,
00483 DBusMutex *mutex,
00484
int timeout_msec)
00485 {
00486
return TRUE;
00487 }
00488
00489
static void
00490 dbus_fake_condvar_wake_one (DBusCondVar *cond)
00491 {
00492
00493 }
00494
00495
static void
00496 dbus_fake_condvar_wake_all (DBusCondVar *cond)
00497 {
00498
00499 }
00500
00501
dbus_bool_t
00502 _dbus_threads_init_debug (
void)
00503 {
00504
return dbus_threads_init (&fake_functions);
00505 }
00506
00507
#endif