1 | // posix-threads.cc - interface between libjava and POSIX threads.
|
---|
2 |
|
---|
3 | /* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
|
---|
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 | // TO DO:
|
---|
12 | // * Document signal handling limitations
|
---|
13 |
|
---|
14 | #include <config.h>
|
---|
15 |
|
---|
16 | // If we're using the Boehm GC, then we need to override some of the
|
---|
17 | // thread primitives. This is fairly gross.
|
---|
18 | #ifdef HAVE_BOEHM_GC
|
---|
19 | #include <gc.h>
|
---|
20 | #endif /* HAVE_BOEHM_GC */
|
---|
21 |
|
---|
22 | #include <stdlib.h>
|
---|
23 | #include <time.h>
|
---|
24 | #include <signal.h>
|
---|
25 | #include <errno.h>
|
---|
26 | #include <limits.h>
|
---|
27 | #ifdef HAVE_UNISTD_H
|
---|
28 | #include <unistd.h> // To test for _POSIX_THREAD_PRIORITY_SCHEDULING
|
---|
29 | #endif
|
---|
30 |
|
---|
31 | #include <gcj/cni.h>
|
---|
32 | #include <jvm.h>
|
---|
33 | #include <java/lang/Thread.h>
|
---|
34 | #include <java/lang/System.h>
|
---|
35 | #include <java/lang/Long.h>
|
---|
36 | #include <java/lang/OutOfMemoryError.h>
|
---|
37 |
|
---|
38 | // This is used to implement thread startup.
|
---|
39 | struct starter
|
---|
40 | {
|
---|
41 | _Jv_ThreadStartFunc *method;
|
---|
42 | _Jv_Thread_t *data;
|
---|
43 | };
|
---|
44 |
|
---|
45 | // This is the key used to map from the POSIX thread value back to the
|
---|
46 | // Java object representing the thread. The key is global to all
|
---|
47 | // threads, so it is ok to make it a global here.
|
---|
48 | pthread_key_t _Jv_ThreadKey;
|
---|
49 |
|
---|
50 | // This is the key used to map from the POSIX thread value back to the
|
---|
51 | // _Jv_Thread_t* representing the thread.
|
---|
52 | pthread_key_t _Jv_ThreadDataKey;
|
---|
53 |
|
---|
54 | // We keep a count of all non-daemon threads which are running. When
|
---|
55 | // this reaches zero, _Jv_ThreadWait returns.
|
---|
56 | static pthread_mutex_t daemon_mutex;
|
---|
57 | static pthread_cond_t daemon_cond;
|
---|
58 | static int non_daemon_count;
|
---|
59 |
|
---|
60 | // The signal to use when interrupting a thread.
|
---|
61 | #if defined(LINUX_THREADS) || defined(FREEBSD_THREADS)
|
---|
62 | // LinuxThreads (prior to glibc 2.1) usurps both SIGUSR1 and SIGUSR2.
|
---|
63 | // GC on FreeBSD uses both SIGUSR1 and SIGUSR2.
|
---|
64 | # define INTR SIGHUP
|
---|
65 | #else /* LINUX_THREADS */
|
---|
66 | # define INTR SIGUSR2
|
---|
67 | #endif /* LINUX_THREADS */
|
---|
68 |
|
---|
69 | //
|
---|
70 | // These are the flags that can appear in _Jv_Thread_t.
|
---|
71 | //
|
---|
72 |
|
---|
73 | // Thread started.
|
---|
74 | #define FLAG_START 0x01
|
---|
75 | // Thread is daemon.
|
---|
76 | #define FLAG_DAEMON 0x02
|
---|
77 |
|
---|
78 | |
---|
79 |
|
---|
80 |
|
---|
81 | // Wait for the condition variable "CV" to be notified.
|
---|
82 | // Return values:
|
---|
83 | // 0: the condition was notified, or the timeout expired.
|
---|
84 | // _JV_NOT_OWNER: the thread does not own the mutex "MU".
|
---|
85 | // _JV_INTERRUPTED: the thread was interrupted. Its interrupted flag is set.
|
---|
86 | int
|
---|
87 | _Jv_CondWait (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu,
|
---|
88 | jlong millis, jint nanos)
|
---|
89 | {
|
---|
90 | pthread_t self = pthread_self();
|
---|
91 | if (mu->owner != self)
|
---|
92 | return _JV_NOT_OWNER;
|
---|
93 |
|
---|
94 | struct timespec ts;
|
---|
95 | jlong m, startTime;
|
---|
96 |
|
---|
97 | if (millis > 0 || nanos > 0)
|
---|
98 | {
|
---|
99 | startTime = java::lang::System::currentTimeMillis();
|
---|
100 | m = millis + startTime;
|
---|
101 | ts.tv_sec = m / 1000;
|
---|
102 | ts.tv_nsec = ((m % 1000) * 1000000) + nanos;
|
---|
103 | }
|
---|
104 |
|
---|
105 | _Jv_Thread_t *current = _Jv_ThreadCurrentData ();
|
---|
106 | java::lang::Thread *current_obj = _Jv_ThreadCurrent ();
|
---|
107 |
|
---|
108 | pthread_mutex_lock (¤t->wait_mutex);
|
---|
109 |
|
---|
110 | // Now that we hold the wait mutex, check if this thread has been
|
---|
111 | // interrupted already.
|
---|
112 | if (current_obj->interrupt_flag)
|
---|
113 | {
|
---|
114 | pthread_mutex_unlock (¤t->wait_mutex);
|
---|
115 | return _JV_INTERRUPTED;
|
---|
116 | }
|
---|
117 |
|
---|
118 | // Add this thread to the cv's wait set.
|
---|
119 | current->next = NULL;
|
---|
120 |
|
---|
121 | if (cv->first == NULL)
|
---|
122 | cv->first = current;
|
---|
123 | else
|
---|
124 | for (_Jv_Thread_t *t = cv->first;; t = t->next)
|
---|
125 | {
|
---|
126 | if (t->next == NULL)
|
---|
127 | {
|
---|
128 | t->next = current;
|
---|
129 | break;
|
---|
130 | }
|
---|
131 | }
|
---|
132 |
|
---|
133 | // Record the current lock depth, so it can be restored when we re-aquire it.
|
---|
134 | int count = mu->count;
|
---|
135 |
|
---|
136 | // Release the monitor mutex.
|
---|
137 | mu->count = 0;
|
---|
138 | mu->owner = 0;
|
---|
139 | pthread_mutex_unlock (&mu->mutex);
|
---|
140 |
|
---|
141 | int r = 0;
|
---|
142 | bool done_sleeping = false;
|
---|
143 |
|
---|
144 | while (! done_sleeping)
|
---|
145 | {
|
---|
146 | if (millis == 0 && nanos == 0)
|
---|
147 | r = pthread_cond_wait (¤t->wait_cond, ¤t->wait_mutex);
|
---|
148 | else
|
---|
149 | r = pthread_cond_timedwait (¤t->wait_cond, ¤t->wait_mutex,
|
---|
150 | &ts);
|
---|
151 |
|
---|
152 | // In older glibc's (prior to 2.1.3), the cond_wait functions may
|
---|
153 | // spuriously wake up on a signal. Catch that here.
|
---|
154 | if (r != EINTR)
|
---|
155 | done_sleeping = true;
|
---|
156 | }
|
---|
157 |
|
---|
158 | // Check for an interrupt *before* releasing the wait mutex.
|
---|
159 | jboolean interrupted = current_obj->interrupt_flag;
|
---|
160 |
|
---|
161 | pthread_mutex_unlock (¤t->wait_mutex);
|
---|
162 |
|
---|
163 | // Reaquire the monitor mutex, and restore the lock count.
|
---|
164 | pthread_mutex_lock (&mu->mutex);
|
---|
165 | mu->owner = self;
|
---|
166 | mu->count = count;
|
---|
167 |
|
---|
168 | // If we were interrupted, or if a timeout occurred, remove ourself from
|
---|
169 | // the cv wait list now. (If we were notified normally, notify() will have
|
---|
170 | // already taken care of this)
|
---|
171 | if (r == ETIMEDOUT || interrupted)
|
---|
172 | {
|
---|
173 | _Jv_Thread_t *prev = NULL;
|
---|
174 | for (_Jv_Thread_t *t = cv->first; t != NULL; t = t->next)
|
---|
175 | {
|
---|
176 | if (t == current)
|
---|
177 | {
|
---|
178 | if (prev != NULL)
|
---|
179 | prev->next = t->next;
|
---|
180 | else
|
---|
181 | cv->first = t->next;
|
---|
182 | t->next = NULL;
|
---|
183 | break;
|
---|
184 | }
|
---|
185 | prev = t;
|
---|
186 | }
|
---|
187 | if (interrupted)
|
---|
188 | return _JV_INTERRUPTED;
|
---|
189 | }
|
---|
190 |
|
---|
191 | return 0;
|
---|
192 | }
|
---|
193 |
|
---|
194 | int
|
---|
195 | _Jv_CondNotify (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu)
|
---|
196 | {
|
---|
197 | if (_Jv_PthreadCheckMonitor (mu))
|
---|
198 | return _JV_NOT_OWNER;
|
---|
199 |
|
---|
200 | _Jv_Thread_t *target;
|
---|
201 | _Jv_Thread_t *prev = NULL;
|
---|
202 |
|
---|
203 | for (target = cv->first; target != NULL; target = target->next)
|
---|
204 | {
|
---|
205 | pthread_mutex_lock (&target->wait_mutex);
|
---|
206 |
|
---|
207 | if (target->thread_obj->interrupt_flag)
|
---|
208 | {
|
---|
209 | // Don't notify a thread that has already been interrupted.
|
---|
210 | pthread_mutex_unlock (&target->wait_mutex);
|
---|
211 | prev = target;
|
---|
212 | continue;
|
---|
213 | }
|
---|
214 |
|
---|
215 | pthread_cond_signal (&target->wait_cond);
|
---|
216 | pthread_mutex_unlock (&target->wait_mutex);
|
---|
217 |
|
---|
218 | // Two concurrent notify() calls must not be delivered to the same
|
---|
219 | // thread, so remove the target thread from the cv wait list now.
|
---|
220 | if (prev == NULL)
|
---|
221 | cv->first = target->next;
|
---|
222 | else
|
---|
223 | prev->next = target->next;
|
---|
224 |
|
---|
225 | target->next = NULL;
|
---|
226 |
|
---|
227 | break;
|
---|
228 | }
|
---|
229 |
|
---|
230 | return 0;
|
---|
231 | }
|
---|
232 |
|
---|
233 | int
|
---|
234 | _Jv_CondNotifyAll (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu)
|
---|
235 | {
|
---|
236 | if (_Jv_PthreadCheckMonitor (mu))
|
---|
237 | return _JV_NOT_OWNER;
|
---|
238 |
|
---|
239 | _Jv_Thread_t *target;
|
---|
240 | _Jv_Thread_t *prev = NULL;
|
---|
241 |
|
---|
242 | for (target = cv->first; target != NULL; target = target->next)
|
---|
243 | {
|
---|
244 | pthread_mutex_lock (&target->wait_mutex);
|
---|
245 | pthread_cond_signal (&target->wait_cond);
|
---|
246 | pthread_mutex_unlock (&target->wait_mutex);
|
---|
247 |
|
---|
248 | if (prev != NULL)
|
---|
249 | prev->next = NULL;
|
---|
250 | prev = target;
|
---|
251 | }
|
---|
252 | if (prev != NULL)
|
---|
253 | prev->next = NULL;
|
---|
254 |
|
---|
255 | cv->first = NULL;
|
---|
256 |
|
---|
257 | return 0;
|
---|
258 | }
|
---|
259 |
|
---|
260 | void
|
---|
261 | _Jv_ThreadInterrupt (_Jv_Thread_t *data)
|
---|
262 | {
|
---|
263 | pthread_mutex_lock (&data->wait_mutex);
|
---|
264 |
|
---|
265 | // Set the thread's interrupted flag *after* aquiring its wait_mutex. This
|
---|
266 | // ensures that there are no races with the interrupt flag being set after
|
---|
267 | // the waiting thread checks it and before pthread_cond_wait is entered.
|
---|
268 | data->thread_obj->interrupt_flag = true;
|
---|
269 |
|
---|
270 | // Interrupt blocking system calls using a signal.
|
---|
271 | pthread_kill (data->thread, INTR);
|
---|
272 |
|
---|
273 | pthread_cond_signal (&data->wait_cond);
|
---|
274 |
|
---|
275 | pthread_mutex_unlock (&data->wait_mutex);
|
---|
276 | }
|
---|
277 |
|
---|
278 | static void
|
---|
279 | handle_intr (int)
|
---|
280 | {
|
---|
281 | // Do nothing.
|
---|
282 | }
|
---|
283 |
|
---|
284 | void
|
---|
285 | _Jv_InitThreads (void)
|
---|
286 | {
|
---|
287 | pthread_key_create (&_Jv_ThreadKey, NULL);
|
---|
288 | pthread_key_create (&_Jv_ThreadDataKey, NULL);
|
---|
289 | pthread_mutex_init (&daemon_mutex, NULL);
|
---|
290 | pthread_cond_init (&daemon_cond, 0);
|
---|
291 | non_daemon_count = 0;
|
---|
292 |
|
---|
293 | // Arrange for the interrupt signal to interrupt system calls.
|
---|
294 | struct sigaction act;
|
---|
295 | act.sa_handler = handle_intr;
|
---|
296 | sigemptyset (&act.sa_mask);
|
---|
297 | act.sa_flags = 0;
|
---|
298 | sigaction (INTR, &act, NULL);
|
---|
299 | }
|
---|
300 |
|
---|
301 | _Jv_Thread_t *
|
---|
302 | _Jv_ThreadInitData (java::lang::Thread *obj)
|
---|
303 | {
|
---|
304 | _Jv_Thread_t *data = (_Jv_Thread_t *) _Jv_Malloc (sizeof (_Jv_Thread_t));
|
---|
305 | data->flags = 0;
|
---|
306 | data->thread_obj = obj;
|
---|
307 |
|
---|
308 | pthread_mutex_init (&data->wait_mutex, NULL);
|
---|
309 | pthread_cond_init (&data->wait_cond, NULL);
|
---|
310 |
|
---|
311 | return data;
|
---|
312 | }
|
---|
313 |
|
---|
314 | void
|
---|
315 | _Jv_ThreadDestroyData (_Jv_Thread_t *data)
|
---|
316 | {
|
---|
317 | pthread_mutex_destroy (&data->wait_mutex);
|
---|
318 | pthread_cond_destroy (&data->wait_cond);
|
---|
319 | _Jv_Free ((void *)data);
|
---|
320 | }
|
---|
321 |
|
---|
322 | void
|
---|
323 | _Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio)
|
---|
324 | {
|
---|
325 | #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
|
---|
326 | if (data->flags & FLAG_START)
|
---|
327 | {
|
---|
328 | struct sched_param param;
|
---|
329 |
|
---|
330 | param.sched_priority = prio;
|
---|
331 | pthread_setschedparam (data->thread, SCHED_RR, ¶m);
|
---|
332 | }
|
---|
333 | #endif
|
---|
334 | }
|
---|
335 |
|
---|
336 | void
|
---|
337 | _Jv_ThreadRegister (_Jv_Thread_t *data)
|
---|
338 | {
|
---|
339 | pthread_setspecific (_Jv_ThreadKey, data->thread_obj);
|
---|
340 | pthread_setspecific (_Jv_ThreadDataKey, data);
|
---|
341 |
|
---|
342 | // glibc 2.1.3 doesn't set the value of `thread' until after start_routine
|
---|
343 | // is called. Since it may need to be accessed from the new thread, work
|
---|
344 | // around the potential race here by explicitly setting it again.
|
---|
345 | data->thread = pthread_self ();
|
---|
346 |
|
---|
347 | # ifdef SLOW_PTHREAD_SELF
|
---|
348 | // Clear all self cache slots that might be needed by this thread.
|
---|
349 | int dummy;
|
---|
350 | int low_index = SC_INDEX(&dummy) + SC_CLEAR_MIN;
|
---|
351 | int high_index = SC_INDEX(&dummy) + SC_CLEAR_MAX;
|
---|
352 | for (int i = low_index; i <= high_index; ++i)
|
---|
353 | {
|
---|
354 | int current_index = i;
|
---|
355 | if (current_index < 0)
|
---|
356 | current_index += SELF_CACHE_SIZE;
|
---|
357 | if (current_index >= SELF_CACHE_SIZE)
|
---|
358 | current_index -= SELF_CACHE_SIZE;
|
---|
359 | _Jv_self_cache[current_index].high_sp_bits = BAD_HIGH_SP_VALUE;
|
---|
360 | }
|
---|
361 | # endif
|
---|
362 | }
|
---|
363 |
|
---|
364 | void
|
---|
365 | _Jv_ThreadUnRegister ()
|
---|
366 | {
|
---|
367 | pthread_setspecific (_Jv_ThreadKey, NULL);
|
---|
368 | pthread_setspecific (_Jv_ThreadDataKey, NULL);
|
---|
369 | }
|
---|
370 |
|
---|
371 | // This function is called when a thread is started. We don't arrange
|
---|
372 | // to call the `run' method directly, because this function must
|
---|
373 | // return a value.
|
---|
374 | static void *
|
---|
375 | really_start (void *x)
|
---|
376 | {
|
---|
377 | struct starter *info = (struct starter *) x;
|
---|
378 |
|
---|
379 | _Jv_ThreadRegister (info->data);
|
---|
380 |
|
---|
381 | info->method (info->data->thread_obj);
|
---|
382 |
|
---|
383 | if (! (info->data->flags & FLAG_DAEMON))
|
---|
384 | {
|
---|
385 | pthread_mutex_lock (&daemon_mutex);
|
---|
386 | --non_daemon_count;
|
---|
387 | if (! non_daemon_count)
|
---|
388 | pthread_cond_signal (&daemon_cond);
|
---|
389 | pthread_mutex_unlock (&daemon_mutex);
|
---|
390 | }
|
---|
391 |
|
---|
392 | return NULL;
|
---|
393 | }
|
---|
394 |
|
---|
395 | void
|
---|
396 | _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data,
|
---|
397 | _Jv_ThreadStartFunc *meth)
|
---|
398 | {
|
---|
399 | struct sched_param param;
|
---|
400 | pthread_attr_t attr;
|
---|
401 | struct starter *info;
|
---|
402 |
|
---|
403 | if (data->flags & FLAG_START)
|
---|
404 | return;
|
---|
405 | data->flags |= FLAG_START;
|
---|
406 |
|
---|
407 | param.sched_priority = thread->getPriority();
|
---|
408 |
|
---|
409 | pthread_attr_init (&attr);
|
---|
410 | pthread_attr_setschedparam (&attr, ¶m);
|
---|
411 | pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
|
---|
412 |
|
---|
413 | info = (struct starter *) _Jv_AllocBytes (sizeof (struct starter));
|
---|
414 | info->method = meth;
|
---|
415 | info->data = data;
|
---|
416 |
|
---|
417 | if (! thread->isDaemon())
|
---|
418 | {
|
---|
419 | pthread_mutex_lock (&daemon_mutex);
|
---|
420 | ++non_daemon_count;
|
---|
421 | pthread_mutex_unlock (&daemon_mutex);
|
---|
422 | }
|
---|
423 | else
|
---|
424 | data->flags |= FLAG_DAEMON;
|
---|
425 | int r = pthread_create (&data->thread, &attr, really_start, (void *) info);
|
---|
426 |
|
---|
427 | pthread_attr_destroy (&attr);
|
---|
428 |
|
---|
429 | if (r)
|
---|
430 | {
|
---|
431 | const char* msg = "Cannot create additional threads";
|
---|
432 | throw new java::lang::OutOfMemoryError (JvNewStringUTF (msg));
|
---|
433 | }
|
---|
434 | }
|
---|
435 |
|
---|
436 | void
|
---|
437 | _Jv_ThreadWait (void)
|
---|
438 | {
|
---|
439 | pthread_mutex_lock (&daemon_mutex);
|
---|
440 | if (non_daemon_count)
|
---|
441 | pthread_cond_wait (&daemon_cond, &daemon_mutex);
|
---|
442 | pthread_mutex_unlock (&daemon_mutex);
|
---|
443 | }
|
---|
444 |
|
---|
445 | #if defined(SLOW_PTHREAD_SELF)
|
---|
446 |
|
---|
447 | #include "sysdep/locks.h"
|
---|
448 |
|
---|
449 | // Support for pthread_self() lookup cache.
|
---|
450 | volatile self_cache_entry _Jv_self_cache[SELF_CACHE_SIZE];
|
---|
451 |
|
---|
452 | _Jv_ThreadId_t
|
---|
453 | _Jv_ThreadSelf_out_of_line(volatile self_cache_entry *sce, size_t high_sp_bits)
|
---|
454 | {
|
---|
455 | pthread_t self = pthread_self();
|
---|
456 | sce -> high_sp_bits = high_sp_bits;
|
---|
457 | write_barrier();
|
---|
458 | sce -> self = self;
|
---|
459 | return self;
|
---|
460 | }
|
---|
461 |
|
---|
462 | #endif /* SLOW_PTHREAD_SELF */
|
---|