dbus-threads.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-threads.h  D-Bus threads handling
00003  *
00004  * Copyright (C) 2002, 2003 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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  /* end of internals */
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   /* these base functions are required. Future additions to
00536    * DBusThreadFunctions may be optional.
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   /* Either the mutex function set or recursive mutex set needs 
00552    * to be available but not both
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   /* Check that all bits in the mask actually are valid mask bits.
00586    * ensures people won't write code that breaks when we add
00587    * new bits.
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; /* allow re-init in new generation */
00593  
00594   /* Silently allow multiple init
00595    * First init wins and D-Bus will always use its threading system 
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 /* Default thread implemenation */
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 /* We need this to free the TLS events on thread exit */
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   /* The event must not be signaled. Check this */
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; /* Prepend failed */
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       /* In the meantime we could have been signaled, so we must again
00779        * wait for the signal, this time with no timeout, to reset
00780        * it. retval is set again to honour the late arrival of the
00781        * signal */
00782       retval = WaitForSingleObject (event, 0);
00783 
00784       LeaveCriticalSection (&cond->lock);
00785     }
00786 
00787 #ifndef DBUS_DISABLE_ASSERT
00788   EnterCriticalSection (&cond->lock);
00789 
00790   /* Now event must not be inside the array, check this */
00791   _dbus_assert (_dbus_list_remove (cond->list, event) == FALSE);
00792 
00793   LeaveCriticalSection (&cond->lock);
00794 #endif /* !G_DISABLE_ASSERT */
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 /* Posix threads */
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   /* We reuse this over several generations, because we can't
00988    * free the events once they are in use
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 /* DBUS_BUILD_TESTS */

Generated on Wed Jan 3 04:58:29 2007 for D-Bus by  doxygen 1.4.7