]> gcc.gnu.org Git - gcc.git/blame - libjava/win32-threads.cc
Win32Process.java: Created a dummy class to allow build process to run to completion.
[gcc.git] / libjava / win32-threads.cc
CommitLineData
878885b4
TT
1// win32-threads.cc - interface between libjava and Win32 threads.
2
85ea93b3 3/* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
878885b4
TT
4
5 This file is part of libgcj.
6
7This software is copyrighted work licensed under the terms of the
8Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9details. */
10
11#include <config.h>
12
13// If we're using the Boehm GC, then we need to override some of the
14// thread primitives. This is fairly gross.
15#ifdef HAVE_BOEHM_GC
16extern "C"
17{
878885b4 18#include <gc.h>
1d3efb36
AM
19// <windows.h> #define's STRICT, which conflicts with Modifier.h
20#undef STRICT
878885b4
TT
21};
22#endif /* HAVE_BOEHM_GC */
23
24#include <gcj/cni.h>
25#include <jvm.h>
26#include <java/lang/Thread.h>
27#include <java/lang/System.h>
28
29#include <errno.h>
30
31#ifndef ETIMEDOUT
32#define ETIMEDOUT 116
33#endif
34
35// This is used to implement thread startup.
36struct starter
37{
38 _Jv_ThreadStartFunc *method;
878885b4
TT
39 _Jv_Thread_t *data;
40};
41
42// Controls access to the variable below
43static HANDLE daemon_mutex;
44static HANDLE daemon_cond;
45// Number of non-daemon threads - _Jv_ThreadWait returns when this is 0
46static int non_daemon_count;
47
48// TLS key get Java object representing the thread
49DWORD _Jv_ThreadKey;
50// TLS key to get _Jv_Thread_t* representing the thread
51DWORD _Jv_ThreadDataKey;
52
53//
54// These are the flags that can appear in _Jv_Thread_t.
55//
56
57// Thread started.
58#define FLAG_START 0x01
59// Thread is daemon.
60#define FLAG_DAEMON 0x02
61
62//
63// Condition variables.
64//
65
a70cb11b
AM
66// we do lazy creation of Events since CreateEvent() is insanely
67// expensive, and because the rest of libgcj will call _Jv_CondInit
68// when only a mutex is needed.
69
70inline void
71ensure_condvar_initialized(_Jv_ConditionVariable_t *cv)
72{
73 if (cv->ev[0] == 0) {
74 cv->ev[0] = CreateEvent (NULL, 0, 0, NULL);
75 if (cv->ev[0] == 0) JvFail("CreateEvent() failed");
76 cv->ev[1] = CreateEvent (NULL, 1, 0, NULL);
77 if (cv->ev[1] == 0) JvFail("CreateEvent() failed");
78 }
79}
80
81// Reimplementation of the general algorithm described at
82// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html (isomorphic to
83// 3.2, not a cut-and-paste).
84
878885b4 85int
a70cb11b 86_Jv_CondWait(_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu, jlong millis, jint nanos)
878885b4 87{
878885b4 88
a70cb11b
AM
89 EnterCriticalSection(&cv->count_mutex);
90 ensure_condvar_initialized(cv);
91 cv->blocked_count++;
92 LeaveCriticalSection(&cv->count_mutex);
93
94 DWORD time;
95 if ((millis == 0) && (nanos > 0)) time = 1;
96 else if (millis == 0) time = INFINITE;
97 else time = millis;
b834f1fa 98
878885b4
TT
99 _Jv_MutexUnlock (mu);
100
a70cb11b
AM
101 DWORD rval = WaitForMultipleObjects (2, &(cv->ev[0]), 0, time);
102
103 EnterCriticalSection(&cv->count_mutex);
104 cv->blocked_count--;
105 // If we were unblocked by the second event (the broadcast one) and nobody is
106 // left, then reset the signal.
107 int last_waiter = rval == WAIT_OBJECT_0 + 1 && cv->blocked_count == 0;
108 LeaveCriticalSection(&cv->count_mutex);
109
110 if (last_waiter) ResetEvent(&cv->ev[1]);
878885b4 111
878885b4
TT
112 _Jv_MutexLock (mu);
113
a70cb11b
AM
114 if (rval == WAIT_FAILED) return GetLastError();
115 else if (rval == WAIT_TIMEOUT) return ETIMEDOUT;
116 else return 0;
878885b4
TT
117}
118
a70cb11b
AM
119void
120_Jv_CondInit (_Jv_ConditionVariable_t *cv)
121{
122 // we do lazy creation of Events since CreateEvent() is insanely expensive
123 cv->ev[0] = 0;
124 InitializeCriticalSection(&cv->count_mutex);
125 cv->blocked_count = 0;
126}
127
128void
129_Jv_CondDestroy (_Jv_ConditionVariable_t *cv)
130{
131 if (cv->ev[0] != 0) CloseHandle(cv->ev[0]);
132 cv = NULL;
133}
878885b4
TT
134
135int
a70cb11b 136_Jv_CondNotify (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *)
878885b4 137{
a70cb11b
AM
138 EnterCriticalSection(&cv->count_mutex);
139 ensure_condvar_initialized(cv);
140 int somebody_is_blocked = cv->blocked_count > 0;
141 LeaveCriticalSection(&cv->count_mutex);
878885b4 142
a70cb11b
AM
143 if (somebody_is_blocked) return SetEvent (cv->ev[0]) ? 0 : GetLastError();
144 else return 0;
145}
878885b4 146
a70cb11b
AM
147int
148_Jv_CondNotifyAll (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *)
149{
150 EnterCriticalSection(&cv->count_mutex);
151 ensure_condvar_initialized(cv);
152 int somebody_is_blocked = cv->blocked_count > 0;
153 LeaveCriticalSection(&cv->count_mutex);
154
155 if (somebody_is_blocked) return SetEvent (cv->ev[1]) ? 0 : GetLastError();
156 else return 0;
878885b4
TT
157}
158
159//
160// Threads.
161//
162
163void
164_Jv_InitThreads (void)
165{
166 _Jv_ThreadKey = TlsAlloc();
167 _Jv_ThreadDataKey = TlsAlloc();
168 daemon_mutex = CreateMutex(NULL, 0, NULL);
169 daemon_cond = CreateEvent(NULL, 0, 0, NULL);
170 non_daemon_count = 0;
171}
172
e301621d 173_Jv_Thread_t *
c93d7fae 174_Jv_ThreadInitData (java::lang::Thread* obj)
878885b4 175{
e301621d
BM
176 _Jv_Thread_t *data = new _Jv_Thread_t;
177 data->flags = 0;
c93d7fae 178 data->thread_obj = obj;
878885b4 179
e301621d
BM
180 return data;
181}
878885b4 182
e301621d
BM
183void
184_Jv_ThreadDestroyData (_Jv_Thread_t *data)
185{
186 delete data;
878885b4
TT
187}
188
189void
190_Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio)
191{
192 int actual = THREAD_PRIORITY_NORMAL;
193
194 if (data->flags & FLAG_START)
195 {
196 switch (prio)
197 {
198 case 10:
199 actual = THREAD_PRIORITY_TIME_CRITICAL;
200 break;
201 case 9:
202 actual = THREAD_PRIORITY_HIGHEST;
203 break;
204 case 8:
205 case 7:
206 actual = THREAD_PRIORITY_ABOVE_NORMAL;
207 break;
208 case 6:
209 case 5:
210 actual = THREAD_PRIORITY_NORMAL;
211 break;
212 case 4:
213 case 3:
214 actual = THREAD_PRIORITY_BELOW_NORMAL;
215 break;
216 case 2:
217 actual = THREAD_PRIORITY_LOWEST;
218 break;
219 case 1:
220 actual = THREAD_PRIORITY_IDLE;
221 break;
222 }
223 SetThreadPriority(data->handle, actual);
224 }
225}
226
c93d7fae
PB
227void
228_Jv_ThreadRegister (_Jv_Thread_t *data)
229{
230 TlsSetValue (_Jv_ThreadKey, data->thread_obj);
231 TlsSetValue (_Jv_ThreadDataKey, data);
232}
233
234void
235_Jv_ThreadUnRegister ()
236{
237 TlsSetValue (_Jv_ThreadKey, NULL);
238 TlsSetValue (_Jv_ThreadDataKey, NULL);
239}
240
878885b4
TT
241// This function is called when a thread is started. We don't arrange
242// to call the `run' method directly, because this function must
243// return a value.
a70cb11b 244static DWORD WINAPI
878885b4
TT
245really_start (void* x)
246{
247 struct starter *info = (struct starter *) x;
248
c93d7fae
PB
249 _Jv_ThreadRegister (info->data);
250
251 info->method (info->data->thread_obj);
878885b4
TT
252
253 if (! (info->data->flags & FLAG_DAEMON))
254 {
255 WaitForSingleObject (daemon_mutex, INFINITE);
256 non_daemon_count--;
257 if (! non_daemon_count)
258 PulseEvent (daemon_cond);
259 ReleaseMutex (daemon_mutex);
260 }
261
262 return 0;
263}
264
265void
266_Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data, _Jv_ThreadStartFunc *meth)
267{
268 DWORD id;
269 struct starter *info;
270
271 // Do nothing if thread has already started
272 if (data->flags & FLAG_START)
273 return;
274 data->flags |= FLAG_START;
275
276 // FIXME: handle marking the info object for GC.
277 info = (struct starter *) _Jv_AllocBytes (sizeof (struct starter));
278 info->method = meth;
878885b4
TT
279 info->data = data;
280
281 if (! thread->isDaemon ())
282 {
283 WaitForSingleObject (daemon_mutex, INFINITE);
284 non_daemon_count++;
285 ReleaseMutex (daemon_mutex);
286 }
287 else
288 data->flags |= FLAG_DAEMON;
289
a70cb11b 290 HANDLE h = GC_CreateThread(NULL, 0, really_start, info, 0, &id);
878885b4
TT
291 _Jv_ThreadSetPriority(data, thread->getPriority());
292
293 //if (!h)
294 //JvThrow ();
295}
296
297void
298_Jv_ThreadWait (void)
299{
300 WaitForSingleObject(daemon_mutex, INFINITE);
301 if(non_daemon_count)
302 SignalObjectAndWait(daemon_mutex, daemon_cond, INFINITE, 0);
303 ReleaseMutex(daemon_mutex);
304}
305
306void
307_Jv_ThreadInterrupt (_Jv_Thread_t *data)
308{
309 MessageBox(NULL, "Unimplemented", "win32-threads.cc:_Jv_ThreadInterrupt", MB_OK);
310 // FIXME:
311}
This page took 0.185923 seconds and 5 git commands to generate.