source: branches/libc-0.6/src/gcc/libjava/include/posix-threads.h

Last change on this file was 1392, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 9.0 KB
Line 
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
8This software is copyrighted work licensed under the terms of the
9Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
10details. */
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
27typedef 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
48typedef void _Jv_ThreadStartFunc (java::lang::Thread *);
49
50
51// Condition Variables used to implement wait/notify/sleep/interrupt.
52typedef struct
53{
54 // Linked list of Threads that are waiting to be notified.
55 _Jv_Thread_t *first;
56
57} _Jv_ConditionVariable_t;
58
59typedef 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.
79inline 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
92int _Jv_CondWait (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu,
93 jlong millis, jint nanos);
94
95int _Jv_CondNotify (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu);
96
97int _Jv_CondNotifyAll (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu);
98
99inline 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
113inline 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
129inline 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
155inline 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
193inline 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
205void _Jv_InitThreads (void);
206
207_Jv_Thread_t *_Jv_ThreadInitData (java::lang::Thread *thread);
208void _Jv_ThreadDestroyData (_Jv_Thread_t *data);
209
210inline 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
226typedef size_t _Jv_ThreadId_t;
227
228register 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.
235inline _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
254typedef unsigned long _Jv_ThreadId_t;
255
256inline _Jv_ThreadId_t
257_Jv_ThreadSelf (void)
258{
259 register unsigned long id __asm__("$0");
260 __asm__ ("call_pal %1" : "=r"(id) : "i"(PAL_rduniq));
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
272typedef 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
303extern volatile
304struct 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
309void _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
315inline _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
342typedef pthread_t _Jv_ThreadId_t;
343
344inline _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
354inline _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
361inline void
362_Jv_ThreadYield (void)
363{
364#ifdef HAVE_SCHED_YIELD
365 sched_yield ();
366#endif /* HAVE_SCHED_YIELD */
367}
368
369void _Jv_ThreadRegister (_Jv_Thread_t *data);
370void _Jv_ThreadUnRegister ();
371
372void _Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio);
373
374void _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data,
375 _Jv_ThreadStartFunc *meth);
376
377void _Jv_ThreadWait (void);
378
379void _Jv_ThreadInterrupt (_Jv_Thread_t *data);
380
381#endif /* __JV_POSIX_THREADS__ */
Note: See TracBrowser for help on using the repository browser.