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