source: vendor/gcc/3.2.2/libjava/include/posix-threads.h

Last change on this file was 2, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • 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 unsigned long id;
260 __asm__ ("call_pal %1\n\tmov $0, %0" : "=r"(id) : "i"(PAL_rduniq) : "$0");
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.