D-Bus 1.6.12
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-threads.h D-Bus threads handling 00003 * 00004 * Copyright (C) 2002, 2003, 2006 Red Hat Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 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 /* end of internals */ 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 /* Default thread implemenation */ 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 /* DBUS_BUILD_TESTS */