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