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 (server_slots),
00227 LOCK_ADDR (message_slots),
00228 LOCK_ADDR (atomic),
00229 LOCK_ADDR (message_handler),
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