OSDN Git Service

2002-01-06 H.J. Lu <hjl@gnu.org>
[pf3gnuchains/gcc-fork.git] / libjava / win32-threads.cc
1 // win32-threads.cc - interface between libjava and Win32 threads.
2
3 /* Copyright (C) 1998, 1999  Red Hat, Inc.
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
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
16 extern "C"
17 {
18 #include <boehm-config.h>
19 #include <gc.h>
20 };
21 #endif /* HAVE_BOEHM_GC */
22
23 #include <gcj/cni.h>
24 #include <jvm.h>
25 #include <java/lang/Thread.h>
26 #include <java/lang/System.h>
27
28 #include <errno.h>
29
30 #ifndef ETIMEDOUT
31 #define ETIMEDOUT 116
32 #endif
33
34 // This is used to implement thread startup.
35 struct starter
36 {
37   _Jv_ThreadStartFunc *method;
38   _Jv_Thread_t *data;
39 };
40
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;
46
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;
51
52 //
53 // These are the flags that can appear in _Jv_Thread_t.
54 //
55
56 // Thread started.
57 #define FLAG_START   0x01
58 // Thread is daemon.
59 #define FLAG_DAEMON  0x02
60
61 //
62 // Condition variables.
63 //
64
65 int
66 _Jv_CondWait (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu, jlong millis, jint nanos)
67 {
68   DWORD time;
69   DWORD rval;
70
71   // FIXME: check for mutex ownership?
72
73   _Jv_MutexUnlock (mu);
74
75   if((millis == 0) && (nanos > 0))
76     time = 1;
77   else if(millis == 0)
78     time = INFINITE;
79   else
80     time = millis;
81
82   rval = WaitForSingleObject (*cv, time);
83   _Jv_MutexLock (mu);
84
85   if (rval == WAIT_FAILED)
86     return _JV_NOT_OWNER;       // FIXME?
87   else
88     return 0;
89 }
90
91 //
92 // Mutexes.
93 //
94
95 int
96 _Jv_MutexLock (_Jv_Mutex_t *mu)
97 {
98   DWORD rval;
99
100   // FIXME: Are Win32 mutexs recursive? Should we use critical section objects
101   rval = WaitForSingleObject (*mu, INFINITE);
102
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;
109 }
110
111 //
112 // Threads.
113 //
114
115 void
116 _Jv_InitThreads (void)
117 {
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;
123 }
124
125 _Jv_Thread_t *
126 _Jv_ThreadInitData (java::lang::Thread* obj)
127 {
128   _Jv_Thread_t *data = new _Jv_Thread_t;
129   data->flags = 0;
130   data->thread_obj = obj;
131
132   return data;
133 }
134
135 void
136 _Jv_ThreadDestroyData (_Jv_Thread_t *data)
137 {
138   delete data;
139 }
140
141 void
142 _Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio)
143 {
144   int actual = THREAD_PRIORITY_NORMAL;
145
146   if (data->flags & FLAG_START)
147     {
148       switch (prio)
149         {
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;
174         }
175       SetThreadPriority(data->handle, actual);
176     }
177 }
178
179 void
180 _Jv_ThreadRegister (_Jv_Thread_t *data)
181 {
182   TlsSetValue (_Jv_ThreadKey, data->thread_obj);
183   TlsSetValue (_Jv_ThreadDataKey, data);
184 }
185
186 void
187 _Jv_ThreadUnRegister ()
188 {
189   TlsSetValue (_Jv_ThreadKey, NULL);
190   TlsSetValue (_Jv_ThreadDataKey, NULL);
191 }
192
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)
198 {
199   struct starter *info = (struct starter *) x;
200
201   _Jv_ThreadRegister (info->data);
202
203   info->method (info->data->thread_obj);
204
205   if (! (info->data->flags & FLAG_DAEMON))
206     {
207       WaitForSingleObject (daemon_mutex, INFINITE);
208       non_daemon_count--;
209       if (! non_daemon_count)
210           PulseEvent (daemon_cond);
211       ReleaseMutex (daemon_mutex);
212     }
213
214   return 0;
215 }
216
217 void
218 _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data, _Jv_ThreadStartFunc *meth)
219 {
220   DWORD id;
221   struct starter *info;
222
223   // Do nothing if thread has already started
224   if (data->flags & FLAG_START)
225     return;
226   data->flags |= FLAG_START;
227
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;
232
233   if (! thread->isDaemon ())
234     {
235       WaitForSingleObject (daemon_mutex, INFINITE);
236       non_daemon_count++;
237       ReleaseMutex (daemon_mutex);
238     }
239   else
240     data->flags |= FLAG_DAEMON;
241
242   HANDLE h = CreateThread(NULL, 0, really_start, info, 0, &id);
243   _Jv_ThreadSetPriority(data, thread->getPriority());
244
245   //if (!h)
246     //JvThrow ();
247 }
248
249 void
250 _Jv_ThreadWait (void)
251 {
252   WaitForSingleObject(daemon_mutex, INFINITE);
253   if(non_daemon_count)
254       SignalObjectAndWait(daemon_mutex, daemon_cond, INFINITE, 0);
255   ReleaseMutex(daemon_mutex);
256 }
257
258 void
259 _Jv_ThreadInterrupt (_Jv_Thread_t *data)
260 {
261   MessageBox(NULL, "Unimplemented", "win32-threads.cc:_Jv_ThreadInterrupt", MB_OK);
262   // FIXME:
263 }