OSDN Git Service

* include/jvm.h: Declare _Jv_RegisterResource.
[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  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 __i386__
225
226 #define SLOW_PTHREAD_SELF
227         // Add a cache for pthread_self() if we don't have the thread
228         // pointer in a register.
229
230 #endif  /* __i386__ */
231
232 #ifdef __ia64__
233
234 typedef size_t _Jv_ThreadId_t;
235
236 register size_t _Jv_self __asm__("r13");
237         // For linux_threads this is really a pointer to its thread data
238         // structure.  We treat it as opaque.  That should also work
239         // on other operating systems that follow the ABI standard.
240
241 // This should become the prototype for machines that maintain a thread
242 // pointer in a register.
243 inline _Jv_ThreadId_t
244 _Jv_ThreadSelf (void)
245 {
246   return _Jv_self;
247 }
248
249 #define JV_SELF_DEFINED
250
251 #endif /* __ia64__ */
252
253 #ifdef __alpha__
254
255 #include <asm/pal.h>
256
257 typedef unsigned long _Jv_ThreadId_t;
258
259 inline _Jv_ThreadId_t
260 _Jv_ThreadSelf (void)
261 {
262   unsigned long id;
263   __asm__ ("call_pal %1\n\tmov $0, %0" : "=r"(id) : "i"(PAL_rduniq) : "$0");
264   return id;
265 }
266
267 #define JV_SELF_DEFINED
268
269 #endif /* __alpha__ */
270
271 #if defined(SLOW_PTHREAD_SELF)
272
273 typedef pthread_t _Jv_ThreadId_t;
274
275 // E.g. on X86 Linux, pthread_self() is too slow for our purpose.
276 // Instead we maintain a cache based on the current sp value.
277 // This is similar to what's done for thread local allocation in the
278 // GC, only far simpler.
279 // This code should probably go away when Linux/X86 starts using a
280 // segment register to hold the thread id.
281 # define LOG_THREAD_SPACING 12
282                         // If two thread pointer values are closer than
283                         // 1 << LOG_THREAD_SPACING, we assume they belong
284                         // to the same thread.
285 # define SELF_CACHE_SIZE 1024
286 # define SC_INDEX(sp) (((unsigned long)(sp) >> 19) & (SELF_CACHE_SIZE-1))
287                         // Mapping from sp value to cache index.
288                         // Note that this is not in any real sense a hash
289                         // function, since we need to be able to clear
290                         // all possibly matching slots on thread startup.
291                         // Thus all entries that might correspond to
292                         // a given thread are intentionally contiguous.
293                         // Works well with anything that allocates at least
294                         // 512KB stacks.
295 # define SC_CLEAR_MIN (-16)     // When starting a new thread, we clear
296 # define SC_CLEAR_MAX 0         // all self cache entries between
297                                 // SC_INDEX(sp)+SC_CLEAR_MIN and
298                                 // SC_INDEX(sp)+SC_CLEAR_MAX to ensure
299                                 // we never see stale values.  The
300                                 // current values assume a downward
301                                 // growing stack of size <= 7.5 MB.
302 # define BAD_HIGH_SP_VALUE ((size_t)(-1))
303
304 extern volatile
305 struct self_cache_entry {
306   size_t high_sp_bits;  // sp value >> LOG_THREAD_SPACING
307   pthread_t self;       // Corresponding thread
308 } _Jv_self_cache[];
309
310 void _Jv_Self_Cache_Init();
311
312 _Jv_ThreadId_t
313 _Jv_ThreadSelf_out_of_line(volatile self_cache_entry *sce,
314                            size_t high_sp_bits);
315   
316 inline _Jv_ThreadId_t
317 _Jv_ThreadSelf (void)
318 {
319   int dummy;
320   size_t sp = (size_t)(&dummy);
321   unsigned h = SC_INDEX(sp);
322   volatile self_cache_entry *sce = _Jv_self_cache + h;
323   pthread_t candidate_self = sce -> self;  // Read must precede following one.
324   // Read barrier goes here, if needed.
325   if (sce -> high_sp_bits == sp >> LOG_THREAD_SPACING)
326     {
327       // The sce -> self value we read must be valid.  An intervening
328       // cache replacement by another thread would have first replaced
329       // high_sp_bits by something else, and it can't possibly change
330       // back without our intervention.
331       return candidate_self;
332     }
333   else
334     return _Jv_ThreadSelf_out_of_line(sce, sp >> LOG_THREAD_SPACING);
335 }
336
337 #define JV_SELF_DEFINED
338
339 #endif /* SLOW_PTHREAD_SELF */
340
341 #ifndef JV_SELF_DEFINED /* If all else fails, call pthread_self directly */
342
343 typedef pthread_t _Jv_ThreadId_t;
344
345 inline _Jv_ThreadId_t
346 _Jv_ThreadSelf (void)
347 {
348   return pthread_self();
349 }
350
351 #endif /* !JV_SELF_DEFINED */
352
353 #endif /* JV_HASH_SYNCHRONIZATION */
354
355 inline _Jv_Thread_t *
356 _Jv_ThreadCurrentData (void)
357 {
358   extern pthread_key_t _Jv_ThreadDataKey;
359   return (_Jv_Thread_t *) pthread_getspecific (_Jv_ThreadDataKey);
360 }
361
362 inline void
363 _Jv_ThreadYield (void)
364 {
365 #ifdef HAVE_SCHED_YIELD
366   sched_yield ();
367 #endif /* HAVE_SCHED_YIELD */
368 }
369
370 void _Jv_ThreadRegister (_Jv_Thread_t *data);
371 void _Jv_ThreadUnRegister ();
372
373 void _Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio);
374
375 void _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data,
376                       _Jv_ThreadStartFunc *meth);
377
378 void _Jv_ThreadWait (void);
379
380 void _Jv_ThreadInterrupt (_Jv_Thread_t *data);
381
382 #endif /* __JV_POSIX_THREADS__ */