#include "config.h"
#include "gthread.h"
+#include "gthreadprivate.h"
+#include "gslice.h"
-#define _WIN32_WINDOWS 0x0401 /* to get IsDebuggerPresent */
#include <windows.h>
#include <process.h>
*/
typedef struct
{
- void (* CallThisOnThreadExit) (void); /* fake */
-
- void (* InitializeSRWLock) (gpointer lock);
- void (* DeleteSRWLock) (gpointer lock); /* fake */
- void (* AcquireSRWLockExclusive) (gpointer lock);
- BOOLEAN (* TryAcquireSRWLockExclusive) (gpointer lock);
- void (* ReleaseSRWLockExclusive) (gpointer lock);
-
- void (* InitializeConditionVariable) (gpointer cond);
- void (* DeleteConditionVariable) (gpointer cond); /* fake */
- BOOL (* SleepConditionVariableSRW) (gpointer cond,
- gpointer lock,
- DWORD timeout,
- ULONG flags);
- void (* WakeAllConditionVariable) (gpointer cond);
- void (* WakeConditionVariable) (gpointer cond);
+ void (__stdcall * CallThisOnThreadExit) (void); /* fake */
+
+ void (__stdcall * InitializeSRWLock) (gpointer lock);
+ void (__stdcall * DeleteSRWLock) (gpointer lock); /* fake */
+ void (__stdcall * AcquireSRWLockExclusive) (gpointer lock);
+ BOOLEAN (__stdcall * TryAcquireSRWLockExclusive) (gpointer lock);
+ void (__stdcall * ReleaseSRWLockExclusive) (gpointer lock);
+ void (__stdcall * AcquireSRWLockShared) (gpointer lock);
+ BOOLEAN (__stdcall * TryAcquireSRWLockShared) (gpointer lock);
+ void (__stdcall * ReleaseSRWLockShared) (gpointer lock);
+
+ void (__stdcall * InitializeConditionVariable) (gpointer cond);
+ void (__stdcall * DeleteConditionVariable) (gpointer cond); /* fake */
+ BOOL (__stdcall * SleepConditionVariableSRW) (gpointer cond,
+ gpointer lock,
+ DWORD timeout,
+ ULONG flags);
+ void (__stdcall * WakeAllConditionVariable) (gpointer cond);
+ void (__stdcall * WakeConditionVariable) (gpointer cond);
} GThreadImplVtable;
static GThreadImplVtable g_thread_impl_vtable;
void
g_mutex_lock (GMutex *mutex)
{
- /* temporary until we fix libglib */
- if (mutex == NULL)
- return;
-
g_thread_impl_vtable.AcquireSRWLockExclusive (mutex);
}
gboolean
g_mutex_trylock (GMutex *mutex)
{
- /* temporary until we fix libglib */
- if (mutex == NULL)
- return TRUE;
-
return g_thread_impl_vtable.TryAcquireSRWLockExclusive (mutex);
}
void
g_mutex_unlock (GMutex *mutex)
{
- /* temporary until we fix libglib */
- if (mutex == NULL)
- return;
-
g_thread_impl_vtable.ReleaseSRWLockExclusive (mutex);
}
+/* {{{1 GRecMutex */
+
+static CRITICAL_SECTION *
+g_rec_mutex_impl_new (void)
+{
+ CRITICAL_SECTION *cs;
+
+ cs = g_slice_new (CRITICAL_SECTION);
+ InitializeCriticalSection (cs);
+
+ return cs;
+}
+
+static void
+g_rec_mutex_impl_free (CRITICAL_SECTION *cs)
+{
+ DeleteCriticalSection (cs);
+ g_slice_free (CRITICAL_SECTION, cs);
+}
+
+static CRITICAL_SECTION *
+g_rec_mutex_get_impl (GRecMutex *mutex)
+{
+ CRITICAL_SECTION *impl = mutex->impl;
+
+ if G_UNLIKELY (mutex->impl == NULL)
+ {
+ impl = g_rec_mutex_impl_new ();
+ if (InterlockedCompareExchangePointer (&mutex->impl, impl, NULL) != NULL)
+ g_rec_mutex_impl_free (impl);
+ impl = mutex->impl;
+ }
+
+ return impl;
+}
+
+void
+g_rec_mutex_init (GRecMutex *mutex)
+{
+ mutex->impl = g_rec_mutex_impl_new ();
+}
+
+void
+g_rec_mutex_clear (GRecMutex *mutex)
+{
+ if (mutex->impl)
+ g_rec_mutex_impl_free (mutex->impl);
+}
+
+void
+g_rec_mutex_lock (GRecMutex *mutex)
+{
+ EnterCriticalSection (g_rec_mutex_get_impl (mutex));
+}
+
+void
+g_rec_mutex_unlock (GRecMutex *mutex)
+{
+ LeaveCriticalSection (mutex->impl);
+}
+
+gboolean
+g_rec_mutex_trylock (GRecMutex *mutex)
+{
+ return TryEnterCriticalSection (g_rec_mutex_get_impl (mutex));
+}
+
+/* {{{1 GRWLock */
+
+void
+g_rw_lock_init (GRWLock *lock)
+{
+ g_thread_impl_vtable.InitializeSRWLock (lock);
+}
+
+void
+g_rw_lock_clear (GRWLock *lock)
+{
+ if (g_thread_impl_vtable.DeleteSRWLock != NULL)
+ g_thread_impl_vtable.DeleteSRWLock (lock);
+}
+
+void
+g_rw_lock_writer_lock (GRWLock *lock)
+{
+ g_thread_impl_vtable.AcquireSRWLockExclusive (lock);
+}
+
+gboolean
+g_rw_lock_writer_trylock (GRWLock *lock)
+{
+ return g_thread_impl_vtable.TryAcquireSRWLockExclusive (lock);
+}
+
+void
+g_rw_lock_writer_unlock (GRWLock *lock)
+{
+ g_thread_impl_vtable.ReleaseSRWLockExclusive (lock);
+}
+
+void
+g_rw_lock_reader_lock (GRWLock *lock)
+{
+ g_thread_impl_vtable.AcquireSRWLockShared (lock);
+}
+
+gboolean
+g_rw_lock_reader_trylock (GRWLock *lock)
+{
+ return g_thread_impl_vtable.TryAcquireSRWLockShared (lock);
+}
+
+void
+g_rw_lock_reader_unlock (GRWLock *lock)
+{
+ g_thread_impl_vtable.ReleaseSRWLockShared (lock);
+}
+
/* {{{1 GCond */
void
g_cond_init (GCond *cond)
void
g_cond_signal (GCond *cond)
{
- /* temporary until we fix libglib */
- if (cond == NULL)
- return;
-
g_thread_impl_vtable.WakeConditionVariable (cond);
}
void
g_cond_broadcast (GCond *cond)
{
- /* temporary until we fix libglib */
- if (cond == NULL)
- return;
-
g_thread_impl_vtable.WakeAllConditionVariable (cond);
}
/* {{{1 GPrivate */
-#include "glib.h"
-#include "gthreadprivate.h"
+typedef struct _GPrivateDestructor GPrivateDestructor;
-#define win32_check_for_error(what) G_STMT_START{ \
- if (!(what)) \
- g_error ("file %s: line %d (%s): error %s during %s", \
- __FILE__, __LINE__, G_STRFUNC, \
- g_win32_error_message (GetLastError ()), #what); \
- }G_STMT_END
-
-#define G_MUTEX_SIZE (sizeof (gpointer))
+struct _GPrivateDestructor
+{
+ DWORD index;
+ GDestroyNotify notify;
+ GPrivateDestructor *next;
+};
-static DWORD g_thread_self_tls;
-static DWORD g_private_tls;
-static CRITICAL_SECTION g_thread_global_spinlock;
+static GPrivateDestructor * volatile g_private_destructors;
-typedef BOOL (__stdcall *GTryEnterCriticalSectionFunc) (CRITICAL_SECTION *);
+void
+g_private_init (GPrivate *key,
+ GDestroyNotify notify)
+{
+ GPrivateDestructor *destructor;
-/* As noted in the docs, GPrivate is a limited resource, here we take
- * a rather low maximum to save memory, use GStaticPrivate instead. */
-#define G_PRIVATE_MAX 100
+ key->index = TlsAlloc ();
-static GDestroyNotify g_private_destructors[G_PRIVATE_MAX];
+ destructor = malloc (sizeof (GPrivateDestructor));
+ if G_UNLIKELY (destructor == NULL)
+ g_thread_abort (errno, "malloc");
+ destructor->index = key->index;
+ destructor->notify = notify;
-static guint g_private_next = 0;
+ do
+ destructor->next = g_private_destructors;
+ while (InterlockedCompareExchangePointer (&g_private_destructors, destructor->next, destructor) != destructor->next);
-typedef struct _GThreadData GThreadData;
-struct _GThreadData
-{
- GThreadFunc func;
- gpointer data;
- HANDLE thread;
- gboolean joinable;
-};
+ key->ready = TRUE;
+}
-static GPrivate *
-g_private_new_win32_impl (GDestroyNotify destructor)
+gpointer
+g_private_get (GPrivate *key)
{
- GPrivate *result;
- EnterCriticalSection (&g_thread_global_spinlock);
- if (g_private_next >= G_PRIVATE_MAX)
- {
- char buf[100];
- sprintf (buf,
- "Too many GPrivate allocated. Their number is limited to %d.",
- G_PRIVATE_MAX);
- MessageBox (NULL, buf, NULL, MB_ICONERROR|MB_SETFOREGROUND);
- if (IsDebuggerPresent ())
- G_BREAKPOINT ();
- abort ();
- }
- g_private_destructors[g_private_next] = destructor;
- result = GUINT_TO_POINTER (g_private_next);
- g_private_next++;
- LeaveCriticalSection (&g_thread_global_spinlock);
+ if (!key->ready)
+ return key->single_value;
- return result;
+ return TlsGetValue (key->index);
}
-/* NOTE: the functions g_private_get and g_private_set may not use
- functions from gmem.c and gmessages.c */
-
-static void
-g_private_set_win32_impl (GPrivate * private_key, gpointer value)
+void
+g_private_set (GPrivate *key,
+ gpointer value)
{
- gpointer* array = TlsGetValue (g_private_tls);
- guint index = GPOINTER_TO_UINT (private_key);
-
- if (index >= G_PRIVATE_MAX)
- return;
-
- if (!array)
+ if (!key->ready)
{
- array = (gpointer*) calloc (G_PRIVATE_MAX, sizeof (gpointer));
- TlsSetValue (g_private_tls, array);
+ key->single_value = value;
+ return;
}
- array[index] = value;
-}
-
-static gpointer
-g_private_get_win32_impl (GPrivate * private_key)
-{
- gpointer* array = TlsGetValue (g_private_tls);
- guint index = GPOINTER_TO_UINT (private_key);
-
- if (index >= G_PRIVATE_MAX || !array)
- return NULL;
-
- return array[index];
+ TlsSetValue (key->index, value);
}
/* {{{1 GThread */
-static void
-g_thread_set_priority_win32_impl (gpointer thread, GThreadPriority priority)
-{
- GThreadData *target = *(GThreadData **)thread;
- gint native_prio;
-
- switch (priority)
- {
- case G_THREAD_PRIORITY_LOW:
- native_prio = THREAD_PRIORITY_BELOW_NORMAL;
- break;
+#include "glib.h"
+#include "gthreadprivate.h"
- case G_THREAD_PRIORITY_NORMAL:
- native_prio = THREAD_PRIORITY_NORMAL;
- break;
+#define win32_check_for_error(what) G_STMT_START{ \
+ if (!(what)) \
+ g_error ("file %s: line %d (%s): error %s during %s", \
+ __FILE__, __LINE__, G_STRFUNC, \
+ g_win32_error_message (GetLastError ()), #what); \
+ }G_STMT_END
- case G_THREAD_PRIORITY_HIGH:
- native_prio = THREAD_PRIORITY_ABOVE_NORMAL;
- break;
+#define G_MUTEX_SIZE (sizeof (gpointer))
- case G_THREAD_PRIORITY_URGENT:
- native_prio = THREAD_PRIORITY_HIGHEST;
- break;
+static DWORD g_thread_self_tls;
+static DWORD g_private_tls;
- default:
- g_return_if_reached ();
- }
+typedef BOOL (__stdcall *GTryEnterCriticalSectionFunc) (CRITICAL_SECTION *);
- win32_check_for_error (SetThreadPriority (target->thread, native_prio));
-}
+typedef struct _GThreadData GThreadData;
+struct _GThreadData
+{
+ GThreadFunc func;
+ gpointer data;
+ HANDLE thread;
+ gboolean joinable;
+};
-static void
-g_thread_self_win32_impl (gpointer thread)
+void
+g_system_thread_self (gpointer thread)
{
GThreadData *self = TlsGetValue (g_thread_self_tls);
*(GThreadData **)thread = self;
}
-static void
-g_thread_exit_win32_impl (void)
+void
+g_system_thread_exit (void)
{
GThreadData *self = TlsGetValue (g_thread_self_tls);
- guint i, private_max;
- gpointer *array = TlsGetValue (g_private_tls);
+ gboolean dtors_called;
- EnterCriticalSection (&g_thread_global_spinlock);
- private_max = g_private_next;
- LeaveCriticalSection (&g_thread_global_spinlock);
-
- if (array)
+ do
{
- gboolean some_data_non_null;
-
- do {
- some_data_non_null = FALSE;
- for (i = 0; i < private_max; i++)
- {
- GDestroyNotify destructor = g_private_destructors[i];
- GDestroyNotify data = array[i];
-
- if (data)
- some_data_non_null = TRUE;
-
- array[i] = NULL;
-
- if (destructor && data)
- destructor (data);
- }
- } while (some_data_non_null);
-
- free (array);
-
- win32_check_for_error (TlsSetValue (g_private_tls, NULL));
+ GPrivateDestructor *dtor;
+
+ /* We go by the POSIX book on this one.
+ *
+ * If we call a destructor then there is a chance that some new
+ * TLS variables got set by code called in that destructor.
+ *
+ * Loop until nothing is left.
+ */
+ dtors_called = FALSE;
+
+ for (dtor = g_private_destructors; dtor; dtor = dtor->next)
+ {
+ gpointer value;
+
+ value = TlsGetValue (dtor->index);
+ if (value != NULL && dtor->notify != NULL)
+ {
+ /* POSIX says to clear this before the call */
+ TlsSetValue (dtor->index, NULL);
+ dtor->notify (value);
+ dtors_called = TRUE;
+ }
+ }
}
+ while (dtors_called);
if (self)
{
self->func (self->data);
- g_thread_exit_win32_impl ();
+ g_system_thread_exit ();
g_assert_not_reached ();
return 0;
}
-static void
-g_thread_create_win32_impl (GThreadFunc func,
- gpointer data,
- gulong stack_size,
- gboolean joinable,
- gboolean bound,
- GThreadPriority priority,
- gpointer thread,
- GError **error)
+void
+g_system_thread_create (GThreadFunc func,
+ gpointer data,
+ gulong stack_size,
+ gboolean joinable,
+ gpointer thread,
+ GError **error)
{
guint ignore;
GThreadData *retval;
g_return_if_fail (func);
- g_return_if_fail (priority >= G_THREAD_PRIORITY_LOW);
- g_return_if_fail (priority <= G_THREAD_PRIORITY_URGENT);
retval = g_new(GThreadData, 1);
retval->func = func;
}
*(GThreadData **)thread = retval;
-
- g_thread_set_priority_win32_impl (thread, priority);
}
-static void
-g_thread_yield_win32_impl (void)
+void
+g_thread_yield (void)
{
Sleep(0);
}
-static void
-g_thread_join_win32_impl (gpointer thread)
+void
+g_system_thread_join (gpointer thread)
{
GThreadData *target = *(GThreadData **)thread;
g_free (target);
}
+gboolean
+g_system_thread_equal (gpointer thread1,
+ gpointer thread2)
+{
+ return ((GSystemThread*)thread1)->dummy_pointer == ((GSystemThread*)thread2)->dummy_pointer;
+}
+
/* {{{1 SRWLock and CONDITION_VARIABLE emulation (for Windows XP) */
-static DWORD g_thread_xp_waiter_tls;
static CRITICAL_SECTION g_thread_xp_lock;
+static DWORD g_thread_xp_waiter_tls;
/* {{{2 GThreadWaiter utility class for CONDITION_VARIABLE emulation */
typedef struct _GThreadXpWaiter GThreadXpWaiter;
return waiter;
}
-static void
+static void __stdcall
g_thread_xp_CallThisOnThreadExit (void)
{
GThreadXpWaiter *waiter;
/* {{{2 SRWLock emulation */
typedef struct
{
- CRITICAL_SECTION critical_section;
+ CRITICAL_SECTION writer_lock;
+ gboolean ever_shared; /* protected by writer_lock */
+
+ /* below is only ever touched if ever_shared becomes true */
+ CRITICAL_SECTION atomicity;
+ GThreadXpWaiter *queued_writer; /* protected by atomicity lock */
+ gint num_readers; /* protected by atomicity lock */
} GThreadSRWLock;
-static void
+static void __stdcall
g_thread_xp_InitializeSRWLock (gpointer mutex)
{
*(GThreadSRWLock * volatile *) mutex = NULL;
}
-static void
+static void __stdcall
g_thread_xp_DeleteSRWLock (gpointer mutex)
{
GThreadSRWLock *lock = *(GThreadSRWLock * volatile *) mutex;
if (lock)
{
- DeleteCriticalSection (&lock->critical_section);
+ if (lock->ever_shared)
+ DeleteCriticalSection (&lock->atomicity);
+
+ DeleteCriticalSection (&lock->writer_lock);
free (lock);
}
}
-static GThreadSRWLock *
+static GThreadSRWLock * __stdcall
g_thread_xp_get_srwlock (GThreadSRWLock * volatile *lock)
{
GThreadSRWLock *result;
if (result == NULL)
g_thread_abort (errno, "malloc");
- InitializeCriticalSection (&result->critical_section);
+ InitializeCriticalSection (&result->writer_lock);
+ result->ever_shared = FALSE;
*lock = result;
LeaveCriticalSection (&g_thread_xp_lock);
return result;
}
-static void
+static void __stdcall
g_thread_xp_AcquireSRWLockExclusive (gpointer mutex)
{
GThreadSRWLock *lock = g_thread_xp_get_srwlock (mutex);
- EnterCriticalSection (&lock->critical_section);
+ EnterCriticalSection (&lock->writer_lock);
+
+ if (lock->ever_shared)
+ {
+ GThreadXpWaiter *waiter = NULL;
+
+ EnterCriticalSection (&lock->atomicity);
+ if (lock->num_readers > 0)
+ lock->queued_writer = waiter = g_thread_xp_waiter_get ();
+ LeaveCriticalSection (&lock->atomicity);
+
+ if (waiter != NULL)
+ WaitForSingleObject (waiter->event, INFINITE);
+
+ lock->queued_writer = NULL;
+ }
}
-static BOOLEAN
+static BOOLEAN __stdcall
g_thread_xp_TryAcquireSRWLockExclusive (gpointer mutex)
{
GThreadSRWLock *lock = g_thread_xp_get_srwlock (mutex);
- return TryEnterCriticalSection (&lock->critical_section);
+ if (!TryEnterCriticalSection (&lock->writer_lock))
+ return FALSE;
+
+ if (lock->ever_shared)
+ {
+ gboolean available;
+
+ EnterCriticalSection (&lock->atomicity);
+ available = lock->num_readers == 0;
+ LeaveCriticalSection (&lock->atomicity);
+
+ if (!available)
+ {
+ LeaveCriticalSection (&lock->writer_lock);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
}
-static void
+static void __stdcall
g_thread_xp_ReleaseSRWLockExclusive (gpointer mutex)
{
GThreadSRWLock *lock = *(GThreadSRWLock * volatile *) mutex;
* unlock freshly-allocated mutexes.
*/
if (lock != NULL)
- LeaveCriticalSection (&lock->critical_section);
+ LeaveCriticalSection (&lock->writer_lock);
+}
+
+static void
+g_thread_xp_srwlock_become_reader (GThreadSRWLock *lock)
+{
+ if G_UNLIKELY (!lock->ever_shared)
+ {
+ InitializeCriticalSection (&lock->atomicity);
+ lock->queued_writer = NULL;
+ lock->num_readers = 0;
+
+ lock->ever_shared = TRUE;
+ }
+
+ EnterCriticalSection (&lock->atomicity);
+ lock->num_readers++;
+ LeaveCriticalSection (&lock->atomicity);
+}
+
+static void __stdcall
+g_thread_xp_AcquireSRWLockShared (gpointer mutex)
+{
+ GThreadSRWLock *lock = g_thread_xp_get_srwlock (mutex);
+
+ EnterCriticalSection (&lock->writer_lock);
+
+ g_thread_xp_srwlock_become_reader (lock);
+
+ LeaveCriticalSection (&lock->writer_lock);
+}
+
+static BOOLEAN __stdcall
+g_thread_xp_TryAcquireSRWLockShared (gpointer mutex)
+{
+ GThreadSRWLock *lock = g_thread_xp_get_srwlock (mutex);
+
+ if (!TryEnterCriticalSection (&lock->writer_lock))
+ return FALSE;
+
+ g_thread_xp_srwlock_become_reader (lock);
+
+ LeaveCriticalSection (&lock->writer_lock);
+
+ return TRUE;
+}
+
+static void __stdcall
+g_thread_xp_ReleaseSRWLockShared (gpointer mutex)
+{
+ GThreadSRWLock *lock = g_thread_xp_get_srwlock (mutex);
+
+ EnterCriticalSection (&lock->atomicity);
+
+ lock->num_readers--;
+
+ if (lock->num_readers == 0 && lock->queued_writer)
+ SetEvent (lock->queued_writer->event);
+
+ LeaveCriticalSection (&lock->atomicity);
}
/* {{{2 CONDITION_VARIABLE emulation */
volatile GThreadXpWaiter **last_ptr;
} GThreadXpCONDITION_VARIABLE;
-static void
+static void __stdcall
g_thread_xp_InitializeConditionVariable (gpointer cond)
{
*(GThreadXpCONDITION_VARIABLE * volatile *) cond = NULL;
}
-static void
+static void __stdcall
g_thread_xp_DeleteConditionVariable (gpointer cond)
{
GThreadXpCONDITION_VARIABLE *cv = *(GThreadXpCONDITION_VARIABLE * volatile *) cond;
free (cv);
}
-static GThreadXpCONDITION_VARIABLE *
+static GThreadXpCONDITION_VARIABLE * __stdcall
g_thread_xp_get_condition_variable (GThreadXpCONDITION_VARIABLE * volatile *cond)
{
GThreadXpCONDITION_VARIABLE *result;
return result;
}
-static BOOL
+static BOOL __stdcall
g_thread_xp_SleepConditionVariableSRW (gpointer cond,
gpointer mutex,
DWORD timeout,
return status == WAIT_OBJECT_0;
}
-static void
+static void __stdcall
g_thread_xp_WakeConditionVariable (gpointer cond)
{
GThreadXpCONDITION_VARIABLE *cv = g_thread_xp_get_condition_variable (cond);
SetEvent (waiter->event);
}
-static void
+static void __stdcall
g_thread_xp_WakeAllConditionVariable (gpointer cond)
{
GThreadXpCONDITION_VARIABLE *cv = g_thread_xp_get_condition_variable (cond);
g_thread_xp_AcquireSRWLockExclusive,
g_thread_xp_TryAcquireSRWLockExclusive,
g_thread_xp_ReleaseSRWLockExclusive,
+ g_thread_xp_AcquireSRWLockShared,
+ g_thread_xp_TryAcquireSRWLockShared,
+ g_thread_xp_ReleaseSRWLockShared,
g_thread_xp_InitializeConditionVariable,
g_thread_xp_DeleteConditionVariable,
g_thread_xp_SleepConditionVariableSRW,
/* {{{1 Epilogue */
-GThreadFunctions g_thread_functions_for_glib_use =
-{
- g_mutex_new, /* mutex */
- g_mutex_lock,
- g_mutex_trylock,
- g_mutex_unlock,
- g_mutex_free,
- g_cond_new, /* condition */
- g_cond_signal,
- g_cond_broadcast,
- g_cond_wait,
- g_cond_timed_wait,
- g_cond_free,
- g_private_new_win32_impl, /* private thread data */
- g_private_get_win32_impl,
- g_private_set_win32_impl,
- g_thread_create_win32_impl, /* thread */
- g_thread_yield_win32_impl,
- g_thread_join_win32_impl,
- g_thread_exit_win32_impl,
- g_thread_set_priority_win32_impl,
- g_thread_self_win32_impl,
- NULL /* no equal function necessary */
-};
-
-void
-_g_thread_impl_init (void)
-{
- static gboolean beenhere = FALSE;
-
- if (beenhere)
- return;
-
- beenhere = TRUE;
-
- printf ("thread init\n");
- win32_check_for_error (TLS_OUT_OF_INDEXES !=
- (g_thread_self_tls = TlsAlloc ()));
- win32_check_for_error (TLS_OUT_OF_INDEXES !=
- (g_private_tls = TlsAlloc ()));
- InitializeCriticalSection (&g_thread_global_spinlock);
-}
-
static gboolean
g_thread_lookup_native_funcs (void)
{
GET_FUNC(AcquireSRWLockExclusive);
GET_FUNC(TryAcquireSRWLockExclusive);
GET_FUNC(ReleaseSRWLockExclusive);
+ GET_FUNC(AcquireSRWLockShared);
+ GET_FUNC(TryAcquireSRWLockShared);
+ GET_FUNC(ReleaseSRWLockShared);
GET_FUNC(InitializeConditionVariable);
GET_FUNC(SleepConditionVariableSRW);
G_GNUC_INTERNAL void
g_thread_DllMain (void)
{
- /* XXX This is broken right now for some unknown reason...
-
if (g_thread_lookup_native_funcs ())
fprintf (stderr, "(debug) GThread using native mode\n");
else
-*/
{
fprintf (stderr, "(debug) GThread using Windows XP mode\n");
g_thread_xp_init ();
}
+
+ win32_check_for_error (TLS_OUT_OF_INDEXES != (g_thread_self_tls = TlsAlloc ()));
+ win32_check_for_error (TLS_OUT_OF_INDEXES != (g_private_tls = TlsAlloc ()));
}
/* vim:set foldmethod=marker: */