00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <config.h>
00024 #include "dbus-threads.h"
00025 #include "dbus-internals.h"
00026 #include "dbus-threads-internal.h"
00027 #include "dbus-list.h"
00028
00029 static int thread_init_generation = 0;
00030
00031 static DBusList *uninitialized_rmutex_list = NULL;
00032 static DBusList *uninitialized_cmutex_list = NULL;
00033 static DBusList *uninitialized_condvar_list = NULL;
00034
00036 #define _DBUS_DUMMY_MUTEX ((DBusMutex*)0xABCDEF)
00037 #define _DBUS_DUMMY_RMUTEX ((DBusRMutex *) _DBUS_DUMMY_MUTEX)
00038 #define _DBUS_DUMMY_CMUTEX ((DBusCMutex *) _DBUS_DUMMY_MUTEX)
00039
00041 #define _DBUS_DUMMY_CONDVAR ((DBusCondVar*)0xABCDEF2)
00042
00069 void
00070 _dbus_rmutex_new_at_location (DBusRMutex **location_p)
00071 {
00072 _dbus_assert (location_p != NULL);
00073
00074 if (thread_init_generation == _dbus_current_generation)
00075 {
00076 *location_p = _dbus_platform_rmutex_new ();
00077 }
00078 else
00079 {
00080 *location_p = _DBUS_DUMMY_RMUTEX;
00081
00082 if (!_dbus_list_append (&uninitialized_rmutex_list, location_p))
00083 *location_p = NULL;
00084 }
00085 }
00086
00102 void
00103 _dbus_cmutex_new_at_location (DBusCMutex **location_p)
00104 {
00105 _dbus_assert (location_p != NULL);
00106
00107 if (thread_init_generation == _dbus_current_generation)
00108 {
00109 *location_p = _dbus_platform_cmutex_new ();
00110 }
00111 else
00112 {
00113 *location_p = _DBUS_DUMMY_CMUTEX;
00114
00115 if (!_dbus_list_append (&uninitialized_cmutex_list, location_p))
00116 *location_p = NULL;
00117 }
00118 }
00119
00124 void
00125 _dbus_rmutex_free_at_location (DBusRMutex **location_p)
00126 {
00127 if (location_p == NULL)
00128 return;
00129
00130 if (thread_init_generation == _dbus_current_generation)
00131 {
00132 if (*location_p != NULL)
00133 _dbus_platform_rmutex_free (*location_p);
00134 }
00135 else
00136 {
00137 _dbus_assert (*location_p == NULL || *location_p == _DBUS_DUMMY_RMUTEX);
00138
00139 _dbus_list_remove (&uninitialized_rmutex_list, location_p);
00140 }
00141 }
00142
00148 void
00149 _dbus_cmutex_free_at_location (DBusCMutex **location_p)
00150 {
00151 if (location_p == NULL)
00152 return;
00153
00154 if (thread_init_generation == _dbus_current_generation)
00155 {
00156 if (*location_p != NULL)
00157 _dbus_platform_cmutex_free (*location_p);
00158 }
00159 else
00160 {
00161 _dbus_assert (*location_p == NULL || *location_p == _DBUS_DUMMY_CMUTEX);
00162
00163 _dbus_list_remove (&uninitialized_cmutex_list, location_p);
00164 }
00165 }
00166
00172 void
00173 _dbus_rmutex_lock (DBusRMutex *mutex)
00174 {
00175 if (mutex && thread_init_generation == _dbus_current_generation)
00176 _dbus_platform_rmutex_lock (mutex);
00177 }
00178
00184 void
00185 _dbus_cmutex_lock (DBusCMutex *mutex)
00186 {
00187 if (mutex && thread_init_generation == _dbus_current_generation)
00188 _dbus_platform_cmutex_lock (mutex);
00189 }
00190
00196 void
00197 _dbus_rmutex_unlock (DBusRMutex *mutex)
00198 {
00199 if (mutex && thread_init_generation == _dbus_current_generation)
00200 _dbus_platform_rmutex_unlock (mutex);
00201 }
00202
00208 void
00209 _dbus_cmutex_unlock (DBusCMutex *mutex)
00210 {
00211 if (mutex && thread_init_generation == _dbus_current_generation)
00212 _dbus_platform_cmutex_unlock (mutex);
00213 }
00214
00223 DBusCondVar *
00224 _dbus_condvar_new (void)
00225 {
00226 if (thread_init_generation == _dbus_current_generation)
00227 return _dbus_platform_condvar_new ();
00228 else
00229 return _DBUS_DUMMY_CONDVAR;
00230 }
00231
00232
00243 void
00244 _dbus_condvar_new_at_location (DBusCondVar **location_p)
00245 {
00246 _dbus_assert (location_p != NULL);
00247
00248 if (thread_init_generation == _dbus_current_generation)
00249 {
00250 *location_p = _dbus_condvar_new();
00251 }
00252 else
00253 {
00254 *location_p = _DBUS_DUMMY_CONDVAR;
00255
00256 if (!_dbus_list_append (&uninitialized_condvar_list, location_p))
00257 *location_p = NULL;
00258 }
00259 }
00260
00261
00266 void
00267 _dbus_condvar_free (DBusCondVar *cond)
00268 {
00269 if (cond && thread_init_generation == _dbus_current_generation)
00270 _dbus_platform_condvar_free (cond);
00271 }
00272
00278 void
00279 _dbus_condvar_free_at_location (DBusCondVar **location_p)
00280 {
00281 if (location_p == NULL)
00282 return;
00283
00284 if (thread_init_generation == _dbus_current_generation)
00285 {
00286 if (*location_p != NULL)
00287 _dbus_platform_condvar_free (*location_p);
00288 }
00289 else
00290 {
00291 _dbus_assert (*location_p == NULL || *location_p == _DBUS_DUMMY_CONDVAR);
00292
00293 _dbus_list_remove (&uninitialized_condvar_list, location_p);
00294 }
00295 }
00296
00303 void
00304 _dbus_condvar_wait (DBusCondVar *cond,
00305 DBusCMutex *mutex)
00306 {
00307 if (cond && mutex && thread_init_generation == _dbus_current_generation)
00308 _dbus_platform_condvar_wait (cond, mutex);
00309 }
00310
00322 dbus_bool_t
00323 _dbus_condvar_wait_timeout (DBusCondVar *cond,
00324 DBusCMutex *mutex,
00325 int timeout_milliseconds)
00326 {
00327 if (cond && mutex && thread_init_generation == _dbus_current_generation)
00328 return _dbus_platform_condvar_wait_timeout (cond, mutex,
00329 timeout_milliseconds);
00330 else
00331 return TRUE;
00332 }
00333
00339 void
00340 _dbus_condvar_wake_one (DBusCondVar *cond)
00341 {
00342 if (cond && thread_init_generation == _dbus_current_generation)
00343 _dbus_platform_condvar_wake_one (cond);
00344 }
00345
00346 static void
00347 shutdown_global_locks (void *data)
00348 {
00349 DBusRMutex ***locks = data;
00350 int i;
00351
00352 i = 0;
00353 while (i < _DBUS_N_GLOBAL_LOCKS)
00354 {
00355 if (*(locks[i]) != NULL)
00356 _dbus_platform_rmutex_free (*(locks[i]));
00357
00358 *(locks[i]) = NULL;
00359 ++i;
00360 }
00361
00362 dbus_free (locks);
00363 }
00364
00365 static void
00366 shutdown_uninitialized_locks (void *data)
00367 {
00368 _dbus_list_clear (&uninitialized_rmutex_list);
00369 _dbus_list_clear (&uninitialized_cmutex_list);
00370 _dbus_list_clear (&uninitialized_condvar_list);
00371 }
00372
00373 static dbus_bool_t
00374 init_uninitialized_locks (void)
00375 {
00376 DBusList *link;
00377
00378 _dbus_assert (thread_init_generation != _dbus_current_generation);
00379
00380 link = uninitialized_rmutex_list;
00381 while (link != NULL)
00382 {
00383 DBusRMutex **mp;
00384
00385 mp = link->data;
00386 _dbus_assert (*mp == _DBUS_DUMMY_RMUTEX);
00387
00388 *mp = _dbus_platform_rmutex_new ();
00389 if (*mp == NULL)
00390 goto fail_mutex;
00391
00392 link = _dbus_list_get_next_link (&uninitialized_rmutex_list, link);
00393 }
00394
00395 link = uninitialized_cmutex_list;
00396 while (link != NULL)
00397 {
00398 DBusCMutex **mp;
00399
00400 mp = link->data;
00401 _dbus_assert (*mp == _DBUS_DUMMY_CMUTEX);
00402
00403 *mp = _dbus_platform_cmutex_new ();
00404 if (*mp == NULL)
00405 goto fail_mutex;
00406
00407 link = _dbus_list_get_next_link (&uninitialized_cmutex_list, link);
00408 }
00409
00410 link = uninitialized_condvar_list;
00411 while (link != NULL)
00412 {
00413 DBusCondVar **cp;
00414
00415 cp = (DBusCondVar **)link->data;
00416 _dbus_assert (*cp == _DBUS_DUMMY_CONDVAR);
00417
00418 *cp = _dbus_platform_condvar_new ();
00419 if (*cp == NULL)
00420 goto fail_condvar;
00421
00422 link = _dbus_list_get_next_link (&uninitialized_condvar_list, link);
00423 }
00424
00425 _dbus_list_clear (&uninitialized_rmutex_list);
00426 _dbus_list_clear (&uninitialized_cmutex_list);
00427 _dbus_list_clear (&uninitialized_condvar_list);
00428
00429 if (!_dbus_register_shutdown_func (shutdown_uninitialized_locks,
00430 NULL))
00431 goto fail_condvar;
00432
00433 return TRUE;
00434
00435 fail_condvar:
00436 link = uninitialized_condvar_list;
00437 while (link != NULL)
00438 {
00439 DBusCondVar **cp;
00440
00441 cp = link->data;
00442
00443 if (*cp != _DBUS_DUMMY_CONDVAR && *cp != NULL)
00444 _dbus_platform_condvar_free (*cp);
00445
00446 *cp = _DBUS_DUMMY_CONDVAR;
00447
00448 link = _dbus_list_get_next_link (&uninitialized_condvar_list, link);
00449 }
00450
00451 fail_mutex:
00452 link = uninitialized_rmutex_list;
00453 while (link != NULL)
00454 {
00455 DBusRMutex **mp;
00456
00457 mp = link->data;
00458
00459 if (*mp != _DBUS_DUMMY_RMUTEX && *mp != NULL)
00460 _dbus_platform_rmutex_free (*mp);
00461
00462 *mp = _DBUS_DUMMY_RMUTEX;
00463
00464 link = _dbus_list_get_next_link (&uninitialized_rmutex_list, link);
00465 }
00466
00467 link = uninitialized_cmutex_list;
00468 while (link != NULL)
00469 {
00470 DBusCMutex **mp;
00471
00472 mp = link->data;
00473
00474 if (*mp != _DBUS_DUMMY_CMUTEX && *mp != NULL)
00475 _dbus_platform_cmutex_free (*mp);
00476
00477 *mp = _DBUS_DUMMY_CMUTEX;
00478
00479 link = _dbus_list_get_next_link (&uninitialized_cmutex_list, link);
00480 }
00481
00482 return FALSE;
00483 }
00484
00485 static dbus_bool_t
00486 init_locks (void)
00487 {
00488 int i;
00489 DBusRMutex ***dynamic_global_locks;
00490 DBusRMutex **global_locks[] = {
00491 #define LOCK_ADDR(name) (& _dbus_lock_##name)
00492 LOCK_ADDR (win_fds),
00493 LOCK_ADDR (sid_atom_cache),
00494 LOCK_ADDR (list),
00495 LOCK_ADDR (connection_slots),
00496 LOCK_ADDR (pending_call_slots),
00497 LOCK_ADDR (server_slots),
00498 LOCK_ADDR (message_slots),
00499 #if !DBUS_USE_SYNC
00500 LOCK_ADDR (atomic),
00501 #endif
00502 LOCK_ADDR (bus),
00503 LOCK_ADDR (bus_datas),
00504 LOCK_ADDR (shutdown_funcs),
00505 LOCK_ADDR (system_users),
00506 LOCK_ADDR (message_cache),
00507 LOCK_ADDR (shared_connections),
00508 LOCK_ADDR (machine_uuid)
00509 #undef LOCK_ADDR
00510 };
00511
00512 _dbus_assert (_DBUS_N_ELEMENTS (global_locks) ==
00513 _DBUS_N_GLOBAL_LOCKS);
00514
00515 i = 0;
00516
00517 dynamic_global_locks = dbus_new (DBusRMutex**, _DBUS_N_GLOBAL_LOCKS);
00518 if (dynamic_global_locks == NULL)
00519 goto failed;
00520
00521 while (i < _DBUS_N_ELEMENTS (global_locks))
00522 {
00523 *global_locks[i] = _dbus_platform_rmutex_new ();
00524
00525 if (*global_locks[i] == NULL)
00526 goto failed;
00527
00528 dynamic_global_locks[i] = global_locks[i];
00529
00530 ++i;
00531 }
00532
00533 if (!_dbus_register_shutdown_func (shutdown_global_locks,
00534 dynamic_global_locks))
00535 goto failed;
00536
00537 if (!init_uninitialized_locks ())
00538 goto failed;
00539
00540 return TRUE;
00541
00542 failed:
00543 dbus_free (dynamic_global_locks);
00544
00545 for (i = i - 1; i >= 0; i--)
00546 {
00547 _dbus_platform_rmutex_free (*global_locks[i]);
00548 *global_locks[i] = NULL;
00549 }
00550 return FALSE;
00551 }
00552
00554
00584 dbus_bool_t
00585 dbus_threads_init (const DBusThreadFunctions *functions)
00586 {
00587 if (thread_init_generation == _dbus_current_generation)
00588 return TRUE;
00589
00590 if (!init_locks ())
00591 return FALSE;
00592
00593 thread_init_generation = _dbus_current_generation;
00594
00595 return TRUE;
00596 }
00597
00598
00599
00600
00601
00616 dbus_bool_t
00617 dbus_threads_init_default (void)
00618 {
00619 return _dbus_threads_init_platform_specific ();
00620 }
00621
00622
00625 #ifdef DBUS_BUILD_TESTS
00626
00627 dbus_bool_t
00628 _dbus_threads_init_debug (void)
00629 {
00630 return _dbus_threads_init_platform_specific();
00631 }
00632
00633 #endif