* doc/gcov.texi: Use more logical markup.
[official-gcc.git] / libjava / win32-threads.cc
blob974f15622a57a2f700cc03a7763e8f26b2317570
1 // win32-threads.cc - interface between libjava and Win32 threads.
3 /* Copyright (C) 1998, 1999 Red Hat, Inc.
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9 details. */
11 #include <config.h>
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
16 extern "C"
18 #include <boehm-config.h>
19 #include <gc.h>
21 #endif /* HAVE_BOEHM_GC */
23 #include <gcj/cni.h>
24 #include <jvm.h>
25 #include <java/lang/Thread.h>
26 #include <java/lang/System.h>
28 #include <errno.h>
30 #ifndef ETIMEDOUT
31 #define ETIMEDOUT 116
32 #endif
34 // This is used to implement thread startup.
35 struct starter
37 _Jv_ThreadStartFunc *method;
38 _Jv_Thread_t *data;
41 // Controls access to the variable below
42 static HANDLE daemon_mutex;
43 static HANDLE daemon_cond;
44 // Number of non-daemon threads - _Jv_ThreadWait returns when this is 0
45 static int non_daemon_count;
47 // TLS key get Java object representing the thread
48 DWORD _Jv_ThreadKey;
49 // TLS key to get _Jv_Thread_t* representing the thread
50 DWORD _Jv_ThreadDataKey;
53 // These are the flags that can appear in _Jv_Thread_t.
56 // Thread started.
57 #define FLAG_START 0x01
58 // Thread is daemon.
59 #define FLAG_DAEMON 0x02
62 // Condition variables.
65 int
66 _Jv_CondWait (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu, jlong millis, jint nanos)
68 DWORD time;
69 DWORD rval;
71 // FIXME: check for mutex ownership?
73 _Jv_MutexUnlock (mu);
75 if((millis == 0) && (nanos > 0))
76 time = 1;
77 else if(millis == 0)
78 time = INFINITE;
79 else
80 time = millis;
82 rval = WaitForSingleObject (*cv, time);
83 _Jv_MutexLock (mu);
85 if (rval == WAIT_FAILED)
86 return _JV_NOT_OWNER; // FIXME?
87 else
88 return 0;
92 // Mutexes.
95 int
96 _Jv_MutexLock (_Jv_Mutex_t *mu)
98 DWORD rval;
100 // FIXME: Are Win32 mutexs recursive? Should we use critical section objects
101 rval = WaitForSingleObject (*mu, INFINITE);
103 if (rval == WAIT_FAILED)
104 return GetLastError (); // FIXME: Map to errno?
105 else if (rval == WAIT_TIMEOUT)
106 return ETIMEDOUT;
107 else
108 return 0;
112 // Threads.
115 void
116 _Jv_InitThreads (void)
118 _Jv_ThreadKey = TlsAlloc();
119 _Jv_ThreadDataKey = TlsAlloc();
120 daemon_mutex = CreateMutex(NULL, 0, NULL);
121 daemon_cond = CreateEvent(NULL, 0, 0, NULL);
122 non_daemon_count = 0;
125 _Jv_Thread_t *
126 _Jv_ThreadInitData (java::lang::Thread* obj)
128 _Jv_Thread_t *data = new _Jv_Thread_t;
129 data->flags = 0;
130 data->thread_obj = obj;
132 return data;
135 void
136 _Jv_ThreadDestroyData (_Jv_Thread_t *data)
138 delete data;
141 void
142 _Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio)
144 int actual = THREAD_PRIORITY_NORMAL;
146 if (data->flags & FLAG_START)
148 switch (prio)
150 case 10:
151 actual = THREAD_PRIORITY_TIME_CRITICAL;
152 break;
153 case 9:
154 actual = THREAD_PRIORITY_HIGHEST;
155 break;
156 case 8:
157 case 7:
158 actual = THREAD_PRIORITY_ABOVE_NORMAL;
159 break;
160 case 6:
161 case 5:
162 actual = THREAD_PRIORITY_NORMAL;
163 break;
164 case 4:
165 case 3:
166 actual = THREAD_PRIORITY_BELOW_NORMAL;
167 break;
168 case 2:
169 actual = THREAD_PRIORITY_LOWEST;
170 break;
171 case 1:
172 actual = THREAD_PRIORITY_IDLE;
173 break;
175 SetThreadPriority(data->handle, actual);
179 void
180 _Jv_ThreadRegister (_Jv_Thread_t *data)
182 TlsSetValue (_Jv_ThreadKey, data->thread_obj);
183 TlsSetValue (_Jv_ThreadDataKey, data);
186 void
187 _Jv_ThreadUnRegister ()
189 TlsSetValue (_Jv_ThreadKey, NULL);
190 TlsSetValue (_Jv_ThreadDataKey, NULL);
193 // This function is called when a thread is started. We don't arrange
194 // to call the `run' method directly, because this function must
195 // return a value.
196 static DWORD __stdcall
197 really_start (void* x)
199 struct starter *info = (struct starter *) x;
201 _Jv_ThreadRegister (info->data);
203 info->method (info->data->thread_obj);
205 if (! (info->data->flags & FLAG_DAEMON))
207 WaitForSingleObject (daemon_mutex, INFINITE);
208 non_daemon_count--;
209 if (! non_daemon_count)
210 PulseEvent (daemon_cond);
211 ReleaseMutex (daemon_mutex);
214 return 0;
217 void
218 _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data, _Jv_ThreadStartFunc *meth)
220 DWORD id;
221 struct starter *info;
223 // Do nothing if thread has already started
224 if (data->flags & FLAG_START)
225 return;
226 data->flags |= FLAG_START;
228 // FIXME: handle marking the info object for GC.
229 info = (struct starter *) _Jv_AllocBytes (sizeof (struct starter));
230 info->method = meth;
231 info->data = data;
233 if (! thread->isDaemon ())
235 WaitForSingleObject (daemon_mutex, INFINITE);
236 non_daemon_count++;
237 ReleaseMutex (daemon_mutex);
239 else
240 data->flags |= FLAG_DAEMON;
242 HANDLE h = CreateThread(NULL, 0, really_start, info, 0, &id);
243 _Jv_ThreadSetPriority(data, thread->getPriority());
245 //if (!h)
246 //JvThrow ();
249 void
250 _Jv_ThreadWait (void)
252 WaitForSingleObject(daemon_mutex, INFINITE);
253 if(non_daemon_count)
254 SignalObjectAndWait(daemon_mutex, daemon_cond, INFINITE, 0);
255 ReleaseMutex(daemon_mutex);
258 void
259 _Jv_ThreadInterrupt (_Jv_Thread_t *data)
261 MessageBox(NULL, "Unimplemented", "win32-threads.cc:_Jv_ThreadInterrupt", MB_OK);
262 // FIXME: