From f95c64cc6ab6675e372b400066f6a5e09fc767f3 Mon Sep 17 00:00:00 2001 From: zeromus Date: Tue, 21 Jul 2009 00:08:52 +0000 Subject: [PATCH] win32: enable gthreads --- .../build/glib/gthread/gthread-impl.c | 372 ++++++++++ .../build/glib/gthread/gthread-none.c | 39 ++ .../build/glib/gthread/gthread-posix.c | 467 +++++++++++++ .../build/glib/gthread/gthread-win32.c | 639 ++++++++++++++++++ .../windows/glib-2.20.1/build/vs8/glib.vcproj | 8 + .../glib-2.20.1/lib/glib-2.20.1-x86.lib | Bin 1818038 -> 1854532 bytes desmume/src/windows/main.cpp | 4 +- 7 files changed, 1528 insertions(+), 1 deletion(-) create mode 100644 desmume/src/windows/glib-2.20.1/build/glib/gthread/gthread-impl.c create mode 100644 desmume/src/windows/glib-2.20.1/build/glib/gthread/gthread-none.c create mode 100644 desmume/src/windows/glib-2.20.1/build/glib/gthread/gthread-posix.c create mode 100644 desmume/src/windows/glib-2.20.1/build/glib/gthread/gthread-win32.c diff --git a/desmume/src/windows/glib-2.20.1/build/glib/gthread/gthread-impl.c b/desmume/src/windows/glib-2.20.1/build/glib/gthread/gthread-impl.c new file mode 100644 index 000000000..24eb3c48e --- /dev/null +++ b/desmume/src/windows/glib-2.20.1/build/glib/gthread/gthread-impl.c @@ -0,0 +1,372 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * gthread.c: thread related functions + * Copyright 1998 Sebastian Wilhelmi; University of Karlsruhe + * + * This library 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 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * MT safe + */ + +#include "config.h" + +#include "glib.h" +#include "gthreadprivate.h" + +#ifdef G_THREADS_ENABLED + +static GSystemThread zero_thread; /* This is initialized to all zero */ +static gboolean thread_system_already_initialized = FALSE; +static gint g_thread_priority_map [G_THREAD_PRIORITY_URGENT + 1]; + +#include G_THREAD_SOURCE + +#ifndef PRIORITY_LOW_VALUE +# define PRIORITY_LOW_VALUE 0 +#endif + +#ifndef PRIORITY_URGENT_VALUE +# define PRIORITY_URGENT_VALUE 0 +#endif + +#ifndef PRIORITY_NORMAL_VALUE +# define PRIORITY_NORMAL_VALUE \ + ((PRIORITY_LOW_VALUE * 6 + PRIORITY_URGENT_VALUE * 4) / 10) +#endif /* PRIORITY_NORMAL_VALUE */ + +#ifndef PRIORITY_HIGH_VALUE +# define PRIORITY_HIGH_VALUE \ + ((PRIORITY_NORMAL_VALUE + PRIORITY_URGENT_VALUE * 2) / 3) +#endif /* PRIORITY_HIGH_VALUE */ + +void g_mutex_init (void); +void g_mem_init (void); +void g_messages_init (void); +void g_convert_init (void); +void g_rand_init (void); +void g_main_thread_init (void); + +typedef struct _GMutexDebugInfo GMutexDebugInfo; +struct _GMutexDebugInfo +{ + gchar *location; + GSystemThread owner; +}; + +#define G_MUTEX_DEBUG_INFO(mutex) \ + (((GMutexDebugInfo*)(((char*)mutex)+G_MUTEX_SIZE))) + +static GMutex * +g_mutex_new_errorcheck_impl (void) +{ + GMutex *retval = g_thread_functions_for_glib_use_default.mutex_new (); + GMutexDebugInfo *info; + retval = g_realloc (retval, G_MUTEX_SIZE + sizeof (GMutexDebugInfo)); + + info = G_MUTEX_DEBUG_INFO (retval); + g_system_thread_assign (info->owner, zero_thread); + info->location = "invalid"; + + return retval; +} + +static void +g_mutex_lock_errorcheck_impl (GMutex *mutex, + const gulong magic, + gchar * const location) +{ + GMutexDebugInfo *info = G_MUTEX_DEBUG_INFO (mutex); + gchar *loc = (magic == G_MUTEX_DEBUG_MAGIC) ? location : "unknown"; + + GSystemThread self; + g_thread_functions_for_glib_use.thread_self (&self); + + if (g_system_thread_equal (info->owner, self)) + g_error ("Trying to recursivly lock a mutex at '%s', " + "previously locked at '%s'", + loc, info->location); + + g_thread_functions_for_glib_use_default.mutex_lock (mutex); + + g_system_thread_assign (info->owner, self); + info->location = loc; +} + +static gboolean +g_mutex_trylock_errorcheck_impl (GMutex *mutex, + const gulong magic, + gchar * const location) +{ + GMutexDebugInfo *info = G_MUTEX_DEBUG_INFO (mutex); + gchar *loc = (magic == G_MUTEX_DEBUG_MAGIC) ? location : "unknown"; + + GSystemThread self; + g_thread_functions_for_glib_use.thread_self (&self); + + if (g_system_thread_equal (info->owner, self)) + g_error ("Trying to recursivly lock a mutex at '%s', " + "previously locked at '%s'", + loc, info->location); + + if (!g_thread_functions_for_glib_use_default.mutex_trylock (mutex)) + return FALSE; + + g_system_thread_assign (info->owner, self); + info->location = loc; + + return TRUE; +} + +static void +g_mutex_unlock_errorcheck_impl (GMutex *mutex, + const gulong magic, + gchar * const location) +{ + GMutexDebugInfo *info = G_MUTEX_DEBUG_INFO (mutex); + gchar *loc = (magic == G_MUTEX_DEBUG_MAGIC) ? location : "unknown"; + + GSystemThread self; + g_thread_functions_for_glib_use.thread_self (&self); + + if (g_system_thread_equal (info->owner, zero_thread)) + g_error ("Trying to unlock an unlocked mutex at '%s'", loc); + + if (!g_system_thread_equal (info->owner, self)) + g_warning ("Trying to unlock a mutex at '%s', " + "previously locked by a different thread at '%s'", + loc, info->location); + + g_system_thread_assign (info->owner, zero_thread); + info->location = NULL; + + g_thread_functions_for_glib_use_default.mutex_unlock (mutex); +} + +static void +g_mutex_free_errorcheck_impl (GMutex *mutex, + const gulong magic, + gchar * const location) +{ + GMutexDebugInfo *info = G_MUTEX_DEBUG_INFO (mutex); + gchar *loc = (magic == G_MUTEX_DEBUG_MAGIC) ? location : "unknown"; + + if (info && !g_system_thread_equal (info->owner, zero_thread)) + g_error ("Trying to free a locked mutex at '%s', " + "which was previously locked at '%s'", + loc, info->location); + + g_thread_functions_for_glib_use_default.mutex_free (mutex); +} + +static void +g_cond_wait_errorcheck_impl (GCond *cond, + GMutex *mutex, + const gulong magic, + gchar * const location) +{ + GMutexDebugInfo *info = G_MUTEX_DEBUG_INFO (mutex); + gchar *loc = (magic == G_MUTEX_DEBUG_MAGIC) ? location : "unknown"; + + GSystemThread self; + g_thread_functions_for_glib_use.thread_self (&self); + + if (g_system_thread_equal (info->owner, zero_thread)) + g_error ("Trying to use an unlocked mutex in g_cond_wait() at '%s'", loc); + + if (!g_system_thread_equal (info->owner, self)) + g_error ("Trying to use a mutex locked by another thread in " + "g_cond_wait() at '%s'", loc); + + g_system_thread_assign (info->owner, zero_thread); + loc = info->location; + + g_thread_functions_for_glib_use_default.cond_wait (cond, mutex); + + g_system_thread_assign (info->owner, self); + info->location = loc; +} + + +static gboolean +g_cond_timed_wait_errorcheck_impl (GCond *cond, + GMutex *mutex, + GTimeVal *end_time, + const gulong magic, + gchar * const location) +{ + GMutexDebugInfo *info = G_MUTEX_DEBUG_INFO (mutex); + gchar *loc = (magic == G_MUTEX_DEBUG_MAGIC) ? location : "unknown"; + gboolean retval; + + GSystemThread self; + g_thread_functions_for_glib_use.thread_self (&self); + + if (g_system_thread_equal (info->owner, zero_thread)) + g_error ("Trying to use an unlocked mutex in g_cond_timed_wait() at '%s'", + loc); + + if (!g_system_thread_equal (info->owner, self)) + g_error ("Trying to use a mutex locked by another thread in " + "g_cond_timed_wait() at '%s'", loc); + + g_system_thread_assign (info->owner, zero_thread); + loc = info->location; + + retval = g_thread_functions_for_glib_use_default.cond_timed_wait (cond, + mutex, + end_time); + + g_system_thread_assign (info->owner, self); + info->location = loc; + + return retval; +} + + +/* unshadow function declaration. See gthread.h */ +#undef g_thread_init + +void +g_thread_init_with_errorcheck_mutexes (GThreadFunctions* init) +{ + GThreadFunctions errorcheck_functions; + if (init) + g_error ("Errorcheck mutexes can only be used for native " + "thread implementations. Sorry." ); + +#ifdef HAVE_G_THREAD_IMPL_INIT + /* This isn't called in g_thread_init, as it doesn't think to get + * the default implementation, so we have to call it on our own. + * + * We must call this before copying + * g_thread_functions_for_glib_use_default as the + * implementation-specific init function might modify the contents + * of g_thread_functions_for_glib_use_default based on operating + * system version, C library version, or whatever. */ + g_thread_impl_init(); +#endif /* HAVE_G_THREAD_IMPL_INIT */ + + errorcheck_functions = g_thread_functions_for_glib_use_default; + errorcheck_functions.mutex_new = g_mutex_new_errorcheck_impl; + errorcheck_functions.mutex_lock = + (void (*)(GMutex *)) g_mutex_lock_errorcheck_impl; + errorcheck_functions.mutex_trylock = + (gboolean (*)(GMutex *)) g_mutex_trylock_errorcheck_impl; + errorcheck_functions.mutex_unlock = + (void (*)(GMutex *)) g_mutex_unlock_errorcheck_impl; + errorcheck_functions.mutex_free = + (void (*)(GMutex *)) g_mutex_free_errorcheck_impl; + errorcheck_functions.cond_wait = + (void (*)(GCond *, GMutex *)) g_cond_wait_errorcheck_impl; + errorcheck_functions.cond_timed_wait = + (gboolean (*)(GCond *, GMutex *, GTimeVal *)) + g_cond_timed_wait_errorcheck_impl; + + g_thread_init (&errorcheck_functions); +} + +void +g_thread_init (GThreadFunctions* init) +{ + gboolean supported; + + if (thread_system_already_initialized) + g_error ("GThread system may only be initialized once."); + + thread_system_already_initialized = TRUE; + + if (init == NULL) + { +#ifdef HAVE_G_THREAD_IMPL_INIT + /* now do any initialization stuff required by the + * implementation, but only if called with a NULL argument, of + * course. Otherwise it's up to the user to do so. */ + g_thread_impl_init(); +#endif /* HAVE_G_THREAD_IMPL_INIT */ + init = &g_thread_functions_for_glib_use_default; + } + else + g_thread_use_default_impl = FALSE; + + g_thread_functions_for_glib_use = *init; + if (g_thread_gettime_impl) + g_thread_gettime = g_thread_gettime_impl; + + supported = (init->mutex_new && + init->mutex_lock && + init->mutex_trylock && + init->mutex_unlock && + init->mutex_free && + init->cond_new && + init->cond_signal && + init->cond_broadcast && + init->cond_wait && + init->cond_timed_wait && + init->cond_free && + init->private_new && + init->private_get && + init->private_set && + init->thread_create && + init->thread_yield && + init->thread_join && + init->thread_exit && + init->thread_set_priority && + init->thread_self); + + /* if somebody is calling g_thread_init (), it means that he wants to + * have thread support, so check this + */ + if (!supported) + { + if (g_thread_use_default_impl) + g_error ("Threads are not supported on this platform."); + else + g_error ("The supplied thread function vector is invalid."); + } + + g_thread_priority_map [G_THREAD_PRIORITY_LOW] = PRIORITY_LOW_VALUE; + g_thread_priority_map [G_THREAD_PRIORITY_NORMAL] = PRIORITY_NORMAL_VALUE; + g_thread_priority_map [G_THREAD_PRIORITY_HIGH] = PRIORITY_HIGH_VALUE; + g_thread_priority_map [G_THREAD_PRIORITY_URGENT] = PRIORITY_URGENT_VALUE; + + g_thread_init_glib (); +} + +#else /* !G_THREADS_ENABLED */ + +void +g_thread_init (GThreadFunctions* init) +{ + g_error ("GLib thread support is disabled."); +} + +void +g_thread_init_with_errorcheck_mutexes (GThreadFunctions* init) +{ + g_error ("GLib thread support is disabled."); +} + +#endif /* !G_THREADS_ENABLED */ diff --git a/desmume/src/windows/glib-2.20.1/build/glib/gthread/gthread-none.c b/desmume/src/windows/glib-2.20.1/build/glib/gthread/gthread-none.c new file mode 100644 index 000000000..6fbeff160 --- /dev/null +++ b/desmume/src/windows/glib-2.20.1/build/glib/gthread/gthread-none.c @@ -0,0 +1,39 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * gthread.c: fallback thread system implementation + * Copyright 1998 Sebastian Wilhelmi; University of Karlsruhe + * + * This library 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 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * MT safe + */ + +static GThreadFunctions +g_thread_functions_for_glib_use_default; /* is NULLified */ + +static guint64 (*g_thread_gettime_impl) (void) = NULL; + +#define G_MUTEX_SIZE 0 diff --git a/desmume/src/windows/glib-2.20.1/build/glib/gthread/gthread-posix.c b/desmume/src/windows/glib-2.20.1/build/glib/gthread/gthread-posix.c new file mode 100644 index 000000000..9188f843e --- /dev/null +++ b/desmume/src/windows/glib-2.20.1/build/glib/gthread/gthread-posix.c @@ -0,0 +1,467 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * gthread.c: posix thread system implementation + * Copyright 1998 Sebastian Wilhelmi; University of Karlsruhe + * + * This library 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 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * MT safe + */ + +#include "config.h" + +#include +#include +#include +#ifdef HAVE_SYS_TIME_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifdef HAVE_SCHED_H +#include +#endif + +#define posix_check_err(err, name) G_STMT_START{ \ + int error = (err); \ + if (error) \ + g_error ("file %s: line %d (%s): error '%s' during '%s'", \ + __FILE__, __LINE__, G_STRFUNC, \ + g_strerror (error), name); \ + }G_STMT_END + +#define posix_check_cmd(cmd) posix_check_err (posix_error (cmd), #cmd) + +#ifdef G_ENABLE_DEBUG +static gboolean posix_check_cmd_prio_warned = FALSE; +# define posix_check_cmd_prio(cmd) G_STMT_START{ \ + int err = posix_error (cmd); \ + if (err == EPERM) \ + { \ + if (!posix_check_cmd_prio_warned) \ + { \ + posix_check_cmd_prio_warned = TRUE; \ + g_warning ("Priorities can only be changed " \ + "(resp. increased) by root."); \ + } \ + } \ + else \ + posix_check_err (err, #cmd); \ + }G_STMT_END +#else /* G_ENABLE_DEBUG */ +# define posix_check_cmd_prio(cmd) G_STMT_START{ \ + int err = posix_error (cmd); \ + if (err != EPERM) \ + posix_check_err (err, #cmd); \ + }G_STMT_END +#endif /* G_ENABLE_DEBUG */ + +#if defined(G_THREADS_IMPL_POSIX) +# define posix_error(what) (what) +# define mutexattr_default NULL +# define condattr_default NULL +#elif defined(G_THREADS_IMPL_DCE) +# define posix_error(what) ((what) == -1 ? errno : 0) +# define pthread_key_create(a, b) pthread_keycreate (a, b) +# define pthread_attr_init(a) pthread_attr_create (a) +# define pthread_attr_destroy(a) pthread_attr_delete (a) +# define pthread_create(a, b, c, d) pthread_create (a, *b, c, d) +# define mutexattr_default (pthread_mutexattr_default) +# define condattr_default (pthread_condattr_default) +#else /* neither G_THREADS_IMPL_POSIX nor G_THREADS_IMPL_DCE are defined */ +# error This should not happen. Contact the GLib team. +#endif + +#if defined (POSIX_MIN_PRIORITY) && defined (POSIX_MAX_PRIORITY) +# define HAVE_PRIORITIES 1 +static gint priority_normal_value; +# ifdef __FreeBSD__ + /* FreeBSD threads use different priority values from the POSIX_ + * defines so we just set them here. The corresponding macros + * PTHREAD_MIN_PRIORITY and PTHREAD_MAX_PRIORITY are implied to be + * exported by the docs, but they aren't. + */ +# define PRIORITY_LOW_VALUE 0 +# define PRIORITY_URGENT_VALUE 31 +# else /* !__FreeBSD__ */ +# define PRIORITY_LOW_VALUE POSIX_MIN_PRIORITY +# define PRIORITY_URGENT_VALUE POSIX_MAX_PRIORITY +# endif /* !__FreeBSD__ */ +# define PRIORITY_NORMAL_VALUE priority_normal_value +#endif /* POSIX_MIN_PRIORITY && POSIX_MAX_PRIORITY */ + +static gulong g_thread_min_stack_size = 0; + +#define G_MUTEX_SIZE (sizeof (pthread_mutex_t)) + +#if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_MONOTONIC_CLOCK) +#define USE_CLOCK_GETTIME 1 +static gint posix_clock = 0; +#endif + +#if defined(_SC_THREAD_STACK_MIN) || defined (HAVE_PRIORITIES) || defined (USE_CLOCK_GETTIME) +#define HAVE_G_THREAD_IMPL_INIT +static void +g_thread_impl_init(void) +{ +#ifdef _SC_THREAD_STACK_MIN + g_thread_min_stack_size = MAX (sysconf (_SC_THREAD_STACK_MIN), 0); +#endif /* _SC_THREAD_STACK_MIN */ +#ifdef HAVE_PRIORITIES +# ifdef G_THREADS_IMPL_POSIX + { + struct sched_param sched; + int policy; + posix_check_cmd (pthread_getschedparam (pthread_self(), &policy, &sched)); + priority_normal_value = sched.sched_priority; + } +# else /* G_THREADS_IMPL_DCE */ + posix_check_cmd (priority_normal_value = + pthread_getprio (*(pthread_t*)thread, + g_thread_priority_map [priority])); +# endif +#endif /* HAVE_PRIORITIES */ + +#ifdef USE_CLOCK_GETTIME + if (sysconf (_SC_MONOTONIC_CLOCK) >= 0) + posix_clock = CLOCK_MONOTONIC; + else + posix_clock = CLOCK_REALTIME; +#endif +} +#endif /* _SC_THREAD_STACK_MIN || HAVE_PRIORITIES */ + +static GMutex * +g_mutex_new_posix_impl (void) +{ + GMutex *result = (GMutex *) g_new (pthread_mutex_t, 1); + posix_check_cmd (pthread_mutex_init ((pthread_mutex_t *) result, + mutexattr_default)); + return result; +} + +static void +g_mutex_free_posix_impl (GMutex * mutex) +{ + posix_check_cmd (pthread_mutex_destroy ((pthread_mutex_t *) mutex)); + g_free (mutex); +} + +/* NOTE: the functions g_mutex_lock and g_mutex_unlock may not use + functions from gmem.c and gmessages.c; */ + +/* pthread_mutex_lock, pthread_mutex_unlock can be taken directly, as + signature and semantic are right, but without error check then!!!!, + we might want to change this therefore. */ + +static gboolean +g_mutex_trylock_posix_impl (GMutex * mutex) +{ + int result; + + result = pthread_mutex_trylock ((pthread_mutex_t *) mutex); + +#ifdef G_THREADS_IMPL_POSIX + if (result == EBUSY) + return FALSE; +#else /* G_THREADS_IMPL_DCE */ + if (result == 0) + return FALSE; +#endif + + posix_check_err (posix_error (result), "pthread_mutex_trylock"); + return TRUE; +} + +static GCond * +g_cond_new_posix_impl (void) +{ + GCond *result = (GCond *) g_new (pthread_cond_t, 1); + posix_check_cmd (pthread_cond_init ((pthread_cond_t *) result, + condattr_default)); + return result; +} + +/* pthread_cond_signal, pthread_cond_broadcast and pthread_cond_wait + can be taken directly, as signature and semantic are right, but + without error check then!!!!, we might want to change this + therefore. */ + +#define G_NSEC_PER_SEC 1000000000 + +static gboolean +g_cond_timed_wait_posix_impl (GCond * cond, + GMutex * entered_mutex, + GTimeVal * abs_time) +{ + int result; + struct timespec end_time; + gboolean timed_out; + + g_return_val_if_fail (cond != NULL, FALSE); + g_return_val_if_fail (entered_mutex != NULL, FALSE); + + if (!abs_time) + { + result = pthread_cond_wait ((pthread_cond_t *)cond, + (pthread_mutex_t *) entered_mutex); + timed_out = FALSE; + } + else + { + end_time.tv_sec = abs_time->tv_sec; + end_time.tv_nsec = abs_time->tv_usec * (G_NSEC_PER_SEC / G_USEC_PER_SEC); + + g_return_val_if_fail (end_time.tv_nsec < G_NSEC_PER_SEC, TRUE); + + result = pthread_cond_timedwait ((pthread_cond_t *) cond, + (pthread_mutex_t *) entered_mutex, + &end_time); +#ifdef G_THREADS_IMPL_POSIX + timed_out = (result == ETIMEDOUT); +#else /* G_THREADS_IMPL_DCE */ + timed_out = (result == -1) && (errno == EAGAIN); +#endif + } + + if (!timed_out) + posix_check_err (posix_error (result), "pthread_cond_timedwait"); + + return !timed_out; +} + +static void +g_cond_free_posix_impl (GCond * cond) +{ + posix_check_cmd (pthread_cond_destroy ((pthread_cond_t *) cond)); + g_free (cond); +} + +static GPrivate * +g_private_new_posix_impl (GDestroyNotify destructor) +{ + GPrivate *result = (GPrivate *) g_new (pthread_key_t, 1); + posix_check_cmd (pthread_key_create ((pthread_key_t *) result, destructor)); + return result; +} + +/* 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_posix_impl (GPrivate * private_key, gpointer value) +{ + if (!private_key) + return; + pthread_setspecific (*(pthread_key_t *) private_key, value); +} + +static gpointer +g_private_get_posix_impl (GPrivate * private_key) +{ + if (!private_key) + return NULL; +#ifdef G_THREADS_IMPL_POSIX + return pthread_getspecific (*(pthread_key_t *) private_key); +#else /* G_THREADS_IMPL_DCE */ + { + void* data; + posix_check_cmd (pthread_getspecific (*(pthread_key_t *) private_key, + &data)); + return data; + } +#endif +} + +static void +g_thread_create_posix_impl (GThreadFunc thread_func, + gpointer arg, + gulong stack_size, + gboolean joinable, + gboolean bound, + GThreadPriority priority, + gpointer thread, + GError **error) +{ + pthread_attr_t attr; + gint ret; + + g_return_if_fail (thread_func); + g_return_if_fail (priority >= G_THREAD_PRIORITY_LOW); + g_return_if_fail (priority <= G_THREAD_PRIORITY_URGENT); + + posix_check_cmd (pthread_attr_init (&attr)); + +#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE + if (stack_size) + { + stack_size = MAX (g_thread_min_stack_size, stack_size); + /* No error check here, because some systems can't do it and + * we simply don't want threads to fail because of that. */ + pthread_attr_setstacksize (&attr, stack_size); + } +#endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */ + +#ifdef PTHREAD_SCOPE_SYSTEM + if (bound) + /* No error check here, because some systems can't do it and we + * simply don't want threads to fail because of that. */ + pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); +#endif /* PTHREAD_SCOPE_SYSTEM */ + +#ifdef G_THREADS_IMPL_POSIX + posix_check_cmd (pthread_attr_setdetachstate (&attr, + joinable ? PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED)); +#endif /* G_THREADS_IMPL_POSIX */ + +#ifdef HAVE_PRIORITIES +# ifdef G_THREADS_IMPL_POSIX + { + struct sched_param sched; + posix_check_cmd (pthread_attr_getschedparam (&attr, &sched)); + sched.sched_priority = g_thread_priority_map [priority]; + posix_check_cmd_prio (pthread_attr_setschedparam (&attr, &sched)); + } +# else /* G_THREADS_IMPL_DCE */ + posix_check_cmd_prio + (pthread_attr_setprio (&attr, g_thread_priority_map [priority])); +# endif /* G_THREADS_IMPL_DCE */ +#endif /* HAVE_PRIORITIES */ + ret = posix_error (pthread_create (thread, &attr, + (void* (*)(void*))thread_func, arg)); + + posix_check_cmd (pthread_attr_destroy (&attr)); + + if (ret == EAGAIN) + { + g_set_error (error, G_THREAD_ERROR, G_THREAD_ERROR_AGAIN, + "Error creating thread: %s", g_strerror (ret)); + return; + } + + posix_check_err (ret, "pthread_create"); + +#ifdef G_THREADS_IMPL_DCE + if (!joinable) + posix_check_cmd (pthread_detach (thread)); +#endif /* G_THREADS_IMPL_DCE */ +} + +static void +g_thread_yield_posix_impl (void) +{ + POSIX_YIELD_FUNC; +} + +static void +g_thread_join_posix_impl (gpointer thread) +{ + gpointer ignore; + posix_check_cmd (pthread_join (*(pthread_t*)thread, &ignore)); +} + +static void +g_thread_exit_posix_impl (void) +{ + pthread_exit (NULL); +} + +static void +g_thread_set_priority_posix_impl (gpointer thread, GThreadPriority priority) +{ + g_return_if_fail (priority >= G_THREAD_PRIORITY_LOW); + g_return_if_fail (priority <= G_THREAD_PRIORITY_URGENT); +#ifdef HAVE_PRIORITIES +# ifdef G_THREADS_IMPL_POSIX + { + struct sched_param sched; + int policy; + posix_check_cmd (pthread_getschedparam (*(pthread_t*)thread, &policy, + &sched)); + sched.sched_priority = g_thread_priority_map [priority]; + posix_check_cmd_prio (pthread_setschedparam (*(pthread_t*)thread, policy, + &sched)); + } +# else /* G_THREADS_IMPL_DCE */ + posix_check_cmd_prio (pthread_setprio (*(pthread_t*)thread, + g_thread_priority_map [priority])); +# endif +#endif /* HAVE_PRIORITIES */ +} + +static void +g_thread_self_posix_impl (gpointer thread) +{ + *(pthread_t*)thread = pthread_self(); +} + +static gboolean +g_thread_equal_posix_impl (gpointer thread1, gpointer thread2) +{ + return (pthread_equal (*(pthread_t*)thread1, *(pthread_t*)thread2) != 0); +} + +#ifdef USE_CLOCK_GETTIME +static guint64 +gettime (void) +{ + struct timespec tv; + + clock_gettime (posix_clock, &tv); + + return (guint64) tv.tv_sec * G_NSEC_PER_SEC + tv.tv_nsec; +} +static guint64 (*g_thread_gettime_impl)(void) = gettime; +#else +static guint64 (*g_thread_gettime_impl)(void) = 0; +#endif + +static GThreadFunctions g_thread_functions_for_glib_use_default = +{ + g_mutex_new_posix_impl, + (void (*)(GMutex *)) pthread_mutex_lock, + g_mutex_trylock_posix_impl, + (void (*)(GMutex *)) pthread_mutex_unlock, + g_mutex_free_posix_impl, + g_cond_new_posix_impl, + (void (*)(GCond *)) pthread_cond_signal, + (void (*)(GCond *)) pthread_cond_broadcast, + (void (*)(GCond *, GMutex *)) pthread_cond_wait, + g_cond_timed_wait_posix_impl, + g_cond_free_posix_impl, + g_private_new_posix_impl, + g_private_get_posix_impl, + g_private_set_posix_impl, + g_thread_create_posix_impl, + g_thread_yield_posix_impl, + g_thread_join_posix_impl, + g_thread_exit_posix_impl, + g_thread_set_priority_posix_impl, + g_thread_self_posix_impl, + g_thread_equal_posix_impl +}; diff --git a/desmume/src/windows/glib-2.20.1/build/glib/gthread/gthread-win32.c b/desmume/src/windows/glib-2.20.1/build/glib/gthread/gthread-win32.c new file mode 100644 index 000000000..465b20550 --- /dev/null +++ b/desmume/src/windows/glib-2.20.1/build/glib/gthread/gthread-win32.c @@ -0,0 +1,639 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * gthread.c: solaris thread system implementation + * Copyright 1998-2001 Sebastian Wilhelmi; University of Karlsruhe + * Copyright 2001 Hans Breuer + * + * This library 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 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * MT safe + */ + +#include "config.h" + +#include "glib.h" + +#define STRICT +#define _WIN32_WINDOWS 0x0401 /* to get IsDebuggerPresent */ +#include +#undef STRICT + +#include +#include +#include + +#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)) + +#define PRIORITY_LOW_VALUE THREAD_PRIORITY_BELOW_NORMAL +#define PRIORITY_NORMAL_VALUE THREAD_PRIORITY_NORMAL +#define PRIORITY_HIGH_VALUE THREAD_PRIORITY_ABOVE_NORMAL +#define PRIORITY_URGENT_VALUE THREAD_PRIORITY_HIGHEST + +static DWORD g_thread_self_tls; +static DWORD g_private_tls; +static DWORD g_cond_event_tls; +static CRITICAL_SECTION g_thread_global_spinlock; + +typedef BOOL (__stdcall *GTryEnterCriticalSectionFunc) (CRITICAL_SECTION *); + +static GTryEnterCriticalSectionFunc try_enter_critical_section = NULL; + +/* 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 + +static GDestroyNotify g_private_destructors[G_PRIVATE_MAX]; + +static guint g_private_next = 0; + +/* A "forward" declaration of this structure */ +static GThreadFunctions g_thread_functions_for_glib_use_default; + +typedef struct _GThreadData GThreadData; +struct _GThreadData +{ + GThreadFunc func; + gpointer data; + HANDLE thread; + gboolean joinable; +}; + +struct _GCond +{ + GPtrArray *array; + CRITICAL_SECTION lock; +}; + +static GMutex * +g_mutex_new_win32_cs_impl (void) +{ + CRITICAL_SECTION *cs = g_new (CRITICAL_SECTION, 1); + gpointer *retval = g_new (gpointer, 1); + + InitializeCriticalSection (cs); + *retval = cs; + return (GMutex *) retval; +} + +static void +g_mutex_free_win32_cs_impl (GMutex *mutex) +{ + gpointer *ptr = (gpointer *) mutex; + CRITICAL_SECTION *cs = (CRITICAL_SECTION *) *ptr; + + DeleteCriticalSection (cs); + g_free (cs); + g_free (mutex); +} + +/* NOTE: the functions g_mutex_lock and g_mutex_unlock may not use + functions from gmem.c and gmessages.c; */ + +static void +g_mutex_lock_win32_cs_impl (GMutex *mutex) +{ + EnterCriticalSection (*(CRITICAL_SECTION **)mutex); +} + +static gboolean +g_mutex_trylock_win32_cs_impl (GMutex * mutex) +{ + return try_enter_critical_section (*(CRITICAL_SECTION **)mutex); +} + +static void +g_mutex_unlock_win32_cs_impl (GMutex *mutex) +{ + LeaveCriticalSection (*(CRITICAL_SECTION **)mutex); +} + +static GMutex * +g_mutex_new_win32_impl (void) +{ + HANDLE handle; + HANDLE *retval; + win32_check_for_error (handle = CreateMutex (NULL, FALSE, NULL)); + retval = g_new (HANDLE, 1); + *retval = handle; + return (GMutex *) retval; +} + +static void +g_mutex_free_win32_impl (GMutex *mutex) +{ + win32_check_for_error (CloseHandle (*(HANDLE *) mutex)); + g_free (mutex); +} + +/* NOTE: the functions g_mutex_lock and g_mutex_unlock may not use + functions from gmem.c and gmessages.c; */ + +static void +g_mutex_lock_win32_impl (GMutex *mutex) +{ + WaitForSingleObject (*(HANDLE *) mutex, INFINITE); +} + +static gboolean +g_mutex_trylock_win32_impl (GMutex * mutex) +{ + DWORD result; + win32_check_for_error (WAIT_FAILED != + (result = WaitForSingleObject (*(HANDLE *)mutex, 0))); + return result != WAIT_TIMEOUT; +} + +static void +g_mutex_unlock_win32_impl (GMutex *mutex) +{ + ReleaseMutex (*(HANDLE *) mutex); +} + +static GCond * +g_cond_new_win32_impl (void) +{ + GCond *retval = g_new (GCond, 1); + + retval->array = g_ptr_array_new (); + InitializeCriticalSection (&retval->lock); + + return retval; +} + +static void +g_cond_signal_win32_impl (GCond * cond) +{ + EnterCriticalSection (&cond->lock); + + if (cond->array->len > 0) + { + SetEvent (g_ptr_array_index (cond->array, 0)); + g_ptr_array_remove_index (cond->array, 0); + } + + LeaveCriticalSection (&cond->lock); +} + +static void +g_cond_broadcast_win32_impl (GCond * cond) +{ + guint i; + EnterCriticalSection (&cond->lock); + + for (i = 0; i < cond->array->len; i++) + SetEvent (g_ptr_array_index (cond->array, i)); + + g_ptr_array_set_size (cond->array, 0); + LeaveCriticalSection (&cond->lock); +} + +static gboolean +g_cond_wait_internal (GCond *cond, + GMutex *entered_mutex, + gulong milliseconds) +{ + gulong retval; + HANDLE event = TlsGetValue (g_cond_event_tls); + + if (!event) + { + win32_check_for_error (event = CreateEvent (0, FALSE, FALSE, NULL)); + TlsSetValue (g_cond_event_tls, event); + } + + EnterCriticalSection (&cond->lock); + + /* The event must not be signaled. Check this */ + g_assert (WaitForSingleObject (event, 0) == WAIT_TIMEOUT); + + g_ptr_array_add (cond->array, event); + LeaveCriticalSection (&cond->lock); + + g_thread_functions_for_glib_use_default.mutex_unlock (entered_mutex); + + win32_check_for_error (WAIT_FAILED != + (retval = WaitForSingleObject (event, milliseconds))); + + g_thread_functions_for_glib_use_default.mutex_lock (entered_mutex); + + if (retval == WAIT_TIMEOUT) + { + EnterCriticalSection (&cond->lock); + g_ptr_array_remove (cond->array, event); + + /* In the meantime we could have been signaled, so we must again + * wait for the signal, this time with no timeout, to reset + * it. retval is set again to honour the late arrival of the + * signal */ + win32_check_for_error (WAIT_FAILED != + (retval = WaitForSingleObject (event, 0))); + + LeaveCriticalSection (&cond->lock); + } + +#ifndef G_DISABLE_ASSERT + EnterCriticalSection (&cond->lock); + + /* Now event must not be inside the array, check this */ + g_assert (g_ptr_array_remove (cond->array, event) == FALSE); + + LeaveCriticalSection (&cond->lock); +#endif /* !G_DISABLE_ASSERT */ + + return retval != WAIT_TIMEOUT; +} + +static void +g_cond_wait_win32_impl (GCond *cond, + GMutex *entered_mutex) +{ + g_return_if_fail (cond != NULL); + g_return_if_fail (entered_mutex != NULL); + + g_cond_wait_internal (cond, entered_mutex, INFINITE); +} + +static gboolean +g_cond_timed_wait_win32_impl (GCond *cond, + GMutex *entered_mutex, + GTimeVal *abs_time) +{ + GTimeVal current_time; + gulong to_wait; + + g_return_val_if_fail (cond != NULL, FALSE); + g_return_val_if_fail (entered_mutex != NULL, FALSE); + + if (!abs_time) + to_wait = INFINITE; + else + { + g_get_current_time (¤t_time); + if (abs_time->tv_sec < current_time.tv_sec || + (abs_time->tv_sec == current_time.tv_sec && + abs_time->tv_usec <= current_time.tv_usec)) + to_wait = 0; + else + to_wait = (abs_time->tv_sec - current_time.tv_sec) * 1000 + + (abs_time->tv_usec - current_time.tv_usec) / 1000; + } + + return g_cond_wait_internal (cond, entered_mutex, to_wait); +} + +static void +g_cond_free_win32_impl (GCond * cond) +{ + DeleteCriticalSection (&cond->lock); + g_ptr_array_free (cond->array, TRUE); + g_free (cond); +} + +static GPrivate * +g_private_new_win32_impl (GDestroyNotify destructor) +{ + 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); + + return result; +} + +/* 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) +{ + gpointer* array = TlsGetValue (g_private_tls); + guint index = GPOINTER_TO_UINT (private_key); + + if (index >= G_PRIVATE_MAX) + return; + + if (!array) + { + array = (gpointer*) calloc (G_PRIVATE_MAX, sizeof (gpointer)); + TlsSetValue (g_private_tls, array); + } + + 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]; +} + +static void +g_thread_set_priority_win32_impl (gpointer thread, GThreadPriority priority) +{ + GThreadData *target = *(GThreadData **)thread; + + g_return_if_fail (priority >= G_THREAD_PRIORITY_LOW); + g_return_if_fail (priority <= G_THREAD_PRIORITY_URGENT); + + win32_check_for_error (SetThreadPriority (target->thread, + g_thread_priority_map [priority])); +} + +static void +g_thread_self_win32_impl (gpointer thread) +{ + GThreadData *self = TlsGetValue (g_thread_self_tls); + + if (!self) + { + /* This should only happen for the main thread! */ + HANDLE handle = GetCurrentThread (); + HANDLE process = GetCurrentProcess (); + self = g_new (GThreadData, 1); + win32_check_for_error (DuplicateHandle (process, handle, process, + &self->thread, 0, FALSE, + DUPLICATE_SAME_ACCESS)); + win32_check_for_error (TlsSetValue (g_thread_self_tls, self)); + self->func = NULL; + self->data = NULL; + self->joinable = FALSE; + } + + *(GThreadData **)thread = self; +} + +static void +g_thread_exit_win32_impl (void) +{ + GThreadData *self = TlsGetValue (g_thread_self_tls); + guint i, private_max; + gpointer *array = TlsGetValue (g_private_tls); + HANDLE event = TlsGetValue (g_cond_event_tls); + + EnterCriticalSection (&g_thread_global_spinlock); + private_max = g_private_next; + LeaveCriticalSection (&g_thread_global_spinlock); + + if (array) + { + 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)); + } + + if (self) + { + if (!self->joinable) + { + win32_check_for_error (CloseHandle (self->thread)); + g_free (self); + } + win32_check_for_error (TlsSetValue (g_thread_self_tls, NULL)); + } + + if (event) + { + CloseHandle (event); + win32_check_for_error (TlsSetValue (g_cond_event_tls, NULL)); + } + + _endthreadex (0); +} + +static guint __stdcall +g_thread_proxy (gpointer data) +{ + GThreadData *self = (GThreadData*) data; + + win32_check_for_error (TlsSetValue (g_thread_self_tls, self)); + + self->func (self->data); + + g_thread_exit_win32_impl (); + + 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) +{ + 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; + retval->data = data; + + retval->joinable = joinable; + + retval->thread = (HANDLE) _beginthreadex (NULL, stack_size, g_thread_proxy, + retval, 0, &ignore); + + if (retval->thread == NULL) + { + gchar *win_error = g_win32_error_message (GetLastError ()); + g_set_error (error, G_THREAD_ERROR, G_THREAD_ERROR_AGAIN, + "Error creating thread: %s", win_error); + g_free (retval); + g_free (win_error); + return; + } + + *(GThreadData **)thread = retval; + + g_thread_set_priority_win32_impl (thread, priority); +} + +static void +g_thread_yield_win32_impl (void) +{ + Sleep(0); +} + +static void +g_thread_join_win32_impl (gpointer thread) +{ + GThreadData *target = *(GThreadData **)thread; + + g_return_if_fail (target->joinable); + + win32_check_for_error (WAIT_FAILED != + WaitForSingleObject (target->thread, INFINITE)); + + win32_check_for_error (CloseHandle (target->thread)); + g_free (target); +} + +static guint64 +g_thread_gettime_impl (void) +{ + guint64 v; + + /* Returns 100s of nanoseconds since start of 1601 */ + GetSystemTimeAsFileTime ((FILETIME *)&v); + + /* Offset to Unix epoch */ + v -= G_GINT64_CONSTANT (116444736000000000); + /* Convert to nanoseconds */ + v *= 100; + + return v; +} + +static GThreadFunctions g_thread_functions_for_glib_use_default = +{ + g_mutex_new_win32_impl, /* mutex */ + g_mutex_lock_win32_impl, + g_mutex_trylock_win32_impl, + g_mutex_unlock_win32_impl, + g_mutex_free_win32_impl, + g_cond_new_win32_impl, /* condition */ + g_cond_signal_win32_impl, + g_cond_broadcast_win32_impl, + g_cond_wait_win32_impl, + g_cond_timed_wait_win32_impl, + g_cond_free_win32_impl, + 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 */ +}; + +#define HAVE_G_THREAD_IMPL_INIT +static void +g_thread_impl_init () +{ + static gboolean beenhere = FALSE; + HMODULE kernel32; + + if (beenhere) + return; + + beenhere = TRUE; + + 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 ())); + win32_check_for_error (TLS_OUT_OF_INDEXES != + (g_cond_event_tls = TlsAlloc ())); + InitializeCriticalSection (&g_thread_global_spinlock); + + /* Here we are looking for TryEnterCriticalSection in KERNEL32.DLL, + * if it is found, we can use the in general faster critical + * sections instead of mutexes. See + * http://world.std.com/~jmhart/csmutx.htm for some discussion. + */ + kernel32 = GetModuleHandle ("KERNEL32.DLL"); + if (kernel32) + { + try_enter_critical_section = (GTryEnterCriticalSectionFunc) + GetProcAddress(kernel32, "TryEnterCriticalSection"); + + /* Even if TryEnterCriticalSection is found, it is not + * necessarily working..., we have to check it */ + if (try_enter_critical_section && + try_enter_critical_section (&g_thread_global_spinlock)) + { + LeaveCriticalSection (&g_thread_global_spinlock); + + g_thread_functions_for_glib_use_default.mutex_new = + g_mutex_new_win32_cs_impl; + g_thread_functions_for_glib_use_default.mutex_lock = + g_mutex_lock_win32_cs_impl; + g_thread_functions_for_glib_use_default.mutex_trylock = + g_mutex_trylock_win32_cs_impl; + g_thread_functions_for_glib_use_default.mutex_unlock = + g_mutex_unlock_win32_cs_impl; + g_thread_functions_for_glib_use_default.mutex_free = + g_mutex_free_win32_cs_impl; + } + } +} diff --git a/desmume/src/windows/glib-2.20.1/build/vs8/glib.vcproj b/desmume/src/windows/glib-2.20.1/build/vs8/glib.vcproj index 0a261c6a4..0bfb0368e 100644 --- a/desmume/src/windows/glib-2.20.1/build/vs8/glib.vcproj +++ b/desmume/src/windows/glib-2.20.1/build/vs8/glib.vcproj @@ -300,6 +300,14 @@ > + + + + diff --git a/desmume/src/windows/glib-2.20.1/lib/glib-2.20.1-x86.lib b/desmume/src/windows/glib-2.20.1/lib/glib-2.20.1-x86.lib index 495ae9be11bdc0c08ff33f9570989ef4d9a20210..2327f8aee060d8fc608bc3cbdd97c81a20cc31fe 100644 GIT binary patch delta 50562 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 TL-f~+XR0?gdS?dz#PojvQ2SQ! delta 24389 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 #include #include +#include "gthread.h" #include "version.h" #include "CWindow.h" #include "../MMU.h" @@ -1717,13 +1718,14 @@ int WINAPI WinMain (HINSTANCE hThisInstance, int nFunsterStil) { + g_thread_init (NULL); hAppInst=hThisInstance; OpenConsole(); // Init debug console int ret = _main(); CloseConsole(); - + return ret; }