OSDN Git Service

Daily bump.
[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   java::lang::Thread *object;
39   _Jv_Thread_t *data;
40 };
41
42 // Controls access to the variable below
43 static HANDLE daemon_mutex;
44 static HANDLE daemon_cond;
45 // Number of non-daemon threads - _Jv_ThreadWait returns when this is 0
46 static int non_daemon_count;
47
48 // TLS key get Java object representing the thread
49 DWORD _Jv_ThreadKey;
50 // TLS key to get _Jv_Thread_t* representing the thread
51 DWORD _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
66 int
67 _Jv_CondWait (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu, jlong millis, jint nanos)
68 {
69   DWORD time;
70   DWORD rval;
71
72   // FIXME: check for mutex ownership?
73
74   _Jv_MutexUnlock (mu);
75
76   if((millis == 0) && (nanos > 0))
77     time = 1;
78   else if(millis == 0)
79     time = INFINITE;
80   else
81     time = millis;
82
83   rval = WaitForSingleObject (*cv, time);
84   _Jv_MutexLock (mu);
85
86   if (rval == WAIT_FAILED)
87     return _JV_NOT_OWNER;       // FIXME?
88   else
89     return 0;
90 }
91
92 //
93 // Mutexes.
94 //
95
96 int
97 _Jv_MutexLock (_Jv_Mutex_t *mu)
98 {
99   DWORD rval;
100
101   // FIXME: Are Win32 mutexs recursive? Should we use critical section objects
102   rval = WaitForSingleObject (*mu, INFINITE);
103
104   if (rval == WAIT_FAILED)
105     return GetLastError ();       // FIXME: Map to errno?
106   else if (rval == WAIT_TIMEOUT)
107     return ETIMEDOUT;
108   else
109     return 0;
110 }
111
112 //
113 // Threads.
114 //
115
116 void
117 _Jv_InitThreads (void)
118 {
119   _Jv_ThreadKey = TlsAlloc();
120   _Jv_ThreadDataKey = TlsAlloc();
121   daemon_mutex = CreateMutex(NULL, 0, NULL);
122   daemon_cond = CreateEvent(NULL, 0, 0, NULL);
123   non_daemon_count = 0;
124 }
125
126 void
127 _Jv_ThreadInitData (_Jv_Thread_t **data, java::lang::Thread *)
128 {
129   _Jv_Thread_t *info = new _Jv_Thread_t;
130   info->flags = 0;
131
132   // FIXME register a finalizer for INFO here.
133   // FIXME also must mark INFO somehow.
134
135   *data = info;
136 }
137
138 void
139 _Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio)
140 {
141   int actual = THREAD_PRIORITY_NORMAL;
142
143   if (data->flags & FLAG_START)
144     {
145       switch (prio)
146         {
147           case 10:
148             actual = THREAD_PRIORITY_TIME_CRITICAL;
149             break;
150           case 9:
151             actual = THREAD_PRIORITY_HIGHEST;
152             break;
153           case 8:
154           case 7:
155             actual = THREAD_PRIORITY_ABOVE_NORMAL;
156             break;
157           case 6:
158           case 5:
159             actual = THREAD_PRIORITY_NORMAL;
160             break;
161           case 4:
162           case 3:
163             actual = THREAD_PRIORITY_BELOW_NORMAL;
164             break;
165           case 2:
166             actual = THREAD_PRIORITY_LOWEST;
167             break;
168           case 1:
169             actual = THREAD_PRIORITY_IDLE;
170             break;
171         }
172       SetThreadPriority(data->handle, actual);
173     }
174 }
175
176 // This function is called when a thread is started.  We don't arrange
177 // to call the `run' method directly, because this function must
178 // return a value.
179 static DWORD __stdcall
180 really_start (void* x)
181 {
182   struct starter *info = (struct starter *) x;
183
184   TlsSetValue (_Jv_ThreadKey, info->object);
185   TlsSetValue (_Jv_ThreadDataKey, info->data);
186   info->method (info->object);
187
188   if (! (info->data->flags & FLAG_DAEMON))
189     {
190       WaitForSingleObject (daemon_mutex, INFINITE);
191       non_daemon_count--;
192       if (! non_daemon_count)
193           PulseEvent (daemon_cond);
194       ReleaseMutex (daemon_mutex);
195     }
196
197   return 0;
198 }
199
200 void
201 _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data, _Jv_ThreadStartFunc *meth)
202 {
203   DWORD id;
204   struct starter *info;
205
206   // Do nothing if thread has already started
207   if (data->flags & FLAG_START)
208     return;
209   data->flags |= FLAG_START;
210
211   // FIXME: handle marking the info object for GC.
212   info = (struct starter *) _Jv_AllocBytes (sizeof (struct starter));
213   info->method = meth;
214   info->object = thread;
215   info->data = data;
216
217   if (! thread->isDaemon ())
218     {
219       WaitForSingleObject (daemon_mutex, INFINITE);
220       non_daemon_count++;
221       ReleaseMutex (daemon_mutex);
222     }
223   else
224     data->flags |= FLAG_DAEMON;
225
226   HANDLE h = CreateThread(NULL, 0, really_start, info, 0, &id);
227   _Jv_ThreadSetPriority(data, thread->getPriority());
228
229   //if (!h)
230     //JvThrow ();
231 }
232
233 void
234 _Jv_ThreadWait (void)
235 {
236   WaitForSingleObject(daemon_mutex, INFINITE);
237   if(non_daemon_count)
238       SignalObjectAndWait(daemon_mutex, daemon_cond, INFINITE, 0);
239   ReleaseMutex(daemon_mutex);
240 }
241
242 void
243 _Jv_ThreadInterrupt (_Jv_Thread_t *data)
244 {
245   MessageBox(NULL, "Unimplemented", "win32-threads.cc:_Jv_ThreadInterrupt", MB_OK);
246   // FIXME:
247 }