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 LOCK_ADDR (message_cache)
00234 #undef LOCK_ADDR
00235 };
00236
00237 _dbus_assert (_DBUS_N_ELEMENTS (global_locks) ==
00238 _DBUS_N_GLOBAL_LOCKS);
00239
00240 i = 0;
00241
00242 dynamic_global_locks = dbus_new (DBusMutex**, _DBUS_N_GLOBAL_LOCKS);
00243 if (dynamic_global_locks == NULL)
00244 goto failed;
00245
00246 while (i < _DBUS_N_ELEMENTS (global_locks))
00247 {
00248 *global_locks[i] = dbus_mutex_new ();
00249
00250 if (*global_locks[i] == NULL)
00251 goto failed;
00252
00253 dynamic_global_locks[i] = global_locks[i];
00254
00255 ++i;
00256 }
00257
00258 if (!_dbus_register_shutdown_func (shutdown_global_locks,
00259 dynamic_global_locks))
00260 goto failed;
00261
00262 return TRUE;
00263
00264 failed:
00265 dbus_free (dynamic_global_locks);
00266
00267 for (i = i - 1; i >= 0; i--)
00268 {
00269 dbus_mutex_free (*global_locks[i]);
00270 *global_locks[i] = NULL;
00271 }
00272 return FALSE;
00273 }
00274
00275
00291 dbus_bool_t
00292 dbus_threads_init (const DBusThreadFunctions *functions)
00293 {
00294 _dbus_assert (functions != NULL);
00295
00296
00297
00298
00299 _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_MUTEX_NEW_MASK);
00300 _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_MUTEX_FREE_MASK);
00301 _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_MUTEX_LOCK_MASK);
00302 _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_MUTEX_UNLOCK_MASK);
00303 _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK);
00304 _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK);
00305 _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK);
00306 _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK);
00307 _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK);
00308 _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK);
00309 _dbus_assert (functions->mutex_new != NULL);
00310 _dbus_assert (functions->mutex_free != NULL);
00311 _dbus_assert (functions->mutex_lock != NULL);
00312 _dbus_assert (functions->mutex_unlock != NULL);
00313 _dbus_assert (functions->condvar_new != NULL);
00314 _dbus_assert (functions->condvar_free != NULL);
00315 _dbus_assert (functions->condvar_wait != NULL);
00316 _dbus_assert (functions->condvar_wait_timeout != NULL);
00317 _dbus_assert (functions->condvar_wake_one != NULL);
00318 _dbus_assert (functions->condvar_wake_all != NULL);
00319
00320
00321
00322
00323
00324 _dbus_assert ((functions->mask & ~DBUS_THREAD_FUNCTIONS_ALL_MASK) == 0);
00325
00326 if (thread_init_generation != _dbus_current_generation)
00327 thread_functions.mask = 0;
00328
00329 if (thread_functions.mask != 0)
00330 {
00331
00332
00333
00334 if (thread_functions.mask == functions->mask &&
00335 thread_functions.mutex_new == functions->mutex_new &&
00336 thread_functions.condvar_new == functions->condvar_new)
00337 {
00338 return TRUE;
00339 }
00340 else
00341 {
00342 _dbus_warn ("dbus_threads_init() called twice with two different sets of functions\n");
00343 return FALSE;
00344 }
00345 }
00346
00347 thread_functions.mutex_new = functions->mutex_new;
00348 thread_functions.mutex_free = functions->mutex_free;
00349 thread_functions.mutex_lock = functions->mutex_lock;
00350 thread_functions.mutex_unlock = functions->mutex_unlock;
00351
00352 thread_functions.condvar_new = functions->condvar_new;
00353 thread_functions.condvar_free = functions->condvar_free;
00354 thread_functions.condvar_wait = functions->condvar_wait;
00355 thread_functions.condvar_wait_timeout = functions->condvar_wait_timeout;
00356 thread_functions.condvar_wake_one = functions->condvar_wake_one;
00357 thread_functions.condvar_wake_all = functions->condvar_wake_all;
00358
00359 thread_functions.mask = functions->mask;
00360
00361 if (!init_global_locks ())
00362 return FALSE;
00363
00364 thread_init_generation = _dbus_current_generation;
00365
00366 return TRUE;
00367 }
00368
00371 #ifdef DBUS_BUILD_TESTS
00372
00373 typedef struct DBusFakeMutex DBusFakeMutex;
00375 struct DBusFakeMutex
00376 {
00377 dbus_bool_t locked;
00378 };
00379
00380 static DBusMutex * dbus_fake_mutex_new (void);
00381 static void dbus_fake_mutex_free (DBusMutex *mutex);
00382 static dbus_bool_t dbus_fake_mutex_lock (DBusMutex *mutex);
00383 static dbus_bool_t dbus_fake_mutex_unlock (DBusMutex *mutex);
00384 static DBusCondVar* dbus_fake_condvar_new (void);
00385 static void dbus_fake_condvar_free (DBusCondVar *cond);
00386 static void dbus_fake_condvar_wait (DBusCondVar *cond,
00387 DBusMutex *mutex);
00388 static dbus_bool_t dbus_fake_condvar_wait_timeout (DBusCondVar *cond,
00389 DBusMutex *mutex,
00390 int timeout_msec);
00391 static void dbus_fake_condvar_wake_one (DBusCondVar *cond);
00392 static void dbus_fake_condvar_wake_all (DBusCondVar *cond);
00393
00394
00395 static const DBusThreadFunctions fake_functions =
00396 {
00397 DBUS_THREAD_FUNCTIONS_MUTEX_NEW_MASK |
00398 DBUS_THREAD_FUNCTIONS_MUTEX_FREE_MASK |
00399 DBUS_THREAD_FUNCTIONS_MUTEX_LOCK_MASK |
00400 DBUS_THREAD_FUNCTIONS_MUTEX_UNLOCK_MASK |
00401 DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK |
00402 DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK |
00403 DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK |
00404 DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK |
00405 DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK|
00406 DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK,
00407 dbus_fake_mutex_new,
00408 dbus_fake_mutex_free,
00409 dbus_fake_mutex_lock,
00410 dbus_fake_mutex_unlock,
00411 dbus_fake_condvar_new,
00412 dbus_fake_condvar_free,
00413 dbus_fake_condvar_wait,
00414 dbus_fake_condvar_wait_timeout,
00415 dbus_fake_condvar_wake_one,
00416 dbus_fake_condvar_wake_all
00417 };
00418
00419 static DBusMutex *
00420 dbus_fake_mutex_new (void)
00421 {
00422 DBusFakeMutex *mutex;
00423
00424 mutex = dbus_new0 (DBusFakeMutex, 1);
00425
00426 return (DBusMutex *)mutex;
00427 }
00428
00429 static void
00430 dbus_fake_mutex_free (DBusMutex *mutex)
00431 {
00432 DBusFakeMutex *fake = (DBusFakeMutex*) mutex;
00433
00434 _dbus_assert (!fake->locked);
00435
00436 dbus_free (fake);
00437 }
00438
00439 static dbus_bool_t
00440 dbus_fake_mutex_lock (DBusMutex *mutex)
00441 {
00442 DBusFakeMutex *fake = (DBusFakeMutex*) mutex;
00443
00444 _dbus_assert (!fake->locked);
00445
00446 fake->locked = TRUE;
00447
00448 return TRUE;
00449 }
00450
00451 static dbus_bool_t
00452 dbus_fake_mutex_unlock (DBusMutex *mutex)
00453 {
00454 DBusFakeMutex *fake = (DBusFakeMutex*) mutex;
00455
00456 _dbus_assert (fake->locked);
00457
00458 fake->locked = FALSE;
00459
00460 return TRUE;
00461 }
00462
00463 static DBusCondVar*
00464 dbus_fake_condvar_new (void)
00465 {
00466 return (DBusCondVar*) _dbus_strdup ("FakeCondvar");
00467 }
00468
00469 static void
00470 dbus_fake_condvar_free (DBusCondVar *cond)
00471 {
00472 dbus_free (cond);
00473 }
00474
00475 static void
00476 dbus_fake_condvar_wait (DBusCondVar *cond,
00477 DBusMutex *mutex)
00478 {
00479
00480 }
00481
00482 static dbus_bool_t
00483 dbus_fake_condvar_wait_timeout (DBusCondVar *cond,
00484 DBusMutex *mutex,
00485 int timeout_msec)
00486 {
00487 return TRUE;
00488 }
00489
00490 static void
00491 dbus_fake_condvar_wake_one (DBusCondVar *cond)
00492 {
00493
00494 }
00495
00496 static void
00497 dbus_fake_condvar_wake_all (DBusCondVar *cond)
00498 {
00499
00500 }
00501
00502 dbus_bool_t
00503 _dbus_threads_init_debug (void)
00504 {
00505 return dbus_threads_init (&fake_functions);
00506 }
00507
00508 #endif