#include <config.h>
#ifdef HAVE_BOEHM_GC
extern "C"
{
#include <boehm-config.h>
#include <gc.h>
};
#endif
#include <gcj/cni.h>
#include <jvm.h>
#include <java/lang/Thread.h>
#include <java/lang/System.h>
#include <errno.h>
#ifndef ETIMEDOUT
#define ETIMEDOUT 116
#endif
struct starter
{
_Jv_ThreadStartFunc *method;
_Jv_Thread_t *data;
};
static HANDLE daemon_mutex;
static HANDLE daemon_cond;
static int non_daemon_count;
DWORD _Jv_ThreadKey;
DWORD _Jv_ThreadDataKey;
#define FLAG_START 0x01
#define FLAG_DAEMON 0x02
int
_Jv_CondWait (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu, jlong millis, jint nanos)
{
DWORD time;
DWORD rval;
_Jv_MutexUnlock (mu);
if((millis == 0) && (nanos > 0))
time = 1;
else if(millis == 0)
time = INFINITE;
else
time = millis;
rval = WaitForSingleObject (*cv, time);
_Jv_MutexLock (mu);
if (rval == WAIT_FAILED)
return _JV_NOT_OWNER; else
return 0;
}
int
_Jv_MutexLock (_Jv_Mutex_t *mu)
{
DWORD rval;
rval = WaitForSingleObject (*mu, INFINITE);
if (rval == WAIT_FAILED)
return GetLastError (); else if (rval == WAIT_TIMEOUT)
return ETIMEDOUT;
else
return 0;
}
void
_Jv_InitThreads (void)
{
_Jv_ThreadKey = TlsAlloc();
_Jv_ThreadDataKey = TlsAlloc();
daemon_mutex = CreateMutex(NULL, 0, NULL);
daemon_cond = CreateEvent(NULL, 0, 0, NULL);
non_daemon_count = 0;
}
_Jv_Thread_t *
_Jv_ThreadInitData (java::lang::Thread* obj)
{
_Jv_Thread_t *data = new _Jv_Thread_t;
data->flags = 0;
data->thread_obj = obj;
return data;
}
void
_Jv_ThreadDestroyData (_Jv_Thread_t *data)
{
delete data;
}
void
_Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio)
{
int actual = THREAD_PRIORITY_NORMAL;
if (data->flags & FLAG_START)
{
switch (prio)
{
case 10:
actual = THREAD_PRIORITY_TIME_CRITICAL;
break;
case 9:
actual = THREAD_PRIORITY_HIGHEST;
break;
case 8:
case 7:
actual = THREAD_PRIORITY_ABOVE_NORMAL;
break;
case 6:
case 5:
actual = THREAD_PRIORITY_NORMAL;
break;
case 4:
case 3:
actual = THREAD_PRIORITY_BELOW_NORMAL;
break;
case 2:
actual = THREAD_PRIORITY_LOWEST;
break;
case 1:
actual = THREAD_PRIORITY_IDLE;
break;
}
SetThreadPriority(data->handle, actual);
}
}
void
_Jv_ThreadRegister (_Jv_Thread_t *data)
{
TlsSetValue (_Jv_ThreadKey, data->thread_obj);
TlsSetValue (_Jv_ThreadDataKey, data);
}
void
_Jv_ThreadUnRegister ()
{
TlsSetValue (_Jv_ThreadKey, NULL);
TlsSetValue (_Jv_ThreadDataKey, NULL);
}
static DWORD __stdcall
really_start (void* x)
{
struct starter *info = (struct starter *) x;
_Jv_ThreadRegister (info->data);
info->method (info->data->thread_obj);
if (! (info->data->flags & FLAG_DAEMON))
{
WaitForSingleObject (daemon_mutex, INFINITE);
non_daemon_count--;
if (! non_daemon_count)
PulseEvent (daemon_cond);
ReleaseMutex (daemon_mutex);
}
return 0;
}
void
_Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data, _Jv_ThreadStartFunc *meth)
{
DWORD id;
struct starter *info;
if (data->flags & FLAG_START)
return;
data->flags |= FLAG_START;
info = (struct starter *) _Jv_AllocBytes (sizeof (struct starter));
info->method = meth;
info->data = data;
if (! thread->isDaemon ())
{
WaitForSingleObject (daemon_mutex, INFINITE);
non_daemon_count++;
ReleaseMutex (daemon_mutex);
}
else
data->flags |= FLAG_DAEMON;
HANDLE h = CreateThread(NULL, 0, really_start, info, 0, &id);
_Jv_ThreadSetPriority(data, thread->getPriority());
}
void
_Jv_ThreadWait (void)
{
WaitForSingleObject(daemon_mutex, INFINITE);
if(non_daemon_count)
SignalObjectAndWait(daemon_mutex, daemon_cond, INFINITE, 0);
ReleaseMutex(daemon_mutex);
}
void
_Jv_ThreadInterrupt (_Jv_Thread_t *data)
{
MessageBox(NULL, "Unimplemented", "win32-threads.cc:_Jv_ThreadInterrupt", MB_OK);
}