OSDN Git Service

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