#ifdef UNDER_CE
# include <mmsystem.h>
#endif
+#include "config/configuration.h"
static vlc_threadvar_t thread_key;
void *data;
};
-#ifdef UNDER_CE
-static void CALLBACK vlc_cancel_self (ULONG_PTR dummy);
+static CRITICAL_SECTION super_mutex;
+static HANDLE super_cond;
+
+BOOL WINAPI DllMain (HINSTANCE, DWORD, LPVOID);
-static DWORD vlc_cancelable_wait (DWORD count, const HANDLE *handles,
- DWORD delay)
+BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
{
- struct vlc_thread *th = vlc_threadvar_get (thread_key);
- if (th == NULL)
- {
- /* Main thread - cannot be cancelled anyway */
- return WaitForMultipleObjects (count, handles, FALSE, delay);
- }
- HANDLE new_handles[count + 1];
- memcpy(new_handles, handles, count * sizeof(HANDLE));
- new_handles[count] = th->cancel_event;
- DWORD result = WaitForMultipleObjects (count + 1, new_handles, FALSE,
- delay);
- if (result == WAIT_OBJECT_0 + count)
- {
- vlc_cancel_self ((uintptr_t)th);
- return WAIT_IO_COMPLETION;
- }
- else
+ (void) hinstDll;
+ (void) lpvReserved;
+
+ switch (fdwReason)
{
- return result;
+ case DLL_PROCESS_ATTACH:
+ super_cond = CreateEvent (NULL, TRUE, FALSE, NULL);
+ if (unlikely(!super_cond))
+ return FALSE;
+ InitializeCriticalSection (&super_mutex);
+ vlc_threadvar_create (&thread_key, NULL);
+ vlc_rwlock_init (&config_lock);
+ break;
+
+ case DLL_PROCESS_DETACH:
+ vlc_rwlock_destroy (&config_lock);
+ vlc_threadvar_delete (&thread_key);
+ DeleteCriticalSection (&super_mutex);
+ CloseHandle (super_cond);
+ break;
}
+ return TRUE;
}
-DWORD SleepEx (DWORD dwMilliseconds, BOOL bAlertable)
+static void CALLBACK vlc_cancel_self (ULONG_PTR);
+
+static DWORD vlc_WaitForMultipleObjects (DWORD count, const HANDLE *handles,
+ DWORD delay)
{
- if (bAlertable)
- {
- DWORD result = vlc_cancelable_wait (0, NULL, dwMilliseconds);
- return (result == WAIT_TIMEOUT) ? 0 : WAIT_IO_COMPLETION;
- }
- else
+ DWORD ret;
+#ifdef UNDER_CE
+ HANDLE buf[count + 1];
+
+ struct vlc_thread *th = vlc_threadvar_get (thread_key);
+ if (th != NULL)
{
- Sleep(dwMilliseconds);
- return 0;
+ memcpy (buf, handles, count * sizeof(HANDLE));
+ buf[count++] = th->cancel_event;
+ handles = buf;
}
-}
-DWORD WaitForSingleObjectEx (HANDLE hHandle, DWORD dwMilliseconds,
- BOOL bAlertable)
-{
- if (bAlertable)
+ if (count == 0)
{
- /* The MSDN documentation specifies different return codes,
- * but in practice they are the same. We just check that it
- * remains so. */
-#if WAIT_ABANDONED != WAIT_ABANDONED_0
-# error Windows headers changed, code needs to be rewritten!
-#endif
- return vlc_cancelable_wait (1, &hHandle, dwMilliseconds);
+ Sleep (delay);
+ ret = WAIT_TIMEOUT;
}
else
- {
- return WaitForSingleObject (hHandle, dwMilliseconds);
- }
-}
+ ret = WaitForMultipleObjects (count, handles, FALSE, delay);
-DWORD WaitForMultipleObjectsEx (DWORD nCount, const HANDLE *lpHandles,
- BOOL bWaitAll, DWORD dwMilliseconds,
- BOOL bAlertable)
-{
- if (bAlertable)
+ if ((th != NULL) && (ret == WAIT_OBJECT_0 + count - 1))
{
- /* We do not support the bWaitAll case */
- assert (! bWaitAll);
- return vlc_cancelable_wait (nCount, lpHandles, dwMilliseconds);
+ vlc_cancel_self ((uintptr_t)th);
+ ret = WAIT_IO_COMPLETION;
}
- else
+#else
+ if (count == 0)
{
- return WaitForMultipleObjects (nCount, lpHandles, bWaitAll,
- dwMilliseconds);
+ ret = SleepEx (delay, TRUE);
+ if (ret == 0)
+ ret = WAIT_TIMEOUT;
}
-}
+ else
+ ret = WaitForMultipleObjectsEx (count, handles, FALSE, delay, TRUE);
#endif
+ /* We do not abandon objects... this would be a bug */
+ assert (ret < WAIT_ABANDONED_0 || WAIT_ABANDONED_0 + count - 1 < ret);
-static vlc_mutex_t super_mutex;
-static vlc_cond_t super_variable;
+ if (unlikely(ret == WAIT_FAILED))
+ abort (); /* We are screwed! */
+ return ret;
+}
-BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
+static DWORD vlc_WaitForSingleObject (HANDLE handle, DWORD delay)
{
- (void) hinstDll;
- (void) lpvReserved;
-
- switch (fdwReason)
- {
- case DLL_PROCESS_ATTACH:
- vlc_mutex_init (&super_mutex);
- vlc_cond_init (&super_variable);
- vlc_threadvar_create (&thread_key, NULL);
- break;
+ return vlc_WaitForMultipleObjects (1, &handle, delay);
+}
- case DLL_PROCESS_DETACH:
- vlc_threadvar_delete (&thread_key);
- vlc_cond_destroy (&super_variable);
- vlc_mutex_destroy (&super_mutex);
- break;
- }
- return TRUE;
+static DWORD vlc_Sleep (DWORD delay)
+{
+ DWORD ret = vlc_WaitForMultipleObjects (0, NULL, delay);
+ return (ret != WAIT_TIMEOUT) ? ret : 0;
}
+
/*** Mutexes ***/
void vlc_mutex_init( vlc_mutex_t *p_mutex )
{
void vlc_mutex_lock (vlc_mutex_t *p_mutex)
{
if (!p_mutex->dynamic)
- { /* static mutexes */
- int canc = vlc_savecancel ();
- assert (p_mutex != &super_mutex); /* this one cannot be static */
-
- vlc_mutex_lock (&super_mutex);
+ { /* static mutexes (inefficient on Windows) */
+ EnterCriticalSection (&super_mutex);
while (p_mutex->locked)
{
p_mutex->contention++;
- vlc_cond_wait (&super_variable, &super_mutex);
+ LeaveCriticalSection (&super_mutex);
+ WaitForSingleObject (super_cond, INFINITE);
+ EnterCriticalSection (&super_mutex);
+ assert (p_mutex->contention > 0);
p_mutex->contention--;
}
p_mutex->locked = true;
- vlc_mutex_unlock (&super_mutex);
- vlc_restorecancel (canc);
+ LeaveCriticalSection (&super_mutex);
return;
}
{ /* static mutexes */
int ret = EBUSY;
- assert (p_mutex != &super_mutex); /* this one cannot be static */
- vlc_mutex_lock (&super_mutex);
+ EnterCriticalSection (&super_mutex);
if (!p_mutex->locked)
{
p_mutex->locked = true;
ret = 0;
}
- vlc_mutex_unlock (&super_mutex);
+ LeaveCriticalSection (&super_mutex);
return ret;
}
{
if (!p_mutex->dynamic)
{ /* static mutexes */
- assert (p_mutex != &super_mutex); /* this one cannot be static */
-
- vlc_mutex_lock (&super_mutex);
+ EnterCriticalSection (&super_mutex);
assert (p_mutex->locked);
p_mutex->locked = false;
- if (p_mutex->contention)
- vlc_cond_broadcast (&super_variable);
- vlc_mutex_unlock (&super_mutex);
+ if (p_mutex->contention > 0)
+ SetEvent (super_cond);
+ LeaveCriticalSection (&super_mutex);
return;
}
/*** Condition variables ***/
enum
{
+ CLOCK_REALTIME=0, /* must be zero for VLC_STATIC_COND */
CLOCK_MONOTONIC,
- CLOCK_REALTIME,
};
static void vlc_cond_init_common (vlc_cond_t *p_condvar, unsigned clock)
void vlc_cond_signal (vlc_cond_t *p_condvar)
{
- /* NOTE: This will cause a broadcast, that is wrong.
- * This will also wake up the next waiting thread if no threads are yet
- * waiting, which is also wrong. However both of these issues are allowed
- * by the provision for spurious wakeups. Better have too many wakeups
- * than too few (= deadlocks). */
- SetEvent (p_condvar->handle);
+ if (!p_condvar->handle)
+ return;
+
+ /* This is suboptimal but works. */
+ vlc_cond_broadcast (p_condvar);
}
void vlc_cond_broadcast (vlc_cond_t *p_condvar)
{
+ if (!p_condvar->handle)
+ return;
+
+ /* Wake all threads up (as the event HANDLE has manual reset) */
SetEvent (p_condvar->handle);
}
{
DWORD result;
- assert (p_mutex->dynamic); /* TODO */
+ if (!p_condvar->handle)
+ { /* FIXME FIXME FIXME */
+ msleep (50000);
+ return;
+ }
+
do
{
vlc_testcancel ();
- LeaveCriticalSection (&p_mutex->mutex);
- result = WaitForSingleObjectEx (p_condvar->handle, INFINITE, TRUE);
- EnterCriticalSection (&p_mutex->mutex);
+ vlc_mutex_unlock (p_mutex);
+ result = vlc_WaitForSingleObject (p_condvar->handle, INFINITE);
+ vlc_mutex_lock (p_mutex);
}
while (result == WAIT_IO_COMPLETION);
- assert (result != WAIT_ABANDONED); /* another thread failed to cleanup! */
- assert (result != WAIT_FAILED);
ResetEvent (p_condvar->handle);
}
{
DWORD result;
- assert (p_mutex->dynamic); /* TODO */
+ if (!p_condvar->handle)
+ { /* FIXME FIXME FIXME */
+ msleep (50000);
+ return 0;
+ }
+
do
{
vlc_testcancel ();
mtime_t total;
switch (p_condvar->clock)
{
- case CLOCK_MONOTONIC:
- total = mdate();
- break;
case CLOCK_REALTIME: /* FIXME? sub-second precision */
total = CLOCK_FREQ * time (NULL);
break;
default:
- assert (0);
+ assert (p_condvar->clock == CLOCK_MONOTONIC);
+ total = mdate();
+ break;
}
total = (deadline - total) / 1000;
if( total < 0 )
total = 0;
DWORD delay = (total > 0x7fffffff) ? 0x7fffffff : total;
- LeaveCriticalSection (&p_mutex->mutex);
- result = WaitForSingleObjectEx (p_condvar->handle, delay, TRUE);
- EnterCriticalSection (&p_mutex->mutex);
+ vlc_mutex_unlock (p_mutex);
+ result = vlc_WaitForSingleObject (p_condvar->handle, delay);
+ vlc_mutex_lock (p_mutex);
}
while (result == WAIT_IO_COMPLETION);
- assert (result != WAIT_ABANDONED);
- assert (result != WAIT_FAILED);
ResetEvent (p_condvar->handle);
return (result == WAIT_OBJECT_0) ? 0 : ETIMEDOUT;
do
{
vlc_testcancel ();
- result = WaitForSingleObjectEx (*sem, INFINITE, TRUE);
+ result = vlc_WaitForSingleObject (*sem, INFINITE);
}
while (result == WAIT_IO_COMPLETION);
}
var->next = NULL;
*p_tls = var;
- vlc_mutex_lock (&super_mutex);
+ EnterCriticalSection (&super_mutex);
var->prev = vlc_threadvar_last;
vlc_threadvar_last = var;
- vlc_mutex_unlock (&super_mutex);
+ LeaveCriticalSection (&super_mutex);
return 0;
}
{
struct vlc_threadvar *var = *p_tls;
- vlc_mutex_lock (&super_mutex);
+ EnterCriticalSection (&super_mutex);
if (var->prev != NULL)
var->prev->next = var->next;
else
vlc_threadvar_last = var->next;
if (var->next != NULL)
var->next->prev = var->prev;
- vlc_mutex_unlock (&super_mutex);
+ LeaveCriticalSection (&super_mutex);
TlsFree (var->id);
free (var);
retry:
/* TODO: use RW lock or something similar */
- vlc_mutex_lock (&super_mutex);
+ EnterCriticalSection (&super_mutex);
for (key = vlc_threadvar_last; key != NULL; key = key->prev)
{
void *value = vlc_threadvar_get (key);
if (value != NULL && key->destroy != NULL)
{
- vlc_mutex_unlock (&super_mutex);
+ EnterCriticalSection (&super_mutex);
vlc_threadvar_set (key, NULL);
key->destroy (value);
goto retry;
}
}
- vlc_mutex_unlock (&super_mutex);
+ EnterCriticalSection (&super_mutex);
if (th->detached)
{
* function instead of CreateThread, otherwise you'll end up with
* memory leaks and the signal functions not working (see Microsoft
* Knowledge Base, article 104641) */
- hThread = (HANDLE)(uintptr_t)
- _beginthreadex (NULL, 0, vlc_entry, th, CREATE_SUSPENDED, NULL);
- if (hThread == NULL)
+ uintptr_t h;
+
+ h = _beginthreadex (NULL, 0, vlc_entry, th, CREATE_SUSPENDED, NULL);
+ if (h == 0)
{
int err = errno;
free (th);
return err;
}
+ hThread = (HANDLE)h;
#else
th->cancel_event = CreateEvent (NULL, FALSE, FALSE, NULL);
{
do
vlc_testcancel ();
- while (WaitForSingleObjectEx (th->id, INFINITE, TRUE)
+ while (vlc_WaitForSingleObject (th->id, INFINITE)
== WAIT_IO_COMPLETION);
if (result != NULL)
delay /= 1000;
if (unlikely(delay > 0x7fffffff))
delay = 0x7fffffff;
- SleepEx (delay, TRUE);
+ vlc_Sleep (delay);
vlc_testcancel();
}
}