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 #include "dbus-list.h"
00027
00028 #if defined(__WIN32) || defined(__CYGWIN__)
00029 #define USE_WIN32_THREADS
00030 #endif
00031
00032 #ifdef USE_WIN32_THREADS
00033 #include <windows.h>
00034 #else
00035 #include <sys/time.h>
00036 #include <pthread.h>
00037 #endif
00038
00039 static DBusThreadFunctions thread_functions =
00040 {
00041 0,
00042 NULL, NULL, NULL, NULL, NULL,
00043 NULL, NULL, NULL, NULL, NULL,
00044 NULL, NULL, NULL, NULL,
00045
00046 NULL, NULL, NULL, NULL
00047 };
00048
00049 #ifdef USE_WIN32_THREADS
00050 struct DBusCondVar {
00051 DBusList *list;
00052 CRITICAL_SECTION lock;
00053 };
00054
00055 static DWORD dbus_cond_event_tls = TLS_OUT_OF_INDEXES;
00056 #endif
00057
00058 static int thread_init_generation = 0;
00059
00060 static DBusList *uninitialized_mutex_list = NULL;
00061 static DBusList *uninitialized_condvar_list = NULL;
00062
00064 #define _DBUS_DUMMY_MUTEX ((DBusMutex*)0xABCDEF)
00065
00067 #define _DBUS_DUMMY_CONDVAR ((DBusCondVar*)0xABCDEF2)
00068
00087 DBusMutex*
00088 _dbus_mutex_new (void)
00089 {
00090 if (thread_functions.recursive_mutex_new)
00091 return (* thread_functions.recursive_mutex_new) ();
00092 else if (thread_functions.mutex_new)
00093 return (* thread_functions.mutex_new) ();
00094 else
00095 return _DBUS_DUMMY_MUTEX;
00096 }
00097
00107 void
00108 _dbus_mutex_new_at_location (DBusMutex **location_p)
00109 {
00110 _dbus_assert (location_p != NULL);
00111
00112 *location_p = _dbus_mutex_new();
00113
00114 if (thread_init_generation != _dbus_current_generation && *location_p)
00115 {
00116 if (!_dbus_list_append (&uninitialized_mutex_list, location_p))
00117 {
00118 _dbus_mutex_free (*location_p);
00119 *location_p = NULL;
00120 }
00121 }
00122 }
00123
00128 void
00129 _dbus_mutex_free (DBusMutex *mutex)
00130 {
00131 if (mutex)
00132 {
00133 if (mutex && thread_functions.recursive_mutex_free)
00134 (* thread_functions.recursive_mutex_free) (mutex);
00135 else if (mutex && thread_functions.mutex_free)
00136 (* thread_functions.mutex_free) (mutex);
00137 }
00138 }
00139
00145 void
00146 _dbus_mutex_free_at_location (DBusMutex **location_p)
00147 {
00148 if (location_p)
00149 {
00150 if (thread_init_generation != _dbus_current_generation)
00151 _dbus_list_remove (&uninitialized_mutex_list, location_p);
00152
00153 _dbus_mutex_free (*location_p);
00154 }
00155 }
00156
00162 void
00163 _dbus_mutex_lock (DBusMutex *mutex)
00164 {
00165 if (mutex)
00166 {
00167 if (thread_functions.recursive_mutex_lock)
00168 (* thread_functions.recursive_mutex_lock) (mutex);
00169 else if (thread_functions.mutex_lock)
00170 (* thread_functions.mutex_lock) (mutex);
00171 }
00172 }
00173
00179 void
00180 _dbus_mutex_unlock (DBusMutex *mutex)
00181 {
00182 if (mutex)
00183 {
00184 if (thread_functions.recursive_mutex_unlock)
00185 (* thread_functions.recursive_mutex_unlock) (mutex);
00186 else if (thread_functions.mutex_unlock)
00187 (* thread_functions.mutex_unlock) (mutex);
00188 }
00189 }
00190
00199 DBusCondVar *
00200 _dbus_condvar_new (void)
00201 {
00202 if (thread_functions.condvar_new)
00203 return (* thread_functions.condvar_new) ();
00204 else
00205 return _DBUS_DUMMY_CONDVAR;
00206 }
00207
00208
00219 void
00220 _dbus_condvar_new_at_location (DBusCondVar **location_p)
00221 {
00222 *location_p = _dbus_condvar_new();
00223
00224 if (thread_init_generation != _dbus_current_generation && *location_p)
00225 {
00226 if (!_dbus_list_append (&uninitialized_condvar_list, location_p))
00227 {
00228 _dbus_condvar_free (*location_p);
00229 *location_p = NULL;
00230 }
00231 }
00232 }
00233
00234
00239 void
00240 _dbus_condvar_free (DBusCondVar *cond)
00241 {
00242 if (cond && thread_functions.condvar_free)
00243 (* thread_functions.condvar_free) (cond);
00244 }
00245
00251 void
00252 _dbus_condvar_free_at_location (DBusCondVar **location_p)
00253 {
00254 if (location_p)
00255 {
00256 if (thread_init_generation != _dbus_current_generation)
00257 _dbus_list_remove (&uninitialized_condvar_list, location_p);
00258
00259 _dbus_condvar_free (*location_p);
00260 }
00261 }
00262
00269 void
00270 _dbus_condvar_wait (DBusCondVar *cond,
00271 DBusMutex *mutex)
00272 {
00273 if (cond && mutex && thread_functions.condvar_wait)
00274 (* thread_functions.condvar_wait) (cond, mutex);
00275 }
00276
00289 dbus_bool_t
00290 _dbus_condvar_wait_timeout (DBusCondVar *cond,
00291 DBusMutex *mutex,
00292 int timeout_milliseconds)
00293 {
00294 if (cond && mutex && thread_functions.condvar_wait)
00295 return (* thread_functions.condvar_wait_timeout) (cond, mutex, timeout_milliseconds);
00296 else
00297 return TRUE;
00298 }
00299
00305 void
00306 _dbus_condvar_wake_one (DBusCondVar *cond)
00307 {
00308 if (cond && thread_functions.condvar_wake_one)
00309 (* thread_functions.condvar_wake_one) (cond);
00310 }
00311
00317 void
00318 _dbus_condvar_wake_all (DBusCondVar *cond)
00319 {
00320 if (cond && thread_functions.condvar_wake_all)
00321 (* thread_functions.condvar_wake_all) (cond);
00322 }
00323
00324 static void
00325 shutdown_global_locks (void *data)
00326 {
00327 DBusMutex ***locks = data;
00328 int i;
00329
00330 i = 0;
00331 while (i < _DBUS_N_GLOBAL_LOCKS)
00332 {
00333 _dbus_mutex_free (*(locks[i]));
00334 *(locks[i]) = NULL;
00335 ++i;
00336 }
00337
00338 dbus_free (locks);
00339 }
00340
00341 static void
00342 shutdown_uninitialized_locks (void *data)
00343 {
00344 _dbus_list_clear (&uninitialized_mutex_list);
00345 _dbus_list_clear (&uninitialized_condvar_list);
00346 }
00347
00348 static dbus_bool_t
00349 init_uninitialized_locks (void)
00350 {
00351 DBusList *link;
00352
00353 _dbus_assert (thread_init_generation == 0);
00354
00355 link = uninitialized_mutex_list;
00356 while (link != NULL)
00357 {
00358 DBusMutex **mp;
00359
00360 mp = (DBusMutex **)link->data;
00361 _dbus_assert (*mp == _DBUS_DUMMY_MUTEX);
00362
00363 *mp = _dbus_mutex_new ();
00364 if (*mp == NULL)
00365 goto fail_mutex;
00366
00367 link = _dbus_list_get_next_link (&uninitialized_mutex_list, link);
00368 }
00369
00370 link = uninitialized_condvar_list;
00371 while (link != NULL)
00372 {
00373 DBusCondVar **cp;
00374
00375 cp = (DBusCondVar **)link->data;
00376 _dbus_assert (*cp == _DBUS_DUMMY_CONDVAR);
00377
00378 *cp = _dbus_condvar_new ();
00379 if (*cp == NULL)
00380 goto fail_condvar;
00381
00382 link = _dbus_list_get_next_link (&uninitialized_condvar_list, link);
00383 }
00384
00385 _dbus_list_clear (&uninitialized_mutex_list);
00386 _dbus_list_clear (&uninitialized_condvar_list);
00387
00388 if (!_dbus_register_shutdown_func (shutdown_uninitialized_locks,
00389 NULL))
00390 goto fail_condvar;
00391
00392 return TRUE;
00393
00394 fail_condvar:
00395 link = uninitialized_condvar_list;
00396 while (link != NULL)
00397 {
00398 DBusCondVar **cp;
00399
00400 cp = (DBusCondVar **)link->data;
00401
00402 if (*cp != _DBUS_DUMMY_CONDVAR)
00403 _dbus_condvar_free (*cp);
00404 else
00405 break;
00406
00407 *cp = _DBUS_DUMMY_CONDVAR;
00408
00409 link = _dbus_list_get_next_link (&uninitialized_condvar_list, link);
00410 }
00411
00412 fail_mutex:
00413 link = uninitialized_mutex_list;
00414 while (link != NULL)
00415 {
00416 DBusMutex **mp;
00417
00418 mp = (DBusMutex **)link->data;
00419
00420 if (*mp != _DBUS_DUMMY_MUTEX)
00421 _dbus_mutex_free (*mp);
00422 else
00423 break;
00424
00425 *mp = _DBUS_DUMMY_MUTEX;
00426
00427 link = _dbus_list_get_next_link (&uninitialized_mutex_list, link);
00428 }
00429
00430 return FALSE;
00431 }
00432
00433 static dbus_bool_t
00434 init_locks (void)
00435 {
00436 int i;
00437 DBusMutex ***dynamic_global_locks;
00438
00439 DBusMutex **global_locks[] = {
00440 #define LOCK_ADDR(name) (& _dbus_lock_##name)
00441 LOCK_ADDR (win_fds),
00442 LOCK_ADDR (sid_atom_cache),
00443 LOCK_ADDR (list),
00444 LOCK_ADDR (connection_slots),
00445 LOCK_ADDR (pending_call_slots),
00446 LOCK_ADDR (server_slots),
00447 LOCK_ADDR (message_slots),
00448 LOCK_ADDR (atomic),
00449 LOCK_ADDR (bus),
00450 LOCK_ADDR (shutdown_funcs),
00451 LOCK_ADDR (system_users),
00452 LOCK_ADDR (message_cache),
00453 LOCK_ADDR (shared_connections)
00454 #undef LOCK_ADDR
00455 };
00456
00457 _dbus_assert (_DBUS_N_ELEMENTS (global_locks) ==
00458 _DBUS_N_GLOBAL_LOCKS);
00459
00460 i = 0;
00461
00462 dynamic_global_locks = dbus_new (DBusMutex**, _DBUS_N_GLOBAL_LOCKS);
00463 if (dynamic_global_locks == NULL)
00464 goto failed;
00465
00466 while (i < _DBUS_N_ELEMENTS (global_locks))
00467 {
00468 *global_locks[i] = _dbus_mutex_new ();
00469
00470 if (*global_locks[i] == NULL)
00471 goto failed;
00472
00473 dynamic_global_locks[i] = global_locks[i];
00474
00475 ++i;
00476 }
00477
00478 if (!_dbus_register_shutdown_func (shutdown_global_locks,
00479 dynamic_global_locks))
00480 goto failed;
00481
00482 if (!init_uninitialized_locks ())
00483 goto failed;
00484
00485 return TRUE;
00486
00487 failed:
00488 dbus_free (dynamic_global_locks);
00489
00490 for (i = i - 1; i >= 0; i--)
00491 {
00492 _dbus_mutex_free (*global_locks[i]);
00493 *global_locks[i] = NULL;
00494 }
00495 return FALSE;
00496 }
00497
00499
00527 dbus_bool_t
00528 dbus_threads_init (const DBusThreadFunctions *functions)
00529 {
00530 dbus_bool_t mutex_set;
00531 dbus_bool_t recursive_mutex_set;
00532
00533 _dbus_assert (functions != NULL);
00534
00535
00536
00537
00538 _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK);
00539 _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK);
00540 _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK);
00541 _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK);
00542 _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK);
00543 _dbus_assert (functions->mask & DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK);
00544 _dbus_assert (functions->condvar_new != NULL);
00545 _dbus_assert (functions->condvar_free != NULL);
00546 _dbus_assert (functions->condvar_wait != NULL);
00547 _dbus_assert (functions->condvar_wait_timeout != NULL);
00548 _dbus_assert (functions->condvar_wake_one != NULL);
00549 _dbus_assert (functions->condvar_wake_all != NULL);
00550
00551
00552
00553
00554 mutex_set = (functions->mask & DBUS_THREAD_FUNCTIONS_MUTEX_NEW_MASK) &&
00555 (functions->mask & DBUS_THREAD_FUNCTIONS_MUTEX_FREE_MASK) &&
00556 (functions->mask & DBUS_THREAD_FUNCTIONS_MUTEX_LOCK_MASK) &&
00557 (functions->mask & DBUS_THREAD_FUNCTIONS_MUTEX_UNLOCK_MASK) &&
00558 functions->mutex_new &&
00559 functions->mutex_free &&
00560 functions->mutex_lock &&
00561 functions->mutex_unlock;
00562
00563 recursive_mutex_set =
00564 (functions->mask & DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_NEW_MASK) &&
00565 (functions->mask & DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_FREE_MASK) &&
00566 (functions->mask & DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_LOCK_MASK) &&
00567 (functions->mask & DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_UNLOCK_MASK) &&
00568 functions->recursive_mutex_new &&
00569 functions->recursive_mutex_free &&
00570 functions->recursive_mutex_lock &&
00571 functions->recursive_mutex_unlock;
00572
00573 if (!(mutex_set || recursive_mutex_set))
00574 _dbus_assert_not_reached ("Either the nonrecusrive or recursive mutex "
00575 "functions sets should be passed into "
00576 "dbus_threads_init. Neither sets were passed.");
00577
00578 if (mutex_set && recursive_mutex_set)
00579 _dbus_assert_not_reached ("Either the nonrecusrive or recursive mutex "
00580 "functions sets should be passed into "
00581 "dbus_threads_init. Both sets were passed. "
00582 "You most likely just want to set the recursive "
00583 "mutex functions to avoid deadlocks in D-Bus.");
00584
00585
00586
00587
00588
00589 _dbus_assert ((functions->mask & ~DBUS_THREAD_FUNCTIONS_ALL_MASK) == 0);
00590
00591 if (thread_init_generation != _dbus_current_generation)
00592 thread_functions.mask = 0;
00593
00594
00595
00596
00597 if (thread_functions.mask != 0)
00598 return TRUE;
00599
00600 thread_functions.mutex_new = functions->mutex_new;
00601 thread_functions.mutex_free = functions->mutex_free;
00602 thread_functions.mutex_lock = functions->mutex_lock;
00603 thread_functions.mutex_unlock = functions->mutex_unlock;
00604
00605 thread_functions.condvar_new = functions->condvar_new;
00606 thread_functions.condvar_free = functions->condvar_free;
00607 thread_functions.condvar_wait = functions->condvar_wait;
00608 thread_functions.condvar_wait_timeout = functions->condvar_wait_timeout;
00609 thread_functions.condvar_wake_one = functions->condvar_wake_one;
00610 thread_functions.condvar_wake_all = functions->condvar_wake_all;
00611
00612 if (functions->mask & DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_NEW_MASK)
00613 thread_functions.recursive_mutex_new = functions->recursive_mutex_new;
00614
00615 if (functions->mask & DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_FREE_MASK)
00616 thread_functions.recursive_mutex_free = functions->recursive_mutex_free;
00617
00618 if (functions->mask & DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_LOCK_MASK)
00619 thread_functions.recursive_mutex_lock = functions->recursive_mutex_lock;
00620
00621 if (functions->mask & DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_UNLOCK_MASK)
00622 thread_functions.recursive_mutex_unlock = functions->recursive_mutex_unlock;
00623
00624 thread_functions.mask = functions->mask;
00625
00626 if (!init_locks ())
00627 return FALSE;
00628
00629 thread_init_generation = _dbus_current_generation;
00630
00631 return TRUE;
00632 }
00633
00634
00635
00636
00637
00638 static DBusMutex* _dbus_internal_mutex_new (void);
00639 static void _dbus_internal_mutex_free (DBusMutex *mutex);
00640 static dbus_bool_t _dbus_internal_mutex_lock (DBusMutex *mutex);
00641 static dbus_bool_t _dbus_internal_mutex_unlock (DBusMutex *mutex);
00642 static DBusCondVar *_dbus_internal_condvar_new (void);
00643 static void _dbus_internal_condvar_free (DBusCondVar *cond);
00644 static void _dbus_internal_condvar_wait (DBusCondVar *cond,
00645 DBusMutex *mutex);
00646 static dbus_bool_t _dbus_internal_condvar_wait_timeout (DBusCondVar *cond,
00647 DBusMutex *mutex,
00648 int timeout_milliseconds);
00649 static void _dbus_internal_condvar_wake_one (DBusCondVar *cond);
00650 static void _dbus_internal_condvar_wake_all (DBusCondVar *cond);
00651
00652 #ifdef USE_WIN32_THREADS
00653
00654 BOOL WINAPI DllMain (HINSTANCE hinstDLL,
00655 DWORD fdwReason,
00656 LPVOID lpvReserved);
00657
00658
00659 BOOL WINAPI
00660 DllMain (HINSTANCE hinstDLL,
00661 DWORD fdwReason,
00662 LPVOID lpvReserved)
00663 {
00664 HANDLE event;
00665 switch (fdwReason)
00666 {
00667 case DLL_THREAD_DETACH:
00668 if (dbus_cond_event_tls != TLS_OUT_OF_INDEXES)
00669 {
00670 event = TlsGetValue(dbus_cond_event_tls);
00671 CloseHandle (event);
00672 TlsSetValue(dbus_cond_event_tls, NULL);
00673 }
00674 break;
00675 case DLL_PROCESS_DETACH:
00676 if (dbus_cond_event_tls != TLS_OUT_OF_INDEXES)
00677 {
00678 event = TlsGetValue(dbus_cond_event_tls);
00679 CloseHandle (event);
00680 TlsSetValue(dbus_cond_event_tls, NULL);
00681
00682 TlsFree(dbus_cond_event_tls);
00683 }
00684 break;
00685 default:
00686 break;
00687 }
00688 return TRUE;
00689 }
00690
00691 static DBusMutex*
00692 _dbus_internal_mutex_new (void)
00693 {
00694 HANDLE handle;
00695 handle = CreateMutex (NULL, FALSE, NULL);
00696 return (DBusMutex *) handle;
00697 }
00698
00699 static void
00700 _dbus_internal_mutex_free (DBusMutex *mutex)
00701 {
00702 CloseHandle ((HANDLE *) mutex);
00703 }
00704
00705 static dbus_bool_t
00706 _dbus_internal_mutex_lock (DBusMutex *mutex)
00707 {
00708 return WaitForSingleObject ((HANDLE *) mutex, INFINITE) != WAIT_FAILED;
00709 }
00710
00711 static dbus_bool_t
00712 _dbus_internal_mutex_unlock (DBusMutex *mutex)
00713 {
00714 return ReleaseMutex ((HANDLE *) mutex) != 0;
00715 }
00716
00717 static DBusCondVar *
00718 _dbus_internal_condvar_new (void)
00719 {
00720 DBusCondVar *cond;
00721
00722 cond = dbus_new (DBusCondVar, 1);
00723 if (cond == NULL)
00724 return NULL;
00725
00726 cond->list = NULL;
00727
00728 InitializeCriticalSection (&cond->lock);
00729 return (DBusCondVar *) cond;
00730 }
00731
00732 static void
00733 _dbus_internal_condvar_free (DBusCondVar *cond)
00734 {
00735 DeleteCriticalSection (&cond->lock);
00736 _dbus_list_clear (&cond->list);
00737 dbus_free (cond);
00738 }
00739
00740 static dbus_bool_t
00741 _dbus_condvar_wait_win32 (DBusCondVar *cond,
00742 DBusMutex *mutex,
00743 int milliseconds)
00744 {
00745 DWORD retval;
00746 dbus_bool_t ret;
00747 HANDLE event = TlsGetValue (dbus_cond_event_tls);
00748
00749 if (!event)
00750 {
00751 event = CreateEvent (0, FALSE, FALSE, NULL);
00752 if (event == 0)
00753 return FALSE;
00754 TlsSetValue (dbus_cond_event_tls, event);
00755 }
00756
00757 EnterCriticalSection (&cond->lock);
00758
00759
00760 _dbus_assert (WaitForSingleObject (event, 0) == WAIT_TIMEOUT);
00761
00762 ret = _dbus_list_append (&cond->list, event);
00763
00764 LeaveCriticalSection (&cond->lock);
00765
00766 if (!ret)
00767 return FALSE;
00768
00769 _dbus_mutex_unlock (mutex);
00770 retval = WaitForSingleObject (event, milliseconds);
00771 _dbus_mutex_lock (mutex);
00772
00773 if (retval == WAIT_TIMEOUT)
00774 {
00775 EnterCriticalSection (&cond->lock);
00776 _dbus_list_remove (&cond->list, event);
00777
00778
00779
00780
00781
00782 retval = WaitForSingleObject (event, 0);
00783
00784 LeaveCriticalSection (&cond->lock);
00785 }
00786
00787 #ifndef DBUS_DISABLE_ASSERT
00788 EnterCriticalSection (&cond->lock);
00789
00790
00791 _dbus_assert (_dbus_list_remove (cond->list, event) == FALSE);
00792
00793 LeaveCriticalSection (&cond->lock);
00794 #endif
00795
00796 return retval != WAIT_TIMEOUT;
00797 }
00798
00799 static void
00800 _dbus_internal_condvar_wait (DBusCondVar *cond,
00801 DBusMutex *mutex)
00802 {
00803 _dbus_condvar_wait_win32 (cond, mutex, INFINITE);
00804 }
00805
00806 static dbus_bool_t
00807 _dbus_internal_condvar_wait_timeout (DBusCondVar *cond,
00808 DBusMutex *mutex,
00809 int timeout_milliseconds)
00810 {
00811 return _dbus_condvar_wait_win32 (cond, mutex, timeout_milliseconds);
00812 }
00813
00814 static void
00815 _dbus_internal_condvar_wake_one (DBusCondVar *cond)
00816 {
00817 EnterCriticalSection (&cond->lock);
00818
00819 if (cond->list != NULL)
00820 SetEvent (_dbus_list_pop_first (&cond->list));
00821
00822 LeaveCriticalSection (&cond->lock);
00823 }
00824
00825 static void
00826 _dbus_internal_condvar_wake_all (DBusCondVar *cond)
00827 {
00828 EnterCriticalSection (&cond->lock);
00829
00830 while (cond->list != NULL)
00831 SetEvent (_dbus_list_pop_first (&cond->list));
00832
00833 LeaveCriticalSection (&cond->lock);
00834 }
00835
00836
00837 #else
00838
00839 static DBusMutex*
00840 _dbus_internal_mutex_new (void)
00841 {
00842 pthread_mutex_t *retval;
00843
00844 retval = dbus_new (pthread_mutex_t, 1);
00845 if (retval == NULL)
00846 return NULL;
00847
00848 if (pthread_mutex_init (retval, NULL))
00849 {
00850 dbus_free (retval);
00851 return NULL;
00852 }
00853 return (DBusMutex *) retval;
00854 }
00855
00856 static void
00857 _dbus_internal_mutex_free (DBusMutex *mutex)
00858 {
00859 pthread_mutex_destroy ((pthread_mutex_t *) mutex);
00860 dbus_free (mutex);
00861 }
00862
00863 static dbus_bool_t
00864 _dbus_internal_mutex_lock (DBusMutex *mutex)
00865 {
00866 return pthread_mutex_lock ((pthread_mutex_t *) mutex) == 0;
00867 }
00868
00869 static dbus_bool_t
00870 _dbus_internal_mutex_unlock (DBusMutex *mutex)
00871 {
00872 return pthread_mutex_unlock ((pthread_mutex_t *) mutex) == 0;
00873 }
00874
00875 static DBusCondVar *
00876 _dbus_internal_condvar_new (void)
00877 {
00878 pthread_cond_t *retval;
00879
00880 retval = dbus_new (pthread_cond_t, 1);
00881 if (retval == NULL)
00882 return NULL;
00883
00884 if (pthread_cond_init (retval, NULL))
00885 {
00886 dbus_free (retval);
00887 return NULL;
00888 }
00889 return (DBusCondVar *) retval;
00890 }
00891
00892 static void
00893 _dbus_internal_condvar_free (DBusCondVar *cond)
00894 {
00895 pthread_cond_destroy ((pthread_cond_t *) cond);
00896 dbus_free (cond);
00897 }
00898
00899 static void
00900 _dbus_internal_condvar_wait (DBusCondVar *cond,
00901 DBusMutex *mutex)
00902 {
00903 pthread_cond_wait ((pthread_cond_t *)cond,
00904 (pthread_mutex_t *) mutex);
00905 }
00906
00907 static dbus_bool_t
00908 _dbus_internal_condvar_wait_timeout (DBusCondVar *cond,
00909 DBusMutex *mutex,
00910 int timeout_milliseconds)
00911 {
00912 struct timeval time_now;
00913 struct timespec end_time;
00914 int result;
00915
00916 gettimeofday (&time_now, NULL);
00917
00918 end_time.tv_sec = time_now.tv_sec + timeout_milliseconds / 1000;
00919 end_time.tv_nsec = (time_now.tv_usec + (timeout_milliseconds % 1000) * 1000) * 1000;
00920 if (end_time.tv_nsec > 1000*1000*1000)
00921 {
00922 end_time.tv_sec += 1;
00923 end_time.tv_nsec -= 1000*1000*1000;
00924 }
00925
00926 result = pthread_cond_timedwait ((pthread_cond_t *) cond,
00927 (pthread_mutex_t *) mutex,
00928 &end_time);
00929 return result == ETIMEDOUT;
00930 }
00931
00932 static void
00933 _dbus_internal_condvar_wake_one (DBusCondVar *cond)
00934 {
00935 pthread_cond_signal ((pthread_cond_t *)cond);
00936 }
00937
00938 static void
00939 _dbus_internal_condvar_wake_all (DBusCondVar *cond)
00940 {
00941 pthread_cond_broadcast ((pthread_cond_t *)cond);
00942 }
00943
00944 #endif
00945
00946 static const DBusThreadFunctions internal_functions =
00947 {
00948 DBUS_THREAD_FUNCTIONS_MUTEX_NEW_MASK |
00949 DBUS_THREAD_FUNCTIONS_MUTEX_FREE_MASK |
00950 DBUS_THREAD_FUNCTIONS_MUTEX_LOCK_MASK |
00951 DBUS_THREAD_FUNCTIONS_MUTEX_UNLOCK_MASK |
00952 DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK |
00953 DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK |
00954 DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK |
00955 DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK |
00956 DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK|
00957 DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK,
00958 _dbus_internal_mutex_new,
00959 _dbus_internal_mutex_free,
00960 _dbus_internal_mutex_lock,
00961 _dbus_internal_mutex_unlock,
00962 _dbus_internal_condvar_new,
00963 _dbus_internal_condvar_free,
00964 _dbus_internal_condvar_wait,
00965 _dbus_internal_condvar_wait_timeout,
00966 _dbus_internal_condvar_wake_one,
00967 _dbus_internal_condvar_wake_all
00968 };
00969
00983 dbus_bool_t
00984 dbus_threads_init_default (void)
00985 {
00986 #ifdef USE_WIN32_THREADS
00987
00988
00989
00990 if (dbus_cond_event_tls == TLS_OUT_OF_INDEXES)
00991 {
00992 dbus_cond_event_tls = TlsAlloc ();
00993 if (dbus_cond_event_tls == TLS_OUT_OF_INDEXES)
00994 return FALSE;
00995 }
00996 #endif
00997
00998 return dbus_threads_init (&internal_functions);
00999 }
01000
01001
01004 #ifdef DBUS_BUILD_TESTS
01005
01006 typedef struct DBusFakeMutex DBusFakeMutex;
01008 struct DBusFakeMutex
01009 {
01010 dbus_bool_t locked;
01011 };
01012
01013 static DBusMutex * dbus_fake_mutex_new (void);
01014 static void dbus_fake_mutex_free (DBusMutex *mutex);
01015 static dbus_bool_t dbus_fake_mutex_lock (DBusMutex *mutex);
01016 static dbus_bool_t dbus_fake_mutex_unlock (DBusMutex *mutex);
01017 static DBusCondVar* dbus_fake_condvar_new (void);
01018 static void dbus_fake_condvar_free (DBusCondVar *cond);
01019 static void dbus_fake_condvar_wait (DBusCondVar *cond,
01020 DBusMutex *mutex);
01021 static dbus_bool_t dbus_fake_condvar_wait_timeout (DBusCondVar *cond,
01022 DBusMutex *mutex,
01023 int timeout_msec);
01024 static void dbus_fake_condvar_wake_one (DBusCondVar *cond);
01025 static void dbus_fake_condvar_wake_all (DBusCondVar *cond);
01026
01027
01028 static const DBusThreadFunctions fake_functions =
01029 {
01030 DBUS_THREAD_FUNCTIONS_MUTEX_NEW_MASK |
01031 DBUS_THREAD_FUNCTIONS_MUTEX_FREE_MASK |
01032 DBUS_THREAD_FUNCTIONS_MUTEX_LOCK_MASK |
01033 DBUS_THREAD_FUNCTIONS_MUTEX_UNLOCK_MASK |
01034 DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK |
01035 DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK |
01036 DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK |
01037 DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK |
01038 DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK|
01039 DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK,
01040 dbus_fake_mutex_new,
01041 dbus_fake_mutex_free,
01042 dbus_fake_mutex_lock,
01043 dbus_fake_mutex_unlock,
01044 dbus_fake_condvar_new,
01045 dbus_fake_condvar_free,
01046 dbus_fake_condvar_wait,
01047 dbus_fake_condvar_wait_timeout,
01048 dbus_fake_condvar_wake_one,
01049 dbus_fake_condvar_wake_all
01050 };
01051
01052 static DBusMutex *
01053 dbus_fake_mutex_new (void)
01054 {
01055 DBusFakeMutex *mutex;
01056
01057 mutex = dbus_new0 (DBusFakeMutex, 1);
01058
01059 return (DBusMutex *)mutex;
01060 }
01061
01062 static void
01063 dbus_fake_mutex_free (DBusMutex *mutex)
01064 {
01065 DBusFakeMutex *fake = (DBusFakeMutex*) mutex;
01066
01067 _dbus_assert (!fake->locked);
01068
01069 dbus_free (fake);
01070 }
01071
01072 static dbus_bool_t
01073 dbus_fake_mutex_lock (DBusMutex *mutex)
01074 {
01075 DBusFakeMutex *fake = (DBusFakeMutex*) mutex;
01076
01077 _dbus_assert (!fake->locked);
01078
01079 fake->locked = TRUE;
01080
01081 return TRUE;
01082 }
01083
01084 static dbus_bool_t
01085 dbus_fake_mutex_unlock (DBusMutex *mutex)
01086 {
01087 DBusFakeMutex *fake = (DBusFakeMutex*) mutex;
01088
01089 _dbus_assert (fake->locked);
01090
01091 fake->locked = FALSE;
01092
01093 return TRUE;
01094 }
01095
01096 static DBusCondVar*
01097 dbus_fake_condvar_new (void)
01098 {
01099 return (DBusCondVar*) _dbus_strdup ("FakeCondvar");
01100 }
01101
01102 static void
01103 dbus_fake_condvar_free (DBusCondVar *cond)
01104 {
01105 dbus_free (cond);
01106 }
01107
01108 static void
01109 dbus_fake_condvar_wait (DBusCondVar *cond,
01110 DBusMutex *mutex)
01111 {
01112
01113 }
01114
01115 static dbus_bool_t
01116 dbus_fake_condvar_wait_timeout (DBusCondVar *cond,
01117 DBusMutex *mutex,
01118 int timeout_msec)
01119 {
01120 return TRUE;
01121 }
01122
01123 static void
01124 dbus_fake_condvar_wake_one (DBusCondVar *cond)
01125 {
01126
01127 }
01128
01129 static void
01130 dbus_fake_condvar_wake_all (DBusCondVar *cond)
01131 {
01132
01133 }
01134
01135 dbus_bool_t
01136 _dbus_threads_init_debug (void)
01137 {
01138 return dbus_threads_init (&fake_functions);
01139 }
01140
01141 #endif