00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <config.h>
00025 #include "dbus-internals.h"
00026 #include "dbus-sysdeps.h"
00027 #include "dbus-sysdeps-win.h"
00028 #include "dbus-threads.h"
00029 #include "dbus-list.h"
00030
00031 #include <windows.h>
00032
00033 struct DBusCondVar {
00034 DBusList *list;
00035 CRITICAL_SECTION lock;
00036 };
00037
00038 static DWORD dbus_cond_event_tls = TLS_OUT_OF_INDEXES;
00039
00040
00041 static HMODULE dbus_dll_hmodule;
00042
00043 void *
00044 _dbus_win_get_dll_hmodule (void)
00045 {
00046 return dbus_dll_hmodule;
00047 }
00048
00049 #ifdef DBUS_WINCE
00050 #define hinst_t HANDLE
00051 #else
00052 #define hinst_t HINSTANCE
00053 #endif
00054
00055 BOOL WINAPI DllMain (hinst_t, DWORD, LPVOID);
00056
00057
00058 BOOL WINAPI
00059 DllMain (hinst_t hinstDLL,
00060 DWORD fdwReason,
00061 LPVOID lpvReserved)
00062 {
00063 HANDLE event;
00064 switch (fdwReason)
00065 {
00066 case DLL_PROCESS_ATTACH:
00067 dbus_dll_hmodule = hinstDLL;
00068 break;
00069 case DLL_THREAD_DETACH:
00070 if (dbus_cond_event_tls != TLS_OUT_OF_INDEXES)
00071 {
00072 event = TlsGetValue(dbus_cond_event_tls);
00073 CloseHandle (event);
00074 TlsSetValue(dbus_cond_event_tls, NULL);
00075 }
00076 break;
00077 case DLL_PROCESS_DETACH:
00078 if (dbus_cond_event_tls != TLS_OUT_OF_INDEXES)
00079 {
00080 event = TlsGetValue(dbus_cond_event_tls);
00081 CloseHandle (event);
00082 TlsSetValue(dbus_cond_event_tls, NULL);
00083
00084 TlsFree(dbus_cond_event_tls);
00085 }
00086 break;
00087 default:
00088 break;
00089 }
00090 return TRUE;
00091 }
00092
00093 static DBusMutex*
00094 _dbus_windows_mutex_new (void)
00095 {
00096 HANDLE handle;
00097 handle = CreateMutex (NULL, FALSE, NULL);
00098 return (DBusMutex *) handle;
00099 }
00100
00101 static void
00102 _dbus_windows_mutex_free (DBusMutex *mutex)
00103 {
00104 CloseHandle ((HANDLE *) mutex);
00105 }
00106
00107 static dbus_bool_t
00108 _dbus_windows_mutex_lock (DBusMutex *mutex)
00109 {
00110 return WaitForSingleObject ((HANDLE *) mutex, INFINITE) != WAIT_FAILED;
00111 }
00112
00113 static dbus_bool_t
00114 _dbus_windows_mutex_unlock (DBusMutex *mutex)
00115 {
00116 return ReleaseMutex ((HANDLE *) mutex) != 0;
00117 }
00118
00119 static DBusCondVar *
00120 _dbus_windows_condvar_new (void)
00121 {
00122 DBusCondVar *cond;
00123
00124 cond = dbus_new (DBusCondVar, 1);
00125 if (cond == NULL)
00126 return NULL;
00127
00128 cond->list = NULL;
00129
00130 InitializeCriticalSection (&cond->lock);
00131 return (DBusCondVar *) cond;
00132 }
00133
00134 static void
00135 _dbus_windows_condvar_free (DBusCondVar *cond)
00136 {
00137 DeleteCriticalSection (&cond->lock);
00138 _dbus_list_clear (&cond->list);
00139 dbus_free (cond);
00140 }
00141
00142 static dbus_bool_t
00143 _dbus_condvar_wait_win32 (DBusCondVar *cond,
00144 DBusMutex *mutex,
00145 int milliseconds)
00146 {
00147 DWORD retval;
00148 dbus_bool_t ret;
00149 HANDLE event = TlsGetValue (dbus_cond_event_tls);
00150
00151 if (!event)
00152 {
00153 event = CreateEvent (0, FALSE, FALSE, NULL);
00154 if (event == 0)
00155 return FALSE;
00156 TlsSetValue (dbus_cond_event_tls, event);
00157 }
00158
00159 EnterCriticalSection (&cond->lock);
00160
00161
00162 _dbus_assert (WaitForSingleObject (event, 0) == WAIT_TIMEOUT);
00163
00164 ret = _dbus_list_append (&cond->list, event);
00165
00166 LeaveCriticalSection (&cond->lock);
00167
00168 if (!ret)
00169 return FALSE;
00170
00171 _dbus_mutex_unlock (mutex);
00172 retval = WaitForSingleObject (event, milliseconds);
00173 _dbus_mutex_lock (mutex);
00174
00175 if (retval == WAIT_TIMEOUT)
00176 {
00177 EnterCriticalSection (&cond->lock);
00178 _dbus_list_remove (&cond->list, event);
00179
00180
00181
00182
00183
00184 retval = WaitForSingleObject (event, 0);
00185
00186 LeaveCriticalSection (&cond->lock);
00187 }
00188
00189 #ifndef DBUS_DISABLE_ASSERT
00190 EnterCriticalSection (&cond->lock);
00191
00192
00193 _dbus_assert (_dbus_list_remove (&cond->list, event) == FALSE);
00194
00195 LeaveCriticalSection (&cond->lock);
00196 #endif
00197
00198 return retval != WAIT_TIMEOUT;
00199 }
00200
00201 static void
00202 _dbus_windows_condvar_wait (DBusCondVar *cond,
00203 DBusMutex *mutex)
00204 {
00205 _dbus_condvar_wait_win32 (cond, mutex, INFINITE);
00206 }
00207
00208 static dbus_bool_t
00209 _dbus_windows_condvar_wait_timeout (DBusCondVar *cond,
00210 DBusMutex *mutex,
00211 int timeout_milliseconds)
00212 {
00213 return _dbus_condvar_wait_win32 (cond, mutex, timeout_milliseconds);
00214 }
00215
00216 static void
00217 _dbus_windows_condvar_wake_one (DBusCondVar *cond)
00218 {
00219 EnterCriticalSection (&cond->lock);
00220
00221 if (cond->list != NULL)
00222 {
00223 SetEvent (_dbus_list_pop_first (&cond->list));
00224
00225
00226
00227
00228 Sleep (0);
00229 }
00230 LeaveCriticalSection (&cond->lock);
00231 }
00232
00233 static void
00234 _dbus_windows_condvar_wake_all (DBusCondVar *cond)
00235 {
00236 EnterCriticalSection (&cond->lock);
00237
00238 while (cond->list != NULL)
00239 SetEvent (_dbus_list_pop_first (&cond->list));
00240
00241 if (cond->list != NULL)
00242 {
00243
00244
00245
00246
00247 Sleep (0);
00248 }
00249
00250 LeaveCriticalSection (&cond->lock);
00251 }
00252
00253 static const DBusThreadFunctions windows_functions =
00254 {
00255 DBUS_THREAD_FUNCTIONS_MUTEX_NEW_MASK |
00256 DBUS_THREAD_FUNCTIONS_MUTEX_FREE_MASK |
00257 DBUS_THREAD_FUNCTIONS_MUTEX_LOCK_MASK |
00258 DBUS_THREAD_FUNCTIONS_MUTEX_UNLOCK_MASK |
00259 DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK |
00260 DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK |
00261 DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK |
00262 DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK |
00263 DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK|
00264 DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK,
00265 _dbus_windows_mutex_new,
00266 _dbus_windows_mutex_free,
00267 _dbus_windows_mutex_lock,
00268 _dbus_windows_mutex_unlock,
00269 _dbus_windows_condvar_new,
00270 _dbus_windows_condvar_free,
00271 _dbus_windows_condvar_wait,
00272 _dbus_windows_condvar_wait_timeout,
00273 _dbus_windows_condvar_wake_one,
00274 _dbus_windows_condvar_wake_all
00275 };
00276
00277 dbus_bool_t
00278 _dbus_threads_init_platform_specific (void)
00279 {
00280
00281
00282
00283 if (dbus_cond_event_tls == TLS_OUT_OF_INDEXES)
00284 {
00285 dbus_cond_event_tls = TlsAlloc ();
00286 if (dbus_cond_event_tls == TLS_OUT_OF_INDEXES)
00287 return FALSE;
00288 }
00289
00290 return dbus_threads_init (&windows_functions);
00291 }
00292