// -*- c++ -*-
// win32-threads.h - Defines for using Win32 threads.
-/* Copyright (C) 1998, 1999, 2000 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2006 Free Software
+ Foundation
This file is part of libgcj.
#ifndef __JV_WIN32_THREADS__
#define __JV_WIN32_THREADS__
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
//
// Typedefs.
//
-typedef HANDLE _Jv_ConditionVariable_t;
-typedef HANDLE _Jv_Mutex_t;
-
typedef struct
{
- int flags; // Flags are defined in implementation.
- HANDLE handle; // Actual handle to the thread
-} _Jv_Thread_t;
+ // ev[0] (signal) is a Win32 auto-reset event for _Jv_CondNotify
+ // ev[1] (broadcast) is a Win32 manual-reset event for _Jv_CondNotifyAll
+ HANDLE ev[2];
-typedef void _Jv_ThreadStartFunc (java::lang::Thread *);
+ // Number of threads waiting on this condition variable
+ int blocked_count;
-//
-// Condition variables.
-//
+ // Protects access to the blocked_count variable
+ CRITICAL_SECTION count_mutex;
+
+} _Jv_ConditionVariable_t;
-inline void
-_Jv_CondInit (_Jv_ConditionVariable_t *cv)
+typedef struct
{
- *cv = CreateEvent (NULL, 0, 0, NULL);
-}
+ // The thread-id of the owner thread if any, 0 otherwise
+ DWORD owner;
-#define _Jv_HaveCondDestroy
+ // Track nested mutex acquisitions by the same thread
+ int refcount;
+
+ // The actual Windows construct used to implement this mutex
+ CRITICAL_SECTION cs;
+
+} _Jv_Mutex_t;
-inline void
-_Jv_CondDestroy (_Jv_ConditionVariable_t *cv)
+typedef struct _Jv_Thread_t
{
- CloseHandle (*cv);
- cv = NULL;
-}
+ int flags; // Flags are defined in implementation.
+ HANDLE handle; // Actual handle to the thread
+
+ // Protects access to the thread's interrupt_flag and
+ // interrupt_event variables within this module.
+ CRITICAL_SECTION interrupt_mutex;
+
+ // A Win32 auto-reset event for thread interruption
+ HANDLE interrupt_event;
-int _Jv_CondWait (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu,
- jlong millis, jint nanos);
+ java::lang::Thread *thread_obj;
+} _Jv_Thread_t;
-inline int
-_Jv_CondNotify (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *)
+typedef DWORD _Jv_ThreadId_t;
+
+inline _Jv_ThreadId_t
+_Jv_ThreadSelf (void)
{
- return PulseEvent (*cv) ? 0 : GetLastError (); // FIXME: Map error code?
+ return GetCurrentThreadId();
}
-inline int
-_Jv_CondNotifyAll (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *)
+typedef void _Jv_ThreadStartFunc (java::lang::Thread *);
+
+// Type identifying a win32 thread.
+typedef HANDLE _Jv_ThreadDesc_t;
+
+inline _Jv_ThreadDesc_t
+_Jv_GetPlatformThreadID(_Jv_Thread_t *t)
{
- return PulseEvent (*cv) ? 0 : GetLastError (); // FIXME: Map error code?
+ return t->handle;
}
+//
+// Condition variables.
+//
+
+#define _Jv_HaveCondDestroy
+int _Jv_CondWait (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu, jlong millis, jint nanos);
+void _Jv_CondInit (_Jv_ConditionVariable_t *cv);
+void _Jv_CondDestroy (_Jv_ConditionVariable_t *cv);
+int _Jv_CondNotify (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *);
+int _Jv_CondNotifyAll (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *);
+
//
// Mutexes.
+// We use CRITICAL_SECTIONs instead of CreateMutex() for better performance
//
-inline void
-_Jv_MutexInit (_Jv_Mutex_t *mu)
+// Returns 0 if the mutex lock is held by the current thread, and 1 otherwise.
+inline int _Jv_MutexCheckMonitor (_Jv_Mutex_t *mu)
{
- *mu = CreateMutex (NULL, 0, NULL);
+ return (mu->owner != GetCurrentThreadId ( ));
}
-#define _Jv_HaveMutexDestroy
+inline void _Jv_MutexInit (_Jv_Mutex_t *mu)
+{
+ mu->owner = 0UL;
+ mu->refcount = 0;
+ InitializeCriticalSection (&(mu->cs));
+}
-inline void
-_Jv_MutexDestroy (_Jv_Mutex_t *mu)
+#define _Jv_HaveMutexDestroy
+inline void _Jv_MutexDestroy (_Jv_Mutex_t *mu)
{
- CloseHandle (*mu);
+ mu->owner = 0UL;
+ mu->refcount = 0;
+ DeleteCriticalSection (&(mu->cs));
mu = NULL;
}
-int _Jv_MutexLock (_Jv_Mutex_t *mu);
+inline int _Jv_MutexUnlock (_Jv_Mutex_t *mu)
+{
+ if (mu->owner == GetCurrentThreadId ( ))
+ {
+ mu->refcount--;
+ if (mu->refcount == 0)
+ mu->owner = 0UL;
+ LeaveCriticalSection (&(mu->cs));
+ return 0;
+ }
+ else
+ return 1;
+}
-inline int
-_Jv_MutexUnlock (_Jv_Mutex_t *mu)
+inline int _Jv_MutexLock (_Jv_Mutex_t *mu)
{
- return ReleaseMutex(*mu) ? 0 : GetLastError(); // FIXME: Map error code?
+ EnterCriticalSection (&(mu->cs));
+ mu->owner = GetCurrentThreadId ( );
+ mu->refcount++;
+ return 0;
}
//
//
void _Jv_InitThreads (void);
-void _Jv_ThreadInitData (_Jv_Thread_t **data, java::lang::Thread *thread);
+_Jv_Thread_t *_Jv_ThreadInitData (java::lang::Thread *thread);
+void _Jv_ThreadDestroyData (_Jv_Thread_t *data);
-inline java::lang::Thread *
-_Jv_ThreadCurrent (void)
+inline java::lang::Thread* _Jv_ThreadCurrent (void)
{
extern DWORD _Jv_ThreadKey;
return (java::lang::Thread *) TlsGetValue(_Jv_ThreadKey);
}
-inline _Jv_Thread_t *
-_Jv_ThreadCurrentData (void)
+inline _Jv_Thread_t *_Jv_ThreadCurrentData(void)
{
extern DWORD _Jv_ThreadDataKey;
return (_Jv_Thread_t *) TlsGetValue(_Jv_ThreadDataKey);
}
-inline void
-_Jv_ThreadYield (void)
+inline void _Jv_ThreadYield (void)
{
Sleep (0);
}
+void _Jv_ThreadRegister (_Jv_Thread_t *data);
+void _Jv_ThreadUnRegister ();
+
void _Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio);
void _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data,
_Jv_ThreadStartFunc *meth);
void _Jv_ThreadWait (void);
void _Jv_ThreadInterrupt (_Jv_Thread_t *data);
+//
+// Thread interruption support
+//
+
+// Gets the auto-reset event for the current thread which is
+// signalled by _Jv_ThreadInterrupt. The caller can wait on this
+// event in addition to other waitable objects.
+//
+// NOTE: After waiting on this event with WaitForMultipleObjects,
+// you should ALWAYS use the return value of WaitForMultipleObjects
+// to test whether this event was signalled and whether thread
+// interruption has occurred. You should do this instead of checking
+// the thread's interrupted_flag, because someone could have reset
+// this flag in the interval of time between the return of
+// WaitForMultipleObjects and the time you query interrupted_flag.
+// See java/lang/natWin32Process.cc (waitFor) for an example.
+HANDLE _Jv_Win32GetInterruptEvent (void);
+
+// park() / unpark() support
+
+struct ParkHelper
+{
+ // We use LONG instead of obj_addr_t to avoid pulling in locks.h,
+ // which depends on size_t, ...
+ volatile LONG permit;
+
+ // The critical section is used for lazy initialization of our event
+ CRITICAL_SECTION cs;
+ HANDLE event;
+
+ void init ();
+ void deactivate ();
+ void destroy ();
+ void park (jboolean isAbsolute, jlong time);
+ void unpark ();
+
+private:
+ void init_event();
+};
+
// Remove defines from <windows.h> that conflict with various things in libgcj code
#undef TRUE
#undef interface
#undef STRICT
#undef VOID
+#undef TEXT
+#undef OUT
#endif /* __JV_WIN32_THREADS__ */