1 | // -*- c++ -*-
|
---|
2 | // posix-threads.h - Defines for using POSIX threads.
|
---|
3 |
|
---|
4 | /* Copyright (C) 1998, 1999, 2001 Free Software Foundation
|
---|
5 |
|
---|
6 | This file is part of libgcj.
|
---|
7 |
|
---|
8 | This software is copyrighted work licensed under the terms of the
|
---|
9 | Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
---|
10 | details. */
|
---|
11 |
|
---|
12 | #ifndef __JV_POSIX_THREADS__
|
---|
13 | #define __JV_POSIX_THREADS__
|
---|
14 |
|
---|
15 | // NOTE: This file may only reference those pthread functions which
|
---|
16 | // are known not to be overridden by the Boehm GC. If in doubt, scan
|
---|
17 | // boehm-gc/gc.h. This is yucky but lets us avoid including gc.h
|
---|
18 | // everywhere (which would be truly yucky).
|
---|
19 |
|
---|
20 | #include <pthread.h>
|
---|
21 | #include <sched.h>
|
---|
22 |
|
---|
23 | //
|
---|
24 | // Typedefs.
|
---|
25 | //
|
---|
26 |
|
---|
27 | typedef struct _Jv_Thread_t
|
---|
28 | {
|
---|
29 | // Flag values are defined in implementation.
|
---|
30 | int flags;
|
---|
31 |
|
---|
32 | // Actual thread id.
|
---|
33 | pthread_t thread;
|
---|
34 |
|
---|
35 | // Java Thread object.
|
---|
36 | java::lang::Thread *thread_obj;
|
---|
37 |
|
---|
38 | // Condition variable and corresponding mutex, used to implement the
|
---|
39 | // interruptable wait/notify mechanism.
|
---|
40 | pthread_cond_t wait_cond;
|
---|
41 | pthread_mutex_t wait_mutex;
|
---|
42 |
|
---|
43 | // Next thread for Condition Variable wait-list chain.
|
---|
44 | _Jv_Thread_t *next;
|
---|
45 |
|
---|
46 | } _Jv_Thread_t;
|
---|
47 |
|
---|
48 | typedef void _Jv_ThreadStartFunc (java::lang::Thread *);
|
---|
49 |
|
---|
50 |
|
---|
51 | // Condition Variables used to implement wait/notify/sleep/interrupt.
|
---|
52 | typedef struct
|
---|
53 | {
|
---|
54 | // Linked list of Threads that are waiting to be notified.
|
---|
55 | _Jv_Thread_t *first;
|
---|
56 |
|
---|
57 | } _Jv_ConditionVariable_t;
|
---|
58 |
|
---|
59 | typedef struct
|
---|
60 | {
|
---|
61 | // For compatibility, simplicity, and correctness, we do not use the native
|
---|
62 | // pthreads recursive mutex implementation, but simulate them instead.
|
---|
63 |
|
---|
64 | // Mutex the thread holds the entire time this mutex is held.
|
---|
65 | pthread_mutex_t mutex;
|
---|
66 |
|
---|
67 | // Thread holding this mutex.
|
---|
68 | pthread_t owner;
|
---|
69 |
|
---|
70 | // Number of times mutex is held (lock depth). If 0, the lock is not held.
|
---|
71 | int count;
|
---|
72 | } _Jv_Mutex_t;
|
---|
73 |
|
---|
74 | // This is a convenience function used only by the pthreads thread
|
---|
75 | // implementation. This is slow, but that's too bad -- we need to do
|
---|
76 | // the checks for correctness. It might be nice to be able to compile
|
---|
77 | // this out. Returns 0 if the lock is held by the current thread, and
|
---|
78 | // 1 otherwise.
|
---|
79 | inline int
|
---|
80 | _Jv_PthreadCheckMonitor (_Jv_Mutex_t *mu)
|
---|
81 | {
|
---|
82 | pthread_t self = pthread_self();
|
---|
83 | if (mu->owner == self)
|
---|
84 | return 0;
|
---|
85 | else return 1;
|
---|
86 | }
|
---|
87 |
|
---|
88 | //
|
---|
89 | // Condition variables.
|
---|
90 | //
|
---|
91 |
|
---|
92 | int _Jv_CondWait (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu,
|
---|
93 | jlong millis, jint nanos);
|
---|
94 |
|
---|
95 | int _Jv_CondNotify (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu);
|
---|
96 |
|
---|
97 | int _Jv_CondNotifyAll (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu);
|
---|
98 |
|
---|
99 | inline void
|
---|
100 | _Jv_CondInit (_Jv_ConditionVariable_t *cv)
|
---|
101 | {
|
---|
102 | cv->first = 0;
|
---|
103 | }
|
---|
104 |
|
---|
105 | //
|
---|
106 | // Mutexes.
|
---|
107 | //
|
---|
108 |
|
---|
109 | #ifdef LOCK_DEBUG
|
---|
110 | # include <stdio.h>
|
---|
111 | #endif
|
---|
112 |
|
---|
113 | inline void
|
---|
114 | _Jv_MutexInit (_Jv_Mutex_t *mu)
|
---|
115 | {
|
---|
116 | # ifdef LOCK_DEBUG /* Assumes Linuxthreads */
|
---|
117 | pthread_mutexattr_t attr;
|
---|
118 | pthread_mutexattr_init(&attr);
|
---|
119 | pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
|
---|
120 | pthread_mutex_init (&mu->mutex, &attr);
|
---|
121 | # else
|
---|
122 | pthread_mutex_init (&mu->mutex, 0);
|
---|
123 | # endif
|
---|
124 |
|
---|
125 | mu->count = 0;
|
---|
126 | mu->owner = 0;
|
---|
127 | }
|
---|
128 |
|
---|
129 | inline int
|
---|
130 | _Jv_MutexLock (_Jv_Mutex_t *mu)
|
---|
131 | {
|
---|
132 | pthread_t self = pthread_self ();
|
---|
133 | if (mu->owner == self)
|
---|
134 | {
|
---|
135 | mu->count++;
|
---|
136 | }
|
---|
137 | else
|
---|
138 | {
|
---|
139 | # ifdef LOCK_DEBUG
|
---|
140 | int result = pthread_mutex_lock (&mu->mutex);
|
---|
141 | if (0 != result)
|
---|
142 | {
|
---|
143 | fprintf(stderr, "Pthread_mutex_lock returned %d\n", result);
|
---|
144 | for (;;) {}
|
---|
145 | }
|
---|
146 | # else
|
---|
147 | pthread_mutex_lock (&mu->mutex);
|
---|
148 | # endif
|
---|
149 | mu->count = 1;
|
---|
150 | mu->owner = self;
|
---|
151 | }
|
---|
152 | return 0;
|
---|
153 | }
|
---|
154 |
|
---|
155 | inline int
|
---|
156 | _Jv_MutexUnlock (_Jv_Mutex_t *mu)
|
---|
157 | {
|
---|
158 | if (_Jv_PthreadCheckMonitor (mu))
|
---|
159 | {
|
---|
160 | # ifdef LOCK_DEBUG
|
---|
161 | fprintf(stderr, "_Jv_MutexUnlock: Not owner\n");
|
---|
162 | for (;;) {}
|
---|
163 | # endif
|
---|
164 | return 1;
|
---|
165 | }
|
---|
166 |
|
---|
167 | mu->count--;
|
---|
168 |
|
---|
169 | if (mu->count == 0)
|
---|
170 | {
|
---|
171 | mu->owner = 0;
|
---|
172 | # ifdef LOCK_DEBUG
|
---|
173 | int result = pthread_mutex_unlock (&mu->mutex);
|
---|
174 | if (0 != result)
|
---|
175 | {
|
---|
176 | fprintf(stderr, "Pthread_mutex_unlock returned %d\n", result);
|
---|
177 | for (;;) {}
|
---|
178 | }
|
---|
179 | # else
|
---|
180 | pthread_mutex_unlock (&mu->mutex);
|
---|
181 | # endif
|
---|
182 | }
|
---|
183 | return 0;
|
---|
184 | }
|
---|
185 |
|
---|
186 | #ifndef LINUX_THREADS
|
---|
187 |
|
---|
188 | // pthread_mutex_destroy does nothing on Linux and it is a win to avoid
|
---|
189 | // defining this macro.
|
---|
190 |
|
---|
191 | #define _Jv_HaveMutexDestroy
|
---|
192 |
|
---|
193 | inline void
|
---|
194 | _Jv_MutexDestroy (_Jv_Mutex_t *mu)
|
---|
195 | {
|
---|
196 | pthread_mutex_destroy (&mu->mutex);
|
---|
197 | }
|
---|
198 |
|
---|
199 | #endif /* LINUX_THREADS */
|
---|
200 |
|
---|
201 | //
|
---|
202 | // Thread creation and manipulation.
|
---|
203 | //
|
---|
204 |
|
---|
205 | void _Jv_InitThreads (void);
|
---|
206 |
|
---|
207 | _Jv_Thread_t *_Jv_ThreadInitData (java::lang::Thread *thread);
|
---|
208 | void _Jv_ThreadDestroyData (_Jv_Thread_t *data);
|
---|
209 |
|
---|
210 | inline java::lang::Thread *
|
---|
211 | _Jv_ThreadCurrent (void)
|
---|
212 | {
|
---|
213 | extern pthread_key_t _Jv_ThreadKey;
|
---|
214 | return (java::lang::Thread *) pthread_getspecific (_Jv_ThreadKey);
|
---|
215 | }
|
---|
216 |
|
---|
217 | #ifdef JV_HASH_SYNCHRONIZATION
|
---|
218 | // Should be specialized to just load the "current thread" register
|
---|
219 | // on platforms that support it. Speed is of the essence. The value
|
---|
220 | // of the descriptor is not, so long as there is a one-to-one correspondence
|
---|
221 | // to threads.
|
---|
222 |
|
---|
223 |
|
---|
224 | #ifdef __ia64__
|
---|
225 |
|
---|
226 | typedef size_t _Jv_ThreadId_t;
|
---|
227 |
|
---|
228 | register size_t _Jv_self __asm__("r13");
|
---|
229 | // For linux_threads this is really a pointer to its thread data
|
---|
230 | // structure. We treat it as opaque. That should also work
|
---|
231 | // on other operating systems that follow the ABI standard.
|
---|
232 |
|
---|
233 | // This should become the prototype for machines that maintain a thread
|
---|
234 | // pointer in a register.
|
---|
235 | inline _Jv_ThreadId_t
|
---|
236 | _Jv_ThreadSelf (void)
|
---|
237 | {
|
---|
238 | return _Jv_self;
|
---|
239 | }
|
---|
240 |
|
---|
241 | #define JV_SELF_DEFINED
|
---|
242 |
|
---|
243 | #endif /* __ia64__ */
|
---|
244 |
|
---|
245 | #ifdef __alpha__
|
---|
246 |
|
---|
247 | #ifdef __FreeBSD__
|
---|
248 | #include <machine/pal.h>
|
---|
249 | #define PAL_rduniq PAL_rdunique
|
---|
250 | #else
|
---|
251 | #include <asm/pal.h>
|
---|
252 | #endif
|
---|
253 |
|
---|
254 | typedef unsigned long _Jv_ThreadId_t;
|
---|
255 |
|
---|
256 | inline _Jv_ThreadId_t
|
---|
257 | _Jv_ThreadSelf (void)
|
---|
258 | {
|
---|
259 | unsigned long id;
|
---|
260 | __asm__ ("call_pal %1\n\tmov $0, %0" : "=r"(id) : "i"(PAL_rduniq) : "$0");
|
---|
261 | return id;
|
---|
262 | }
|
---|
263 |
|
---|
264 | #define JV_SELF_DEFINED
|
---|
265 |
|
---|
266 | #endif /* __alpha__ */
|
---|
267 |
|
---|
268 | #if defined(SLOW_PTHREAD_SELF)
|
---|
269 |
|
---|
270 | #include "sysdep/locks.h"
|
---|
271 |
|
---|
272 | typedef pthread_t _Jv_ThreadId_t;
|
---|
273 |
|
---|
274 | // E.g. on X86 Linux, pthread_self() is too slow for our purpose.
|
---|
275 | // Instead we maintain a cache based on the current sp value.
|
---|
276 | // This is similar to what's done for thread local allocation in the
|
---|
277 | // GC, only far simpler.
|
---|
278 | // This code should probably go away when Linux/X86 starts using a
|
---|
279 | // segment register to hold the thread id.
|
---|
280 | # define LOG_THREAD_SPACING 12
|
---|
281 | // If two thread pointer values are closer than
|
---|
282 | // 1 << LOG_THREAD_SPACING, we assume they belong
|
---|
283 | // to the same thread.
|
---|
284 | # define SELF_CACHE_SIZE 1024
|
---|
285 | # define SC_INDEX(sp) (((unsigned long)(sp) >> 19) & (SELF_CACHE_SIZE-1))
|
---|
286 | // Mapping from sp value to cache index.
|
---|
287 | // Note that this is not in any real sense a hash
|
---|
288 | // function, since we need to be able to clear
|
---|
289 | // all possibly matching slots on thread startup.
|
---|
290 | // Thus all entries that might correspond to
|
---|
291 | // a given thread are intentionally contiguous.
|
---|
292 | // Works well with anything that allocates at least
|
---|
293 | // 512KB stacks.
|
---|
294 | # define SC_CLEAR_MIN (-16) // When starting a new thread, we clear
|
---|
295 | # define SC_CLEAR_MAX 0 // all self cache entries between
|
---|
296 | // SC_INDEX(sp)+SC_CLEAR_MIN and
|
---|
297 | // SC_INDEX(sp)+SC_CLEAR_MAX to ensure
|
---|
298 | // we never see stale values. The
|
---|
299 | // current values assume a downward
|
---|
300 | // growing stack of size <= 7.5 MB.
|
---|
301 | # define BAD_HIGH_SP_VALUE ((size_t)(-1))
|
---|
302 |
|
---|
303 | extern volatile
|
---|
304 | struct self_cache_entry {
|
---|
305 | size_t high_sp_bits; // sp value >> LOG_THREAD_SPACING
|
---|
306 | pthread_t self; // Corresponding thread
|
---|
307 | } _Jv_self_cache[];
|
---|
308 |
|
---|
309 | void _Jv_Self_Cache_Init();
|
---|
310 |
|
---|
311 | _Jv_ThreadId_t
|
---|
312 | _Jv_ThreadSelf_out_of_line(volatile self_cache_entry *sce,
|
---|
313 | size_t high_sp_bits);
|
---|
314 |
|
---|
315 | inline _Jv_ThreadId_t
|
---|
316 | _Jv_ThreadSelf (void)
|
---|
317 | {
|
---|
318 | int dummy;
|
---|
319 | size_t sp = (size_t)(&dummy);
|
---|
320 | unsigned h = SC_INDEX(sp);
|
---|
321 | volatile self_cache_entry *sce = _Jv_self_cache + h;
|
---|
322 | pthread_t candidate_self = sce -> self; // Read must precede following one.
|
---|
323 | read_barrier();
|
---|
324 | if (sce -> high_sp_bits == sp >> LOG_THREAD_SPACING)
|
---|
325 | {
|
---|
326 | // The sce -> self value we read must be valid. An intervening
|
---|
327 | // cache replacement by another thread would have first replaced
|
---|
328 | // high_sp_bits by something else, and it can't possibly change
|
---|
329 | // back without our intervention.
|
---|
330 | return candidate_self;
|
---|
331 | }
|
---|
332 | else
|
---|
333 | return _Jv_ThreadSelf_out_of_line(sce, sp >> LOG_THREAD_SPACING);
|
---|
334 | }
|
---|
335 |
|
---|
336 | #define JV_SELF_DEFINED
|
---|
337 |
|
---|
338 | #endif /* SLOW_PTHREAD_SELF */
|
---|
339 |
|
---|
340 | #ifndef JV_SELF_DEFINED /* If all else fails, call pthread_self directly */
|
---|
341 |
|
---|
342 | typedef pthread_t _Jv_ThreadId_t;
|
---|
343 |
|
---|
344 | inline _Jv_ThreadId_t
|
---|
345 | _Jv_ThreadSelf (void)
|
---|
346 | {
|
---|
347 | return pthread_self();
|
---|
348 | }
|
---|
349 |
|
---|
350 | #endif /* !JV_SELF_DEFINED */
|
---|
351 |
|
---|
352 | #endif /* JV_HASH_SYNCHRONIZATION */
|
---|
353 |
|
---|
354 | inline _Jv_Thread_t *
|
---|
355 | _Jv_ThreadCurrentData (void)
|
---|
356 | {
|
---|
357 | extern pthread_key_t _Jv_ThreadDataKey;
|
---|
358 | return (_Jv_Thread_t *) pthread_getspecific (_Jv_ThreadDataKey);
|
---|
359 | }
|
---|
360 |
|
---|
361 | inline void
|
---|
362 | _Jv_ThreadYield (void)
|
---|
363 | {
|
---|
364 | #ifdef HAVE_SCHED_YIELD
|
---|
365 | sched_yield ();
|
---|
366 | #endif /* HAVE_SCHED_YIELD */
|
---|
367 | }
|
---|
368 |
|
---|
369 | void _Jv_ThreadRegister (_Jv_Thread_t *data);
|
---|
370 | void _Jv_ThreadUnRegister ();
|
---|
371 |
|
---|
372 | void _Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio);
|
---|
373 |
|
---|
374 | void _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data,
|
---|
375 | _Jv_ThreadStartFunc *meth);
|
---|
376 |
|
---|
377 | void _Jv_ThreadWait (void);
|
---|
378 |
|
---|
379 | void _Jv_ThreadInterrupt (_Jv_Thread_t *data);
|
---|
380 |
|
---|
381 | #endif /* __JV_POSIX_THREADS__ */
|
---|