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 static dbus_bool_t global_init_done = FALSE;
00034 static CRITICAL_SECTION init_lock;
00035
00036
00037 void
00038 _dbus_threads_windows_init_global (void)
00039 {
00040
00041
00042 _dbus_threads_windows_ensure_ctor_linked ();
00043
00044 InitializeCriticalSection (&init_lock);
00045 global_init_done = TRUE;
00046 }
00047
00048 struct DBusCondVar {
00049 DBusList *list;
00050 CRITICAL_SECTION lock;
00051 };
00052
00053 static DWORD dbus_cond_event_tls = TLS_OUT_OF_INDEXES;
00054
00055
00056 static HMODULE dbus_dll_hmodule;
00057
00058 void *
00059 _dbus_win_get_dll_hmodule (void)
00060 {
00061 return dbus_dll_hmodule;
00062 }
00063
00064 #ifdef DBUS_WINCE
00065 #define hinst_t HANDLE
00066 #else
00067 #define hinst_t HINSTANCE
00068 #endif
00069
00070 BOOL WINAPI DllMain (hinst_t, DWORD, LPVOID);
00071
00072
00073 BOOL WINAPI
00074 DllMain (hinst_t hinstDLL,
00075 DWORD fdwReason,
00076 LPVOID lpvReserved)
00077 {
00078 HANDLE event;
00079 switch (fdwReason)
00080 {
00081 case DLL_PROCESS_ATTACH:
00082 dbus_dll_hmodule = hinstDLL;
00083 break;
00084 case DLL_THREAD_DETACH:
00085 if (dbus_cond_event_tls != TLS_OUT_OF_INDEXES)
00086 {
00087 event = TlsGetValue(dbus_cond_event_tls);
00088 CloseHandle (event);
00089 TlsSetValue(dbus_cond_event_tls, NULL);
00090 }
00091 break;
00092 case DLL_PROCESS_DETACH:
00093 if (dbus_cond_event_tls != TLS_OUT_OF_INDEXES)
00094 {
00095 event = TlsGetValue(dbus_cond_event_tls);
00096 CloseHandle (event);
00097 TlsSetValue(dbus_cond_event_tls, NULL);
00098
00099 TlsFree(dbus_cond_event_tls);
00100 }
00101 break;
00102 default:
00103 break;
00104 }
00105 return TRUE;
00106 }
00107
00108 DBusCMutex *
00109 _dbus_platform_cmutex_new (void)
00110 {
00111 HANDLE handle;
00112 handle = CreateMutex (NULL, FALSE, NULL);
00113 return (DBusCMutex *) handle;
00114 }
00115
00116 DBusRMutex *
00117 _dbus_platform_rmutex_new (void)
00118 {
00119 HANDLE handle;
00120 handle = CreateMutex (NULL, FALSE, NULL);
00121 return (DBusRMutex *) handle;
00122 }
00123
00124 void
00125 _dbus_platform_cmutex_free (DBusCMutex *mutex)
00126 {
00127 CloseHandle ((HANDLE *) mutex);
00128 }
00129
00130 void
00131 _dbus_platform_rmutex_free (DBusRMutex *mutex)
00132 {
00133 CloseHandle ((HANDLE *) mutex);
00134 }
00135
00136 void
00137 _dbus_platform_cmutex_lock (DBusCMutex *mutex)
00138 {
00139 WaitForSingleObject ((HANDLE *) mutex, INFINITE);
00140 }
00141
00142 void
00143 _dbus_platform_rmutex_lock (DBusRMutex *mutex)
00144 {
00145 WaitForSingleObject ((HANDLE *) mutex, INFINITE);
00146 }
00147
00148 void
00149 _dbus_platform_cmutex_unlock (DBusCMutex *mutex)
00150 {
00151 ReleaseMutex ((HANDLE *) mutex);
00152 }
00153
00154 void
00155 _dbus_platform_rmutex_unlock (DBusRMutex *mutex)
00156 {
00157 ReleaseMutex ((HANDLE *) mutex);
00158 }
00159
00160 DBusCondVar *
00161 _dbus_platform_condvar_new (void)
00162 {
00163 DBusCondVar *cond;
00164
00165 cond = dbus_new (DBusCondVar, 1);
00166 if (cond == NULL)
00167 return NULL;
00168
00169 cond->list = NULL;
00170
00171 InitializeCriticalSection (&cond->lock);
00172 return cond;
00173 }
00174
00175 void
00176 _dbus_platform_condvar_free (DBusCondVar *cond)
00177 {
00178 DeleteCriticalSection (&cond->lock);
00179 _dbus_list_clear (&cond->list);
00180 dbus_free (cond);
00181 }
00182
00183 static dbus_bool_t
00184 _dbus_condvar_wait_win32 (DBusCondVar *cond,
00185 DBusCMutex *mutex,
00186 int milliseconds)
00187 {
00188 DWORD retval;
00189 dbus_bool_t ret;
00190 HANDLE event = TlsGetValue (dbus_cond_event_tls);
00191
00192 if (!event)
00193 {
00194 event = CreateEvent (0, FALSE, FALSE, NULL);
00195 if (event == 0)
00196 return FALSE;
00197 TlsSetValue (dbus_cond_event_tls, event);
00198 }
00199
00200 EnterCriticalSection (&cond->lock);
00201
00202
00203 _dbus_assert (WaitForSingleObject (event, 0) == WAIT_TIMEOUT);
00204
00205 ret = _dbus_list_append (&cond->list, event);
00206
00207 LeaveCriticalSection (&cond->lock);
00208
00209 if (!ret)
00210 return FALSE;
00211
00212 _dbus_platform_cmutex_unlock (mutex);
00213 retval = WaitForSingleObject (event, milliseconds);
00214 _dbus_platform_cmutex_lock (mutex);
00215
00216 if (retval == WAIT_TIMEOUT)
00217 {
00218 EnterCriticalSection (&cond->lock);
00219 _dbus_list_remove (&cond->list, event);
00220
00221
00222
00223
00224
00225 retval = WaitForSingleObject (event, 0);
00226
00227 LeaveCriticalSection (&cond->lock);
00228 }
00229
00230 #ifndef DBUS_DISABLE_ASSERT
00231 EnterCriticalSection (&cond->lock);
00232
00233
00234 _dbus_assert (_dbus_list_remove (&cond->list, event) == FALSE);
00235
00236 LeaveCriticalSection (&cond->lock);
00237 #endif
00238
00239 return retval != WAIT_TIMEOUT;
00240 }
00241
00242 void
00243 _dbus_platform_condvar_wait (DBusCondVar *cond,
00244 DBusCMutex *mutex)
00245 {
00246 _dbus_condvar_wait_win32 (cond, mutex, INFINITE);
00247 }
00248
00249 dbus_bool_t
00250 _dbus_platform_condvar_wait_timeout (DBusCondVar *cond,
00251 DBusCMutex *mutex,
00252 int timeout_milliseconds)
00253 {
00254 return _dbus_condvar_wait_win32 (cond, mutex, timeout_milliseconds);
00255 }
00256
00257 void
00258 _dbus_platform_condvar_wake_one (DBusCondVar *cond)
00259 {
00260 EnterCriticalSection (&cond->lock);
00261
00262 if (cond->list != NULL)
00263 {
00264 SetEvent (_dbus_list_pop_first (&cond->list));
00265
00266
00267
00268
00269 Sleep (0);
00270 }
00271 LeaveCriticalSection (&cond->lock);
00272 }
00273
00274 dbus_bool_t
00275 _dbus_threads_init_platform_specific (void)
00276 {
00277
00278
00279
00280 if (dbus_cond_event_tls == TLS_OUT_OF_INDEXES)
00281 {
00282 dbus_cond_event_tls = TlsAlloc ();
00283 if (dbus_cond_event_tls == TLS_OUT_OF_INDEXES)
00284 return FALSE;
00285 }
00286
00287 return TRUE;
00288 }
00289
00290 void
00291 _dbus_threads_lock_platform_specific (void)
00292 {
00293 _dbus_assert (global_init_done);
00294 EnterCriticalSection (&init_lock);
00295 }
00296
00297 void
00298 _dbus_threads_unlock_platform_specific (void)
00299 {
00300 _dbus_assert (global_init_done);
00301 LeaveCriticalSection (&init_lock);
00302 }