LGPL
[vlc.git] / src / win32 / thread.c
index 965db99..90a80a3 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * thread.c : Win32 back-end for LibVLC
  *****************************************************************************
- * Copyright (C) 1999-2009 the VideoLAN team
+ * Copyright (C) 1999-2009 VLC authors and VideoLAN
  *
  * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
  *          Samuel Hocevar <sam@zoy.org>
  *          RĂ©mi Denis-Courmont
  *          Pierre Ynard
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 #ifdef HAVE_CONFIG_H
@@ -39,7 +39,6 @@
 #ifdef UNDER_CE
 # include <mmsystem.h>
 #endif
-#include "config/configuration.h"
 
 static vlc_threadvar_t thread_key;
 
@@ -62,8 +61,9 @@ struct vlc_thread
     void          *data;
 };
 
-static CRITICAL_SECTION super_mutex;
-static HANDLE           super_cond;
+static vlc_mutex_t super_mutex;
+static vlc_cond_t  super_variable;
+extern vlc_rwlock_t config_lock, msg_lock;
 
 BOOL WINAPI DllMain (HINSTANCE, DWORD, LPVOID);
 
@@ -75,19 +75,20 @@ BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
     switch (fdwReason)
     {
         case DLL_PROCESS_ATTACH:
-            super_cond = CreateEvent (NULL, TRUE, FALSE, NULL);
-            if (unlikely(!super_cond))
-                return FALSE;
-            InitializeCriticalSection (&super_mutex);
+            vlc_mutex_init (&super_mutex);
+            vlc_cond_init (&super_variable);
             vlc_threadvar_create (&thread_key, NULL);
             vlc_rwlock_init (&config_lock);
+            vlc_rwlock_init (&msg_lock);
+            vlc_CPU_init ();
             break;
 
         case DLL_PROCESS_DETACH:
+            vlc_rwlock_destroy (&msg_lock);
             vlc_rwlock_destroy (&config_lock);
             vlc_threadvar_delete (&thread_key);
-            DeleteCriticalSection (&super_mutex);
-            CloseHandle (super_cond);
+            vlc_cond_destroy (&super_variable);
+            vlc_mutex_destroy (&super_mutex);
             break;
     }
     return TRUE;
@@ -178,19 +179,20 @@ void vlc_mutex_destroy (vlc_mutex_t *p_mutex)
 void vlc_mutex_lock (vlc_mutex_t *p_mutex)
 {
     if (!p_mutex->dynamic)
-    {   /* static mutexes (inefficient on Windows) */
-        EnterCriticalSection (&super_mutex);
+    {   /* static mutexes */
+        int canc = vlc_savecancel ();
+        assert (p_mutex != &super_mutex); /* this one cannot be static */
+
+        vlc_mutex_lock (&super_mutex);
         while (p_mutex->locked)
         {
             p_mutex->contention++;
-            LeaveCriticalSection (&super_mutex);
-            WaitForSingleObject (super_cond, INFINITE);
-            EnterCriticalSection (&super_mutex);
-            assert (p_mutex->contention > 0);
+            vlc_cond_wait (&super_variable, &super_mutex);
             p_mutex->contention--;
         }
         p_mutex->locked = true;
-        LeaveCriticalSection (&super_mutex);
+        vlc_mutex_unlock (&super_mutex);
+        vlc_restorecancel (canc);
         return;
     }
 
@@ -203,13 +205,14 @@ int vlc_mutex_trylock (vlc_mutex_t *p_mutex)
     {   /* static mutexes */
         int ret = EBUSY;
 
-        EnterCriticalSection (&super_mutex);
+        assert (p_mutex != &super_mutex); /* this one cannot be static */
+        vlc_mutex_lock (&super_mutex);
         if (!p_mutex->locked)
         {
             p_mutex->locked = true;
             ret = 0;
         }
-        LeaveCriticalSection (&super_mutex);
+        vlc_mutex_unlock (&super_mutex);
         return ret;
     }
 
@@ -220,12 +223,14 @@ void vlc_mutex_unlock (vlc_mutex_t *p_mutex)
 {
     if (!p_mutex->dynamic)
     {   /* static mutexes */
-        EnterCriticalSection (&super_mutex);
+        assert (p_mutex != &super_mutex); /* this one cannot be static */
+
+        vlc_mutex_lock (&super_mutex);
         assert (p_mutex->locked);
         p_mutex->locked = false;
-        if (p_mutex->contention > 0)
-            SetEvent (super_cond);
-        LeaveCriticalSection (&super_mutex);
+        if (p_mutex->contention)
+            vlc_cond_broadcast (&super_variable);
+        vlc_mutex_unlock (&super_mutex);
         return;
     }
 
@@ -381,8 +386,7 @@ void vlc_sem_wait (vlc_sem_t *sem)
 void vlc_rwlock_init (vlc_rwlock_t *lock)
 {
     vlc_mutex_init (&lock->mutex);
-    vlc_cond_init (&lock->read_wait);
-    vlc_cond_init (&lock->write_wait);
+    vlc_cond_init (&lock->wait);
     lock->readers = 0; /* active readers */
     lock->writers = 0; /* waiting writers */
     lock->writer = 0; /* ID of active writer */
@@ -390,8 +394,7 @@ void vlc_rwlock_init (vlc_rwlock_t *lock)
 
 void vlc_rwlock_destroy (vlc_rwlock_t *lock)
 {
-    vlc_cond_destroy (&lock->read_wait);
-    vlc_cond_destroy (&lock->write_wait);
+    vlc_cond_destroy (&lock->wait);
     vlc_mutex_destroy (&lock->mutex);
 }
 
@@ -408,7 +411,7 @@ void vlc_rwlock_rdlock (vlc_rwlock_t *lock)
     while (lock->writer != 0)
     {
         assert (lock->readers == 0);
-        vlc_cond_wait (&lock->read_wait, &lock->mutex);
+        vlc_cond_wait (&lock->wait, &lock->mutex);
     }
     if (unlikely(lock->readers == ULONG_MAX))
         abort ();
@@ -423,7 +426,7 @@ static void vlc_rwlock_rdunlock (vlc_rwlock_t *lock)
 
     /* If there are no readers left, wake up a writer. */
     if (--lock->readers == 0 && lock->writers > 0)
-        vlc_cond_signal (&lock->write_wait);
+        vlc_cond_signal (&lock->wait);
     vlc_mutex_unlock (&lock->mutex);
 }
 
@@ -435,7 +438,7 @@ void vlc_rwlock_wrlock (vlc_rwlock_t *lock)
     lock->writers++;
     /* Wait until nobody owns the lock in either way. */
     while ((lock->readers > 0) || (lock->writer != 0))
-        vlc_cond_wait (&lock->write_wait, &lock->mutex);
+        vlc_cond_wait (&lock->wait, &lock->mutex);
     lock->writers--;
     assert (lock->writer == 0);
     lock->writer = GetCurrentThreadId ();
@@ -450,9 +453,7 @@ static void vlc_rwlock_wrunlock (vlc_rwlock_t *lock)
     lock->writer = 0; /* Write unlock */
 
     /* Let reader and writer compete. Scheduler decides who wins. */
-    if (lock->writers > 0)
-        vlc_cond_signal (&lock->write_wait);
-    vlc_cond_broadcast (&lock->read_wait);
+    vlc_cond_broadcast (&lock->wait);
     vlc_mutex_unlock (&lock->mutex);
 }
 
@@ -492,10 +493,13 @@ int vlc_threadvar_create (vlc_threadvar_t *p_tls, void (*destr) (void *))
     var->next = NULL;
     *p_tls = var;
 
-    EnterCriticalSection (&super_mutex);
+    vlc_mutex_lock (&super_mutex);
     var->prev = vlc_threadvar_last;
+    if (var->prev)
+        var->prev->next = var;
+
     vlc_threadvar_last = var;
-    LeaveCriticalSection (&super_mutex);
+    vlc_mutex_unlock (&super_mutex);
     return 0;
 }
 
@@ -503,14 +507,16 @@ void vlc_threadvar_delete (vlc_threadvar_t *p_tls)
 {
     struct vlc_threadvar *var = *p_tls;
 
-    EnterCriticalSection (&super_mutex);
+    vlc_mutex_lock (&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;
-    LeaveCriticalSection (&super_mutex);
+    else
+        vlc_threadvar_last = var->prev;
+
+    vlc_mutex_unlock (&super_mutex);
 
     TlsFree (var->id);
     free (var);
@@ -538,19 +544,19 @@ static void vlc_thread_cleanup (struct vlc_thread *th)
 
 retry:
     /* TODO: use RW lock or something similar */
-    EnterCriticalSection (&super_mutex);
+    vlc_mutex_lock (&super_mutex);
     for (key = vlc_threadvar_last; key != NULL; key = key->prev)
     {
         void *value = vlc_threadvar_get (key);
         if (value != NULL && key->destroy != NULL)
         {
-            EnterCriticalSection (&super_mutex);
+            vlc_mutex_unlock (&super_mutex);
             vlc_threadvar_set (key, NULL);
             key->destroy (value);
             goto retry;
         }
     }
-    EnterCriticalSection (&super_mutex);
+    vlc_mutex_unlock (&super_mutex);
 
     if (th->detached)
     {
@@ -945,8 +951,8 @@ unsigned vlc_timer_getoverrun (vlc_timer_t timer)
 unsigned vlc_GetCPUCount (void)
 {
 #ifndef UNDER_CE
-    DWORD process;
-    DWORD system;
+    DWORD_PTR process;
+    DWORD_PTR system;
 
     if (GetProcessAffinityMask (GetCurrentProcess(), &process, &system))
         return popcount (system);