1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is the Netscape Portable Runtime (NSPR).
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998-2000
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #ifndef nspr_pth_defs_h_
39 #define nspr_pth_defs_h_
42 ** Appropriate definitions of entry points not used in a pthreads world
44 #define _PR_MD_BLOCK_CLOCK_INTERRUPTS()
45 #define _PR_MD_UNBLOCK_CLOCK_INTERRUPTS()
46 #define _PR_MD_DISABLE_CLOCK_INTERRUPTS()
47 #define _PR_MD_ENABLE_CLOCK_INTERRUPTS()
49 /* In good standards fashion, the DCE threads (based on posix-4) are not
50 * quite the same as newer posix implementations. These are mostly name
51 * changes and small differences, so macros usually do the trick
54 #define _PT_PTHREAD_MUTEXATTR_INIT pthread_mutexattr_create
55 #define _PT_PTHREAD_MUTEXATTR_DESTROY pthread_mutexattr_delete
56 #define _PT_PTHREAD_MUTEX_INIT(m, a) pthread_mutex_init(&(m), a)
57 #define _PT_PTHREAD_MUTEX_IS_LOCKED(m) (0 == pthread_mutex_trylock(&(m)))
58 #define _PT_PTHREAD_CONDATTR_INIT pthread_condattr_create
59 #define _PT_PTHREAD_COND_INIT(m, a) pthread_cond_init(&(m), a)
60 #define _PT_PTHREAD_CONDATTR_DESTROY pthread_condattr_delete
62 /* Notes about differences between DCE threads and pthreads 10:
63 * 1. pthread_mutex_trylock returns 1 when it locks the mutex
64 * 0 when it does not. The latest pthreads has a set of errno-like
66 * 2. return values from pthread_cond_timedwait are different.
73 * Mutex and condition attributes are not supported. The attr
74 * argument to pthread_mutex_init() and pthread_cond_init() must
77 * The memset calls in _PT_PTHREAD_MUTEX_INIT and _PT_PTHREAD_COND_INIT
78 * are to work around BSDI's using a single bit to indicate a mutex
79 * or condition variable is initialized. This entire BSDI section
80 * will go away when BSDI releases updated threads libraries for
83 #define _PT_PTHREAD_MUTEXATTR_INIT(x) 0
84 #define _PT_PTHREAD_MUTEXATTR_DESTROY(x) /* */
85 #define _PT_PTHREAD_MUTEX_INIT(m, a) (memset(&(m), 0, sizeof(m)), \
86 pthread_mutex_init(&(m), NULL))
87 #define _PT_PTHREAD_MUTEX_IS_LOCKED(m) (EBUSY == pthread_mutex_trylock(&(m)))
88 #define _PT_PTHREAD_CONDATTR_INIT(x) 0
89 #define _PT_PTHREAD_CONDATTR_DESTROY(x) /* */
90 #define _PT_PTHREAD_COND_INIT(m, a) (memset(&(m), 0, sizeof(m)), \
91 pthread_cond_init(&(m), NULL))
93 #define _PT_PTHREAD_MUTEXATTR_INIT pthread_mutexattr_init
94 #define _PT_PTHREAD_MUTEXATTR_DESTROY pthread_mutexattr_destroy
95 #define _PT_PTHREAD_MUTEX_INIT(m, a) pthread_mutex_init(&(m), &(a))
97 #define _PT_PTHREAD_MUTEX_IS_LOCKED(m) pt_pthread_mutex_is_locked(&(m))
99 #define _PT_PTHREAD_MUTEX_IS_LOCKED(m) (EBUSY == pthread_mutex_trylock(&(m)))
102 #define _PT_PTHREAD_CONDATTR_INIT(x) 0
104 #define _PT_PTHREAD_CONDATTR_INIT pthread_condattr_init
106 #define _PT_PTHREAD_CONDATTR_DESTROY pthread_condattr_destroy
107 #define _PT_PTHREAD_COND_INIT(m, a) pthread_cond_init(&(m), &(a))
110 /* The pthreads standard does not specify an invalid value for the
111 * pthread_t handle. (0 is usually an invalid pthread identifier
112 * but there are exceptions, for example, DG/UX.) These macros
113 * define a way to set the handle to or compare the handle with an
114 * invalid identifier. These macros are not portable and may be
115 * more of a problem as we adapt to more pthreads implementations.
116 * They are only used in the PRMonitor functions. Do not use them
119 * Unfortunately some of our clients depend on certain properties
120 * of our PRMonitor implementation, preventing us from replacing
121 * it by a portable implementation.
122 * - High-performance servers like the fact that PR_EnterMonitor
123 * only calls PR_Lock and PR_ExitMonitor only calls PR_Unlock.
124 * (A portable implementation would use a PRLock and a PRCondVar
125 * to implement the recursive lock in a monitor and call both
126 * PR_Lock and PR_Unlock in PR_EnterMonitor and PR_ExitMonitor.)
127 * Unfortunately this forces us to read the monitor owner field
128 * without holding a lock.
129 * - One way to make it safe to read the monitor owner field
130 * without holding a lock is to make that field a PRThread*
131 * (one should be able to read a pointer with a single machine
132 * instruction). However, PR_GetCurrentThread calls calloc if
133 * it is called by a thread that was not created by NSPR. The
134 * malloc tracing tools in the Mozilla client use PRMonitor for
135 * locking in their malloc, calloc, and free functions. If
136 * PR_EnterMonitor calls any of these functions, infinite
139 #if defined(_PR_DCETHREADS)
140 #define _PT_PTHREAD_INVALIDATE_THR_HANDLE(t) \
141 memset(&(t), 0, sizeof(pthread_t))
142 #define _PT_PTHREAD_THR_HANDLE_IS_INVALID(t) \
143 (!memcmp(&(t), &pt_zero_tid, sizeof(pthread_t)))
144 #define _PT_PTHREAD_COPY_THR_HANDLE(st, dt) (dt) = (st)
145 #elif defined(IRIX) || defined(OSF1) || defined(AIX) || defined(SOLARIS) \
146 || defined(LINUX) || defined(__GNU__) || defined(__GLIBC__) \
147 || defined(HPUX) || defined(FREEBSD) \
148 || defined(NETBSD) || defined(OPENBSD) || defined(BSDI) \
149 || defined(VMS) || defined(NTO) || defined(DARWIN) \
150 || defined(UNIXWARE) || defined(RISCOS) || defined(SYMBIAN)
152 /* Hurd pthreads don't have an invalid value for pthread_t. -- rmh */
153 #error Using Hurd pthreads
155 #define _PT_PTHREAD_INVALIDATE_THR_HANDLE(t) (t) = 0
156 #define _PT_PTHREAD_THR_HANDLE_IS_INVALID(t) (t) == 0
157 #define _PT_PTHREAD_COPY_THR_HANDLE(st, dt) (dt) = (st)
159 #error "pthreads is not supported for this architecture"
162 #if defined(_PR_DCETHREADS)
163 #define _PT_PTHREAD_ATTR_INIT pthread_attr_create
164 #define _PT_PTHREAD_ATTR_DESTROY pthread_attr_delete
165 #define _PT_PTHREAD_CREATE(t, a, f, r) pthread_create(t, a, f, r)
166 #define _PT_PTHREAD_KEY_CREATE pthread_keycreate
167 #define _PT_PTHREAD_ATTR_SETSCHEDPOLICY pthread_attr_setsched
168 #define _PT_PTHREAD_ATTR_GETSTACKSIZE(a, s) \
169 (*(s) = pthread_attr_getstacksize(*(a)), 0)
170 #define _PT_PTHREAD_GETSPECIFIC(k, r) \
171 pthread_getspecific((k), (pthread_addr_t *) &(r))
172 #elif defined(_PR_PTHREADS)
173 #define _PT_PTHREAD_ATTR_INIT pthread_attr_init
174 #define _PT_PTHREAD_ATTR_DESTROY pthread_attr_destroy
175 #define _PT_PTHREAD_CREATE(t, a, f, r) pthread_create(t, &a, f, r)
176 #define _PT_PTHREAD_KEY_CREATE pthread_key_create
177 #define _PT_PTHREAD_ATTR_SETSCHEDPOLICY pthread_attr_setschedpolicy
178 #define _PT_PTHREAD_ATTR_GETSTACKSIZE(a, s) pthread_attr_getstacksize(a, s)
179 #define _PT_PTHREAD_GETSPECIFIC(k, r) (r) = pthread_getspecific(k)
181 #error "Cannot determine pthread strategy"
184 #if defined(_PR_DCETHREADS)
185 #define _PT_PTHREAD_EXPLICIT_SCHED _PT_PTHREAD_DEFAULT_SCHED
189 * pthread_mutex_trylock returns different values in DCE threads and
192 #if defined(_PR_DCETHREADS)
193 #define PT_TRYLOCK_SUCCESS 1
194 #define PT_TRYLOCK_BUSY 0
196 #define PT_TRYLOCK_SUCCESS 0
197 #define PT_TRYLOCK_BUSY EBUSY
201 * These platforms don't have sigtimedwait()
203 #if (defined(AIX) && !defined(AIX4_3_PLUS)) \
204 || defined(LINUX) || defined(__GNU__)|| defined(__GLIBC__) \
205 || defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) \
206 || defined(BSDI) || defined(VMS) || defined(UNIXWARE) \
207 || defined(DARWIN) || defined(SYMBIAN)
208 #define PT_NO_SIGTIMEDWAIT
211 #if defined(OSF1) || defined(VMS)
212 #define PT_PRIO_MIN PRI_OTHER_MIN
213 #define PT_PRIO_MAX PRI_OTHER_MAX
215 #include <sys/sched.h>
216 #define PT_PRIO_MIN PX_PRIO_MIN
217 #define PT_PRIO_MAX PX_PRIO_MAX
219 #include <sys/priv.h>
220 #include <sys/sched.h>
221 #ifndef PTHREAD_CREATE_JOINABLE
222 #define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED
224 #define PT_PRIO_MIN DEFAULT_PRIO
225 #define PT_PRIO_MAX DEFAULT_PRIO
228 #if defined(_PR_DCETHREADS)
229 #define PT_PRIO_MIN PRI_OTHER_MIN
230 #define PT_PRIO_MAX PRI_OTHER_MAX
231 #else /* defined(_PR_DCETHREADS) */
232 #include <sys/sched.h>
233 #define PT_PRIO_MIN sched_get_priority_min(SCHED_OTHER)
234 #define PT_PRIO_MAX sched_get_priority_max(SCHED_OTHER)
235 #endif /* defined(_PR_DCETHREADS) */
237 #elif defined(LINUX) || defined(__GNU__) || defined(__GLIBC__) \
238 || defined(FREEBSD) || defined(SYMBIAN)
239 #define PT_PRIO_MIN sched_get_priority_min(SCHED_OTHER)
240 #define PT_PRIO_MAX sched_get_priority_max(SCHED_OTHER)
243 * Neutrino has functions that return the priority range but
244 * they return invalid numbers, so I just hard coded these here
245 * for now. Jerry.Kirk@Nexarecorp.com
247 #define PT_PRIO_MIN 0
248 #define PT_PRIO_MAX 30
249 #elif defined(SOLARIS)
251 * Solaris doesn't seem to have macros for the min/max priorities.
252 * The range of 0-127 is mentioned in the pthread_setschedparam(3T)
253 * man pages, and pthread_setschedparam indeed allows 0-127. However,
254 * pthread_attr_setschedparam does not allow 0; it allows 1-127.
256 #define PT_PRIO_MIN 1
257 #define PT_PRIO_MAX 127
258 #elif defined(OPENBSD)
259 #define PT_PRIO_MIN 0
260 #define PT_PRIO_MAX 31
261 #elif defined(NETBSD) \
262 || defined(BSDI) || defined(DARWIN) || defined(UNIXWARE) \
263 || defined(RISCOS) /* XXX */
264 #define PT_PRIO_MIN 0
265 #define PT_PRIO_MAX 126
267 #error "pthreads is not supported for this architecture"
271 * The _PT_PTHREAD_YIELD function is called from a signal handler.
272 * Needed for garbage collection -- Look at PR_Suspend/PR_Resume
275 #if defined(_PR_DCETHREADS)
276 #define _PT_PTHREAD_YIELD() pthread_yield()
277 #elif defined(OSF1) || defined(VMS)
279 * sched_yield can't be called from a signal handler. Must use
282 #define _PT_PTHREAD_YIELD() pthread_yield_np()
284 extern int (*_PT_aix_yield_fcn
)();
285 #define _PT_PTHREAD_YIELD() (*_PT_aix_yield_fcn)()
288 #define _PT_PTHREAD_YIELD() \
290 struct timespec onemillisec = {0}; \
291 onemillisec.tv_nsec = 1000000L; \
292 nanosleep(&onemillisec,NULL); \
294 #elif defined(HPUX) || defined(SOLARIS) \
295 || defined(LINUX) || defined(__GNU__) || defined(__GLIBC__) \
296 || defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) \
297 || defined(BSDI) || defined(NTO) || defined(DARWIN) \
298 || defined(UNIXWARE) || defined(RISCOS) || defined(SYMBIAN)
299 #define _PT_PTHREAD_YIELD() sched_yield()
301 #error "Need to define _PT_PTHREAD_YIELD for this platform"
304 #endif /* nspr_pth_defs_h_ */