2003-10-01 Nathan Myers <ncm@cantrip.org>
[official-gcc.git] / libjava / include / posix-threads.h
blob6c8dcec933c1ca4b40836fc2ee77f364d5647c28
1 // -*- c++ -*-
2 // posix-threads.h - Defines for using POSIX threads.
4 /* Copyright (C) 1998, 1999, 2001, 2003 Free Software Foundation
6 This file is part of libgcj.
8 This software is copyrighted work licensed under the terms of the
9 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
10 details. */
12 #ifndef __JV_POSIX_THREADS__
13 #define __JV_POSIX_THREADS__
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).
20 #include <pthread.h>
21 #include <sched.h>
24 // Typedefs.
27 typedef struct _Jv_Thread_t
29 // Flag values are defined in implementation.
30 int flags;
32 // Actual thread id.
33 pthread_t thread;
35 // Java Thread object.
36 java::lang::Thread *thread_obj;
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;
43 // Next thread for Condition Variable wait-list chain.
44 _Jv_Thread_t *next;
46 } _Jv_Thread_t;
48 typedef void _Jv_ThreadStartFunc (java::lang::Thread *);
51 // Condition Variables used to implement wait/notify/sleep/interrupt.
52 typedef struct
54 // Linked list of Threads that are waiting to be notified.
55 _Jv_Thread_t *first;
57 } _Jv_ConditionVariable_t;
59 typedef struct
61 // For compatibility, simplicity, and correctness, we do not use the native
62 // pthreads recursive mutex implementation, but simulate them instead.
64 // Mutex the thread holds the entire time this mutex is held.
65 pthread_mutex_t mutex;
67 // Thread holding this mutex.
68 pthread_t owner;
70 // Number of times mutex is held (lock depth). If 0, the lock is not held.
71 int count;
72 } _Jv_Mutex_t;
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)
82 pthread_t self = pthread_self();
83 if (mu->owner == self)
84 return 0;
85 else return 1;
89 // Condition variables.
92 int _Jv_CondWait (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu,
93 jlong millis, jint nanos);
95 int _Jv_CondNotify (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu);
97 int _Jv_CondNotifyAll (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu);
99 inline void
100 _Jv_CondInit (_Jv_ConditionVariable_t *cv)
102 cv->first = 0;
106 // Mutexes.
109 #ifdef LOCK_DEBUG
110 # include <stdio.h>
111 #endif
113 inline void
114 _Jv_MutexInit (_Jv_Mutex_t *mu)
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
125 mu->count = 0;
126 mu->owner = 0;
129 inline int
130 _Jv_MutexLock (_Jv_Mutex_t *mu)
132 pthread_t self = pthread_self ();
133 if (mu->owner == self)
135 mu->count++;
137 else
139 # ifdef LOCK_DEBUG
140 int result = pthread_mutex_lock (&mu->mutex);
141 if (0 != result)
143 fprintf(stderr, "Pthread_mutex_lock returned %d\n", result);
144 for (;;) {}
146 # else
147 pthread_mutex_lock (&mu->mutex);
148 # endif
149 mu->count = 1;
150 mu->owner = self;
152 return 0;
155 inline int
156 _Jv_MutexUnlock (_Jv_Mutex_t *mu)
158 if (_Jv_PthreadCheckMonitor (mu))
160 # ifdef LOCK_DEBUG
161 fprintf(stderr, "_Jv_MutexUnlock: Not owner\n");
162 for (;;) {}
163 # endif
164 return 1;
167 mu->count--;
169 if (mu->count == 0)
171 mu->owner = 0;
172 # ifdef LOCK_DEBUG
173 int result = pthread_mutex_unlock (&mu->mutex);
174 if (0 != result)
176 fprintf(stderr, "Pthread_mutex_unlock returned %d\n", result);
177 for (;;) {}
179 # else
180 pthread_mutex_unlock (&mu->mutex);
181 # endif
183 return 0;
186 #ifndef LINUX_THREADS
188 // pthread_mutex_destroy does nothing on Linux and it is a win to avoid
189 // defining this macro.
191 #define _Jv_HaveMutexDestroy
193 inline void
194 _Jv_MutexDestroy (_Jv_Mutex_t *mu)
196 pthread_mutex_destroy (&mu->mutex);
199 #endif /* LINUX_THREADS */
202 // Thread creation and manipulation.
205 void _Jv_InitThreads (void);
207 _Jv_Thread_t *_Jv_ThreadInitData (java::lang::Thread *thread);
208 void _Jv_ThreadDestroyData (_Jv_Thread_t *data);
210 inline java::lang::Thread *
211 _Jv_ThreadCurrent (void)
213 extern pthread_key_t _Jv_ThreadKey;
214 return (java::lang::Thread *) pthread_getspecific (_Jv_ThreadKey);
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.
224 #ifdef __ia64__
226 typedef size_t _Jv_ThreadId_t;
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.
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)
238 return _Jv_self;
241 #define JV_SELF_DEFINED
243 #endif /* __ia64__ */
245 #ifdef __alpha__
247 #ifdef __FreeBSD__
248 #include <machine/pal.h>
249 #define PAL_rduniq PAL_rdunique
250 #elif defined (__osf__)
251 #include <machine/pal.h>
252 #else
253 #include <asm/pal.h>
254 #endif
256 typedef unsigned long _Jv_ThreadId_t;
258 inline _Jv_ThreadId_t
259 _Jv_ThreadSelf (void)
261 register unsigned long id __asm__("$0");
262 __asm__ ("call_pal %1" : "=r"(id) : "i"(PAL_rduniq));
263 return id;
266 #define JV_SELF_DEFINED
268 #endif /* __alpha__ */
270 #if defined(SLOW_PTHREAD_SELF)
272 #include "sysdep/locks.h"
274 typedef pthread_t _Jv_ThreadId_t;
276 // E.g. on X86 Linux, pthread_self() is too slow for our purpose.
277 // Instead we maintain a cache based on the current sp value.
278 // This is similar to what's done for thread local allocation in the
279 // GC, only far simpler.
280 // This code should probably go away when Linux/X86 starts using a
281 // segment register to hold the thread id.
282 # define LOG_THREAD_SPACING 12
283 // If two thread pointer values are closer than
284 // 1 << LOG_THREAD_SPACING, we assume they belong
285 // to the same thread.
286 # define SELF_CACHE_SIZE 1024
287 # define SC_INDEX(sp) (((unsigned long)(sp) >> 19) & (SELF_CACHE_SIZE-1))
288 // Mapping from sp value to cache index.
289 // Note that this is not in any real sense a hash
290 // function, since we need to be able to clear
291 // all possibly matching slots on thread startup.
292 // Thus all entries that might correspond to
293 // a given thread are intentionally contiguous.
294 // Works well with anything that allocates at least
295 // 512KB stacks.
296 # define SC_CLEAR_MIN (-16) // When starting a new thread, we clear
297 # define SC_CLEAR_MAX 0 // all self cache entries between
298 // SC_INDEX(sp)+SC_CLEAR_MIN and
299 // SC_INDEX(sp)+SC_CLEAR_MAX to ensure
300 // we never see stale values. The
301 // current values assume a downward
302 // growing stack of size <= 7.5 MB.
303 # define BAD_HIGH_SP_VALUE ((size_t)(-1))
305 extern volatile
306 struct self_cache_entry {
307 size_t high_sp_bits; // sp value >> LOG_THREAD_SPACING
308 pthread_t self; // Corresponding thread
309 } _Jv_self_cache[];
311 void _Jv_Self_Cache_Init();
313 _Jv_ThreadId_t
314 _Jv_ThreadSelf_out_of_line(volatile self_cache_entry *sce,
315 size_t high_sp_bits);
317 inline _Jv_ThreadId_t
318 _Jv_ThreadSelf (void)
320 int dummy;
321 size_t sp = (size_t)(&dummy);
322 unsigned h = SC_INDEX(sp);
323 volatile self_cache_entry *sce = _Jv_self_cache + h;
324 pthread_t candidate_self = sce -> self; // Read must precede following one.
325 read_barrier();
326 if (sce -> high_sp_bits == sp >> LOG_THREAD_SPACING)
328 // The sce -> self value we read must be valid. An intervening
329 // cache replacement by another thread would have first replaced
330 // high_sp_bits by something else, and it can't possibly change
331 // back without our intervention.
332 return candidate_self;
334 else
335 return _Jv_ThreadSelf_out_of_line(sce, sp >> LOG_THREAD_SPACING);
338 #define JV_SELF_DEFINED
340 #endif /* SLOW_PTHREAD_SELF */
342 #ifndef JV_SELF_DEFINED /* If all else fails, call pthread_self directly */
344 typedef pthread_t _Jv_ThreadId_t;
346 inline _Jv_ThreadId_t
347 _Jv_ThreadSelf (void)
349 return pthread_self();
352 #endif /* !JV_SELF_DEFINED */
354 #endif /* JV_HASH_SYNCHRONIZATION */
356 inline _Jv_Thread_t *
357 _Jv_ThreadCurrentData (void)
359 extern pthread_key_t _Jv_ThreadDataKey;
360 return (_Jv_Thread_t *) pthread_getspecific (_Jv_ThreadDataKey);
363 inline void
364 _Jv_ThreadYield (void)
366 #ifdef HAVE_SCHED_YIELD
367 sched_yield ();
368 #endif /* HAVE_SCHED_YIELD */
371 void _Jv_ThreadRegister (_Jv_Thread_t *data);
372 void _Jv_ThreadUnRegister ();
374 void _Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio);
376 void _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data,
377 _Jv_ThreadStartFunc *meth);
379 void _Jv_ThreadWait (void);
381 void _Jv_ThreadInterrupt (_Jv_Thread_t *data);
383 #endif /* __JV_POSIX_THREADS__ */