OSDN Git Service

* All files: Updated copyright information.
[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  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 #if defined (HAVE_PTHREAD_MUTEXATTR_SETTYPE) || defined (HAVE_PTHREAD_MUTEXATTR_SETKIND_NP)
24 #  define HAVE_RECURSIVE_MUTEX 1
25 #endif
26
27
28 //
29 // Typedefs.
30 //
31
32 typedef pthread_cond_t _Jv_ConditionVariable_t;
33
34 #if defined (PTHREAD_MUTEX_HAVE_M_COUNT) || defined (PTHREAD_MUTEX_HAVE___M_COUNT)
35
36 // On Linux we use implementation details of mutexes in order to get
37 // faster results.
38 typedef pthread_mutex_t _Jv_Mutex_t;
39
40 #else /* LINUX_THREADS */
41
42 #define PTHREAD_MUTEX_IS_STRUCT
43
44 typedef struct
45 {
46   // Mutex used when locking this structure transiently.
47   pthread_mutex_t mutex;
48 #ifndef HAVE_RECURSIVE_MUTEX
49   // Some systems do not have recursive mutexes, so we must simulate
50   // them.  Solaris is one such system.
51
52   // Mutex the thread holds the entire time this mutex is held.  This
53   // is used to make condition variables work properly.
54   pthread_mutex_t mutex2;
55   // Condition variable used when waiting for this lock.
56   pthread_cond_t cond;
57   // Thread holding this mutex.  If COUNT is 0, no thread is holding.
58   pthread_t thread;
59 #endif /* HAVE_RECURSIVE_MUTEX */
60
61   // Number of times mutex is held.  If 0, the lock is not held.  We
62   // do this even if we have a native recursive mutex so that we can
63   // keep track of whether the lock is held; this lets us do error
64   // checking.  FIXME it would be nice to optimize this; on some
65   // systems we could do so by relying on implementation details of
66   // recursive mutexes.
67   int count;
68 } _Jv_Mutex_t;
69
70 #endif
71
72 typedef struct
73 {
74   // Flag values are defined in implementation.
75   int flags;
76
77   // Actual thread id.
78   pthread_t thread;
79 } _Jv_Thread_t;
80 typedef void _Jv_ThreadStartFunc (java::lang::Thread *);
81
82
83 // This convenience function is used to return the POSIX mutex
84 // corresponding to our mutex.
85 inline pthread_mutex_t *
86 _Jv_PthreadGetMutex (_Jv_Mutex_t *mu)
87 {
88 #if ! defined (PTHREAD_MUTEX_IS_STRUCT)
89   return mu;
90 #elif defined (HAVE_RECURSIVE_MUTEX)
91   return &mu->mutex;
92 #else
93   return &mu->mutex2;
94 #endif
95 }
96
97 #include <stdio.h>
98
99 // This is a convenience function used only by the pthreads thread
100 // implementation.  This is slow, but that's too bad -- we need to do
101 // the checks for correctness.  It might be nice to be able to compile
102 // this out.  Returns 0 if the lock is held by the current thread, and
103 // 1 otherwise.
104 inline int
105 _Jv_PthreadCheckMonitor (_Jv_Mutex_t *mu)
106 {
107   pthread_mutex_t *pmu;
108 #ifdef HAVE_RECURSIVE_MUTEX
109   pmu = _Jv_PthreadGetMutex (mu);
110   // See if the mutex is locked by this thread.
111   if (pthread_mutex_trylock (pmu))
112     return 1;
113
114 #if defined (PTHREAD_MUTEX_HAVE_M_COUNT)
115   // On Linux we exploit knowledge of the implementation.
116   int r = pmu->m_count == 1;
117 #elif defined (PTHREAD_MUTEX_HAVE___M_COUNT)
118   // In glibc 2.1, the first time the mutex is grabbed __m_count is
119   // set to 0 and __m_owner is set to pthread_self().
120   int r = ! pmu->__m_count;
121 #else
122   int r = mu->count == 0;
123 #endif
124
125 #else /* HAVE_RECURSIVE_MUTEX */
126   // In this case we must lock our structure and then see if this
127   // thread owns the mutex.
128   pmu = &mu->mutex;
129   if (pthread_mutex_lock (pmu))
130     return 1;
131
132   int r = mu->thread != pthread_self () || mu->count == 0;
133 #endif /* HAVE_RECURSIVE_MUTEX */
134
135   pthread_mutex_unlock (pmu);
136   return r;
137 }
138
139 //
140 // Condition variables.
141 //
142
143 inline void
144 _Jv_CondInit (_Jv_ConditionVariable_t *cv)
145 {
146   pthread_cond_init (cv, 0);
147 }
148
149 #ifndef LINUX_THREADS
150
151 // pthread_cond_destroy does nothing on Linux and it is a win to avoid
152 // defining this macro.
153
154 #define _Jv_HaveCondDestroy
155
156 inline void
157 _Jv_CondDestroy (_Jv_ConditionVariable_t *cv)
158 {
159   pthread_cond_destroy (cv);
160 }
161
162 #endif /* LINUX_THREADS */
163
164 int _Jv_CondWait (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu,
165                   jlong millis, jint nanos);
166
167 inline int
168 _Jv_CondNotify (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu)
169 {
170   return _Jv_PthreadCheckMonitor (mu) || pthread_cond_signal (cv);
171 }
172
173 inline int
174 _Jv_CondNotifyAll (_Jv_ConditionVariable_t *cv, _Jv_Mutex_t *mu)
175 {
176   return _Jv_PthreadCheckMonitor (mu) || pthread_cond_broadcast (cv);
177 }
178
179
180 //
181 // Mutexes.
182 //
183
184 #ifdef RECURSIVE_MUTEX_IS_DEFAULT
185 inline void
186 _Jv_MutexInit (_Jv_Mutex_t *mu)
187 {
188   pthread_mutex_init (_Jv_PthreadGetMutex (mu), NULL);
189 #ifdef PTHREAD_MUTEX_IS_STRUCT
190   mu->count = 0;
191 #endif
192 }
193 #else
194 void _Jv_MutexInit (_Jv_Mutex_t *mu);
195 #endif
196
197 #ifndef LINUX_THREADS
198
199 // pthread_mutex_destroy does nothing on Linux and it is a win to avoid
200 // defining this macro.
201
202 #define _Jv_HaveMutexDestroy
203
204 #ifdef HAVE_RECURSIVE_MUTEX
205
206 inline void
207 _Jv_MutexDestroy (_Jv_Mutex_t *mu)
208 {
209   pthread_mutex_destroy (_Jv_PthreadGetMutex (mu));
210 }
211
212 #else /* HAVE_RECURSIVE_MUTEX */
213
214 extern void _Jv_MutexDestroy (_Jv_Mutex_t *mu);
215
216 #endif /* HAVE_RECURSIVE_MUTEX */
217 #endif /* LINUX_THREADS */
218
219 #ifdef HAVE_RECURSIVE_MUTEX
220
221 inline int
222 _Jv_MutexLock (_Jv_Mutex_t *mu)
223 {
224   int r = pthread_mutex_lock (_Jv_PthreadGetMutex (mu));
225 #ifdef PTHREAD_MUTEX_IS_STRUCT
226   if (! r)
227     ++mu->count;
228 #endif
229   return r;
230 }
231
232 inline int
233 _Jv_MutexUnlock (_Jv_Mutex_t *mu)
234 {
235   int r = pthread_mutex_unlock (_Jv_PthreadGetMutex (mu));
236 #ifdef PTHREAD_MUTEX_IS_STRUCT
237   if (! r)
238     --mu->count;
239 #endif
240   return r;
241 }
242
243 #else /* HAVE_RECURSIVE_MUTEX */
244
245 extern int _Jv_MutexLock (_Jv_Mutex_t *mu);
246 extern int _Jv_MutexUnlock (_Jv_Mutex_t *mu);
247
248 #endif /* HAVE_RECURSIVE_MUTEX */
249
250
251 //
252 // Thread creation and manipulation.
253 //
254
255 void _Jv_InitThreads (void);
256
257 void _Jv_ThreadInitData (_Jv_Thread_t **data, java::lang::Thread *thread);
258
259 inline java::lang::Thread *
260 _Jv_ThreadCurrent (void)
261 {
262   extern pthread_key_t _Jv_ThreadKey;
263   return (java::lang::Thread *) pthread_getspecific (_Jv_ThreadKey);
264 }
265
266 inline _Jv_Thread_t *
267 _Jv_ThreadCurrentData (void)
268 {
269   extern pthread_key_t _Jv_ThreadDataKey;
270   return (_Jv_Thread_t *) pthread_getspecific (_Jv_ThreadDataKey);
271 }
272
273 inline void
274 _Jv_ThreadYield (void)
275 {
276 #ifdef HAVE_SCHED_YIELD
277   sched_yield ();
278 #endif /* HAVE_SCHED_YIELD */
279 }
280
281 void _Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio);
282
283 void _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data,
284                       _Jv_ThreadStartFunc *meth);
285
286 void _Jv_ThreadWait (void);
287
288 void _Jv_ThreadInterrupt (_Jv_Thread_t *data);
289
290 #endif /* __JV_POSIX_THREADS__ */