X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=glib%2Fgthread-win32.c;h=275ecc63c552abbf9d8f135e9343651e2a7ba460;hb=2a53b4d0e2c98a14aedf31e38f0ad1fb2e8fe26f;hp=c8af9c82796640d033f08937885acae02c2431b8;hpb=67e28068e14428afe8335a1503ea7d734419326d;p=platform%2Fupstream%2Fglib.git diff --git a/glib/gthread-win32.c b/glib/gthread-win32.c index c8af9c8..275ecc6 100644 --- a/glib/gthread-win32.c +++ b/glib/gthread-win32.c @@ -16,9 +16,7 @@ * 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. + * License along with this library; if not, see . */ /* @@ -42,6 +40,8 @@ #include "config.h" +#include "glib.h" +#include "glib-init.h" #include "gthread.h" #include "gthreadprivate.h" #include "gslice.h" @@ -301,21 +301,13 @@ g_cond_wait (GCond *cond, } gboolean -g_cond_timedwait (GCond *cond, - GMutex *entered_mutex, - gint64 abs_time) +g_cond_wait_until (GCond *cond, + GMutex *entered_mutex, + gint64 end_time) { gint64 span; - FILETIME ft; - gint64 now; - - GetSystemTimeAsFileTime (&ft); - memmove (&now, &ft, sizeof (FILETIME)); - now -= G_GINT64_CONSTANT (116444736000000000); - now /= 10; - - span = abs_time - now; + span = end_time - g_get_monotonic_time (); if G_UNLIKELY (span < 0) span = 0; @@ -326,28 +318,6 @@ g_cond_timedwait (GCond *cond, return g_thread_impl_vtable.SleepConditionVariableSRW (cond, entered_mutex, span / 1000, 0); } -gboolean -g_cond_timed_wait (GCond *cond, - GMutex *entered_mutex, - GTimeVal *abs_time) -{ - if (abs_time) - { - gint64 micros; - - micros = abs_time->tv_sec; - micros *= 1000000; - micros += abs_time->tv_usec; - - return g_cond_timedwait (cond, entered_mutex, micros); - } - else - { - g_cond_wait (cond, entered_mutex); - return TRUE; - } -} - /* {{{1 GPrivate */ typedef struct _GPrivateDestructor GPrivateDestructor; @@ -438,9 +408,6 @@ g_private_replace (GPrivate *key, /* {{{1 GThread */ -#include "glib.h" -#include "gthreadprivate.h" - #define win32_check_for_error(what) G_STMT_START{ \ if (!(what)) \ g_error ("file %s: line %d (%s): error %s during %s", \ @@ -450,23 +417,23 @@ g_private_replace (GPrivate *key, #define G_MUTEX_SIZE (sizeof (gpointer)) -static DWORD g_thread_self_tls; - typedef BOOL (__stdcall *GTryEnterCriticalSectionFunc) (CRITICAL_SECTION *); -typedef struct _GThreadData GThreadData; -struct _GThreadData +typedef struct { - GThreadFunc func; - gpointer data; - HANDLE thread; - gboolean joinable; -}; + GRealThread thread; + + GThreadFunc proxy; + HANDLE handle; +} GThreadWin32; void g_system_thread_free (GRealThread *thread) { - g_slice_free (GRealThread, thread); + GThreadWin32 *wt = (GThreadWin32 *) thread; + + win32_check_for_error (CloseHandle (wt->handle)); + g_slice_free (GThreadWin32, wt); } void @@ -478,11 +445,9 @@ g_system_thread_exit (void) static guint __stdcall g_thread_win32_proxy (gpointer data) { - GThreadData *self = (GThreadData*) data; + GThreadWin32 *self = data; - win32_check_for_error (TlsSetValue (g_thread_self_tls, self)); - - self->func (self->data); + self->proxy (self); g_system_thread_exit (); @@ -494,37 +459,27 @@ g_thread_win32_proxy (gpointer data) GRealThread * g_system_thread_new (GThreadFunc func, gulong stack_size, - gboolean joinable, GError **error) { - GRealThread *thread; + GThreadWin32 *thread; guint ignore; - GThreadData *retval; - - thread = g_slice_new0 (GRealThread); - retval = g_new(GThreadData, 1); - retval->func = func; - retval->data = thread; - retval->joinable = joinable; + thread = g_slice_new0 (GThreadWin32); + thread->proxy = func; - retval->thread = (HANDLE) _beginthreadex (NULL, stack_size, g_thread_win32_proxy, - retval, 0, &ignore); + thread->handle = (HANDLE) _beginthreadex (NULL, stack_size, g_thread_win32_proxy, thread, 0, &ignore); - if (retval->thread == NULL) + if (thread->handle == 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); - g_slice_free (GRealThread, thread); + g_slice_free (GThreadWin32, thread); return NULL; } - *(GThreadData **) &(thread->system_thread) = retval; - - return thread; + return (GRealThread *) thread; } void @@ -536,15 +491,9 @@ g_thread_yield (void) void g_system_thread_wait (GRealThread *thread) { - GThreadData *target = *(GThreadData **)&(thread->system_thread); - - g_return_if_fail (target->joinable); + GThreadWin32 *wt = (GThreadWin32 *) thread; - win32_check_for_error (WAIT_FAILED != - WaitForSingleObject (target->thread, INFINITE)); - - win32_check_for_error (CloseHandle (target->thread)); - g_free (target); + win32_check_for_error (WAIT_FAILED != WaitForSingleObject (wt->handle, INFINITE)); } void @@ -562,8 +511,9 @@ static DWORD g_thread_xp_waiter_tls; typedef struct _GThreadXpWaiter GThreadXpWaiter; struct _GThreadXpWaiter { - HANDLE event; - volatile GThreadXpWaiter *next; + HANDLE event; + volatile GThreadXpWaiter *next; + volatile GThreadXpWaiter **my_owner; }; static GThreadXpWaiter * @@ -581,6 +531,7 @@ g_thread_xp_waiter_get (void) waiter->event = CreateEvent (0, FALSE, FALSE, NULL); if (waiter->event == NULL) g_thread_abort (GetLastError (), "CreateEvent"); + waiter->my_owner = NULL; TlsSetValue (g_thread_xp_waiter_tls, waiter); } @@ -653,15 +604,20 @@ g_thread_xp_get_srwlock (GThreadSRWLock * volatile *lock) { EnterCriticalSection (&g_thread_xp_lock); - result = malloc (sizeof (GThreadSRWLock)); - + /* Check again */ + result = *lock; if (result == NULL) - g_thread_abort (errno, "malloc"); + { + result = malloc (sizeof (GThreadSRWLock)); + + if (result == NULL) + g_thread_abort (errno, "malloc"); - InitializeCriticalSection (&result->writer_lock); - result->writer_locked = FALSE; - result->ever_shared = FALSE; - *lock = result; + InitializeCriticalSection (&result->writer_lock); + result->writer_locked = FALSE; + result->ever_shared = FALSE; + *lock = result; + } LeaveCriticalSection (&g_thread_xp_lock); } @@ -885,6 +841,7 @@ g_thread_xp_SleepConditionVariableSRW (gpointer cond, waiter->next = NULL; EnterCriticalSection (&g_thread_xp_lock); + waiter->my_owner = cv->last_ptr; *cv->last_ptr = waiter; cv->last_ptr = &waiter->next; LeaveCriticalSection (&g_thread_xp_lock); @@ -894,9 +851,23 @@ g_thread_xp_SleepConditionVariableSRW (gpointer cond, if (status != WAIT_TIMEOUT && status != WAIT_OBJECT_0) g_thread_abort (GetLastError (), "WaitForSingleObject"); - g_mutex_lock (mutex); + if (status == WAIT_TIMEOUT) + { + EnterCriticalSection (&g_thread_xp_lock); + if (waiter->my_owner) + { + if (waiter->next) + waiter->next->my_owner = waiter->my_owner; + else + cv->last_ptr = waiter->my_owner; + *waiter->my_owner = waiter->next; + waiter->my_owner = NULL; + } + LeaveCriticalSection (&g_thread_xp_lock); + } + return status == WAIT_OBJECT_0; } @@ -907,17 +878,22 @@ g_thread_xp_WakeConditionVariable (gpointer cond) volatile GThreadXpWaiter *waiter; EnterCriticalSection (&g_thread_xp_lock); + waiter = cv->first; if (waiter != NULL) { + waiter->my_owner = NULL; cv->first = waiter->next; - if (cv->first == NULL) + if (cv->first != NULL) + cv->first->my_owner = &cv->first; + else cv->last_ptr = &cv->first; } - LeaveCriticalSection (&g_thread_xp_lock); if (waiter != NULL) SetEvent (waiter->event); + + LeaveCriticalSection (&g_thread_xp_lock); } static void __stdcall @@ -927,10 +903,10 @@ g_thread_xp_WakeAllConditionVariable (gpointer cond) volatile GThreadXpWaiter *waiter; EnterCriticalSection (&g_thread_xp_lock); + waiter = cv->first; cv->first = NULL; cv->last_ptr = &cv->first; - LeaveCriticalSection (&g_thread_xp_lock); while (waiter != NULL) { @@ -938,8 +914,11 @@ g_thread_xp_WakeAllConditionVariable (gpointer cond) next = waiter->next; SetEvent (waiter->event); + waiter->my_owner = NULL; waiter = next; } + + LeaveCriticalSection (&g_thread_xp_lock); } /* {{{2 XP Setup */ @@ -1002,25 +981,18 @@ g_thread_lookup_native_funcs (void) return TRUE; } -G_GNUC_INTERNAL void +void g_thread_win32_init (void) { - 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 (); - } + if (!g_thread_lookup_native_funcs ()) + g_thread_xp_init (); - win32_check_for_error (TLS_OUT_OF_INDEXES != (g_thread_self_tls = TlsAlloc ())); InitializeCriticalSection (&g_private_lock); } -G_GNUC_INTERNAL void +void g_thread_win32_thread_detach (void) { - GThreadData *self = TlsGetValue (g_thread_self_tls); gboolean dtors_called; do @@ -1052,16 +1024,6 @@ g_thread_win32_thread_detach (void) } while (dtors_called); - 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 (g_thread_impl_vtable.CallThisOnThreadExit) g_thread_impl_vtable.CallThisOnThreadExit (); }