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