OSDN Git Service

accept local directory for fixincl in fixincl.sh script
[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 _Jv_Thread_t *
127 _Jv_ThreadInitData (java::lang::Thread *)
128 {
129   _Jv_Thread_t *data = new _Jv_Thread_t;
130   data->flags = 0;
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 // This function is called when a thread is started.  We don't arrange
180 // to call the `run' method directly, because this function must
181 // return a value.
182 static DWORD __stdcall
183 really_start (void* x)
184 {
185   struct starter *info = (struct starter *) x;
186
187   TlsSetValue (_Jv_ThreadKey, info->object);
188   TlsSetValue (_Jv_ThreadDataKey, info->data);
189   info->method (info->object);
190
191   if (! (info->data->flags & FLAG_DAEMON))
192     {
193       WaitForSingleObject (daemon_mutex, INFINITE);
194       non_daemon_count--;
195       if (! non_daemon_count)
196           PulseEvent (daemon_cond);
197       ReleaseMutex (daemon_mutex);
198     }
199
200   return 0;
201 }
202
203 void
204 _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data, _Jv_ThreadStartFunc *meth)
205 {
206   DWORD id;
207   struct starter *info;
208
209   // Do nothing if thread has already started
210   if (data->flags & FLAG_START)
211     return;
212   data->flags |= FLAG_START;
213
214   // FIXME: handle marking the info object for GC.
215   info = (struct starter *) _Jv_AllocBytes (sizeof (struct starter));
216   info->method = meth;
217   info->object = thread;
218   info->data = data;
219
220   if (! thread->isDaemon ())
221     {
222       WaitForSingleObject (daemon_mutex, INFINITE);
223       non_daemon_count++;
224       ReleaseMutex (daemon_mutex);
225     }
226   else
227     data->flags |= FLAG_DAEMON;
228
229   HANDLE h = CreateThread(NULL, 0, really_start, info, 0, &id);
230   _Jv_ThreadSetPriority(data, thread->getPriority());
231
232   //if (!h)
233     //JvThrow ();
234 }
235
236 void
237 _Jv_ThreadWait (void)
238 {
239   WaitForSingleObject(daemon_mutex, INFINITE);
240   if(non_daemon_count)
241       SignalObjectAndWait(daemon_mutex, daemon_cond, INFINITE, 0);
242   ReleaseMutex(daemon_mutex);
243 }
244
245 void
246 _Jv_ThreadInterrupt (_Jv_Thread_t *data)
247 {
248   MessageBox(NULL, "Unimplemented", "win32-threads.cc:_Jv_ThreadInterrupt", MB_OK);
249   // FIXME:
250 }