nsprpub/pr/include/md/_pth.h

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #ifndef nspr_pth_defs_h_
michael@0 7 #define nspr_pth_defs_h_
michael@0 8
michael@0 9 /*
michael@0 10 ** Appropriate definitions of entry points not used in a pthreads world
michael@0 11 */
michael@0 12 #define _PR_MD_BLOCK_CLOCK_INTERRUPTS()
michael@0 13 #define _PR_MD_UNBLOCK_CLOCK_INTERRUPTS()
michael@0 14 #define _PR_MD_DISABLE_CLOCK_INTERRUPTS()
michael@0 15 #define _PR_MD_ENABLE_CLOCK_INTERRUPTS()
michael@0 16
michael@0 17 /* In good standards fashion, the DCE threads (based on posix-4) are not
michael@0 18 * quite the same as newer posix implementations. These are mostly name
michael@0 19 * changes and small differences, so macros usually do the trick
michael@0 20 */
michael@0 21 #ifdef _PR_DCETHREADS
michael@0 22 #define _PT_PTHREAD_MUTEXATTR_INIT pthread_mutexattr_create
michael@0 23 #define _PT_PTHREAD_MUTEXATTR_DESTROY pthread_mutexattr_delete
michael@0 24 #define _PT_PTHREAD_MUTEX_INIT(m, a) pthread_mutex_init(&(m), a)
michael@0 25 #define _PT_PTHREAD_MUTEX_IS_LOCKED(m) (0 == pthread_mutex_trylock(&(m)))
michael@0 26 #define _PT_PTHREAD_CONDATTR_INIT pthread_condattr_create
michael@0 27 #define _PT_PTHREAD_COND_INIT(m, a) pthread_cond_init(&(m), a)
michael@0 28 #define _PT_PTHREAD_CONDATTR_DESTROY pthread_condattr_delete
michael@0 29
michael@0 30 /* Notes about differences between DCE threads and pthreads 10:
michael@0 31 * 1. pthread_mutex_trylock returns 1 when it locks the mutex
michael@0 32 * 0 when it does not. The latest pthreads has a set of errno-like
michael@0 33 * return values.
michael@0 34 * 2. return values from pthread_cond_timedwait are different.
michael@0 35 *
michael@0 36 *
michael@0 37 *
michael@0 38 */
michael@0 39 #elif defined(BSDI)
michael@0 40 /*
michael@0 41 * Mutex and condition attributes are not supported. The attr
michael@0 42 * argument to pthread_mutex_init() and pthread_cond_init() must
michael@0 43 * be passed as NULL.
michael@0 44 *
michael@0 45 * The memset calls in _PT_PTHREAD_MUTEX_INIT and _PT_PTHREAD_COND_INIT
michael@0 46 * are to work around BSDI's using a single bit to indicate a mutex
michael@0 47 * or condition variable is initialized. This entire BSDI section
michael@0 48 * will go away when BSDI releases updated threads libraries for
michael@0 49 * BSD/OS 3.1 and 4.0.
michael@0 50 */
michael@0 51 #define _PT_PTHREAD_MUTEXATTR_INIT(x) 0
michael@0 52 #define _PT_PTHREAD_MUTEXATTR_DESTROY(x) /* */
michael@0 53 #define _PT_PTHREAD_MUTEX_INIT(m, a) (memset(&(m), 0, sizeof(m)), \
michael@0 54 pthread_mutex_init(&(m), NULL))
michael@0 55 #define _PT_PTHREAD_MUTEX_IS_LOCKED(m) (EBUSY == pthread_mutex_trylock(&(m)))
michael@0 56 #define _PT_PTHREAD_CONDATTR_INIT(x) 0
michael@0 57 #define _PT_PTHREAD_CONDATTR_DESTROY(x) /* */
michael@0 58 #define _PT_PTHREAD_COND_INIT(m, a) (memset(&(m), 0, sizeof(m)), \
michael@0 59 pthread_cond_init(&(m), NULL))
michael@0 60 #else
michael@0 61 #define _PT_PTHREAD_MUTEXATTR_INIT pthread_mutexattr_init
michael@0 62 #define _PT_PTHREAD_MUTEXATTR_DESTROY pthread_mutexattr_destroy
michael@0 63 #define _PT_PTHREAD_MUTEX_INIT(m, a) pthread_mutex_init(&(m), &(a))
michael@0 64 #if defined(FREEBSD)
michael@0 65 #define _PT_PTHREAD_MUTEX_IS_LOCKED(m) pt_pthread_mutex_is_locked(&(m))
michael@0 66 #else
michael@0 67 #define _PT_PTHREAD_MUTEX_IS_LOCKED(m) (EBUSY == pthread_mutex_trylock(&(m)))
michael@0 68 #endif
michael@0 69 #if defined(ANDROID)
michael@0 70 /* Conditional attribute init and destroy aren't implemented in bionic. */
michael@0 71 #define _PT_PTHREAD_CONDATTR_INIT(x) 0
michael@0 72 #define _PT_PTHREAD_CONDATTR_DESTROY(x) /* */
michael@0 73 #else
michael@0 74 #define _PT_PTHREAD_CONDATTR_INIT pthread_condattr_init
michael@0 75 #define _PT_PTHREAD_CONDATTR_DESTROY pthread_condattr_destroy
michael@0 76 #endif
michael@0 77 #define _PT_PTHREAD_COND_INIT(m, a) pthread_cond_init(&(m), &(a))
michael@0 78 #endif
michael@0 79
michael@0 80 /* The pthreads standard does not specify an invalid value for the
michael@0 81 * pthread_t handle. (0 is usually an invalid pthread identifier
michael@0 82 * but there are exceptions, for example, DG/UX.) These macros
michael@0 83 * define a way to set the handle to or compare the handle with an
michael@0 84 * invalid identifier. These macros are not portable and may be
michael@0 85 * more of a problem as we adapt to more pthreads implementations.
michael@0 86 * They are only used in the PRMonitor functions. Do not use them
michael@0 87 * in new code.
michael@0 88 *
michael@0 89 * Unfortunately some of our clients depend on certain properties
michael@0 90 * of our PRMonitor implementation, preventing us from replacing
michael@0 91 * it by a portable implementation.
michael@0 92 * - High-performance servers like the fact that PR_EnterMonitor
michael@0 93 * only calls PR_Lock and PR_ExitMonitor only calls PR_Unlock.
michael@0 94 * (A portable implementation would use a PRLock and a PRCondVar
michael@0 95 * to implement the recursive lock in a monitor and call both
michael@0 96 * PR_Lock and PR_Unlock in PR_EnterMonitor and PR_ExitMonitor.)
michael@0 97 * Unfortunately this forces us to read the monitor owner field
michael@0 98 * without holding a lock.
michael@0 99 * - One way to make it safe to read the monitor owner field
michael@0 100 * without holding a lock is to make that field a PRThread*
michael@0 101 * (one should be able to read a pointer with a single machine
michael@0 102 * instruction). However, PR_GetCurrentThread calls calloc if
michael@0 103 * it is called by a thread that was not created by NSPR. The
michael@0 104 * malloc tracing tools in the Mozilla client use PRMonitor for
michael@0 105 * locking in their malloc, calloc, and free functions. If
michael@0 106 * PR_EnterMonitor calls any of these functions, infinite
michael@0 107 * recursion ensues.
michael@0 108 */
michael@0 109 #if defined(_PR_DCETHREADS)
michael@0 110 #define _PT_PTHREAD_INVALIDATE_THR_HANDLE(t) \
michael@0 111 memset(&(t), 0, sizeof(pthread_t))
michael@0 112 #define _PT_PTHREAD_THR_HANDLE_IS_INVALID(t) \
michael@0 113 (!memcmp(&(t), &pt_zero_tid, sizeof(pthread_t)))
michael@0 114 #define _PT_PTHREAD_COPY_THR_HANDLE(st, dt) (dt) = (st)
michael@0 115 #elif defined(IRIX) || defined(OSF1) || defined(AIX) || defined(SOLARIS) \
michael@0 116 || defined(LINUX) || defined(__GNU__) || defined(__GLIBC__) \
michael@0 117 || defined(HPUX) || defined(FREEBSD) \
michael@0 118 || defined(NETBSD) || defined(OPENBSD) || defined(BSDI) \
michael@0 119 || defined(NTO) || defined(DARWIN) \
michael@0 120 || defined(UNIXWARE) || defined(RISCOS) || defined(SYMBIAN)
michael@0 121 #define _PT_PTHREAD_INVALIDATE_THR_HANDLE(t) (t) = 0
michael@0 122 #define _PT_PTHREAD_THR_HANDLE_IS_INVALID(t) (t) == 0
michael@0 123 #define _PT_PTHREAD_COPY_THR_HANDLE(st, dt) (dt) = (st)
michael@0 124 #else
michael@0 125 #error "pthreads is not supported for this architecture"
michael@0 126 #endif
michael@0 127
michael@0 128 #if defined(_PR_DCETHREADS)
michael@0 129 #define _PT_PTHREAD_ATTR_INIT pthread_attr_create
michael@0 130 #define _PT_PTHREAD_ATTR_DESTROY pthread_attr_delete
michael@0 131 #define _PT_PTHREAD_CREATE(t, a, f, r) pthread_create(t, a, f, r)
michael@0 132 #define _PT_PTHREAD_KEY_CREATE pthread_keycreate
michael@0 133 #define _PT_PTHREAD_ATTR_SETSCHEDPOLICY pthread_attr_setsched
michael@0 134 #define _PT_PTHREAD_ATTR_GETSTACKSIZE(a, s) \
michael@0 135 (*(s) = pthread_attr_getstacksize(*(a)), 0)
michael@0 136 #define _PT_PTHREAD_GETSPECIFIC(k, r) \
michael@0 137 pthread_getspecific((k), (pthread_addr_t *) &(r))
michael@0 138 #elif defined(_PR_PTHREADS)
michael@0 139 #define _PT_PTHREAD_ATTR_INIT pthread_attr_init
michael@0 140 #define _PT_PTHREAD_ATTR_DESTROY pthread_attr_destroy
michael@0 141 #define _PT_PTHREAD_CREATE(t, a, f, r) pthread_create(t, &a, f, r)
michael@0 142 #define _PT_PTHREAD_KEY_CREATE pthread_key_create
michael@0 143 #define _PT_PTHREAD_ATTR_SETSCHEDPOLICY pthread_attr_setschedpolicy
michael@0 144 #define _PT_PTHREAD_ATTR_GETSTACKSIZE(a, s) pthread_attr_getstacksize(a, s)
michael@0 145 #define _PT_PTHREAD_GETSPECIFIC(k, r) (r) = pthread_getspecific(k)
michael@0 146 #else
michael@0 147 #error "Cannot determine pthread strategy"
michael@0 148 #endif
michael@0 149
michael@0 150 #if defined(_PR_DCETHREADS)
michael@0 151 #define _PT_PTHREAD_EXPLICIT_SCHED _PT_PTHREAD_DEFAULT_SCHED
michael@0 152 #endif
michael@0 153
michael@0 154 /*
michael@0 155 * pthread_mutex_trylock returns different values in DCE threads and
michael@0 156 * pthreads.
michael@0 157 */
michael@0 158 #if defined(_PR_DCETHREADS)
michael@0 159 #define PT_TRYLOCK_SUCCESS 1
michael@0 160 #define PT_TRYLOCK_BUSY 0
michael@0 161 #else
michael@0 162 #define PT_TRYLOCK_SUCCESS 0
michael@0 163 #define PT_TRYLOCK_BUSY EBUSY
michael@0 164 #endif
michael@0 165
michael@0 166 /*
michael@0 167 * These platforms don't have sigtimedwait()
michael@0 168 */
michael@0 169 #if (defined(AIX) && !defined(AIX4_3_PLUS)) \
michael@0 170 || defined(LINUX) || defined(__GNU__)|| defined(__GLIBC__) \
michael@0 171 || defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) \
michael@0 172 || defined(BSDI) || defined(UNIXWARE) \
michael@0 173 || defined(DARWIN) || defined(SYMBIAN)
michael@0 174 #define PT_NO_SIGTIMEDWAIT
michael@0 175 #endif
michael@0 176
michael@0 177 #if defined(OSF1)
michael@0 178 #define PT_PRIO_MIN PRI_OTHER_MIN
michael@0 179 #define PT_PRIO_MAX PRI_OTHER_MAX
michael@0 180 #elif defined(IRIX)
michael@0 181 #include <sys/sched.h>
michael@0 182 #define PT_PRIO_MIN PX_PRIO_MIN
michael@0 183 #define PT_PRIO_MAX PX_PRIO_MAX
michael@0 184 #elif defined(AIX)
michael@0 185 #include <sys/priv.h>
michael@0 186 #include <sys/sched.h>
michael@0 187 #ifndef PTHREAD_CREATE_JOINABLE
michael@0 188 #define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED
michael@0 189 #endif
michael@0 190 #define PT_PRIO_MIN DEFAULT_PRIO
michael@0 191 #define PT_PRIO_MAX DEFAULT_PRIO
michael@0 192 #elif defined(HPUX)
michael@0 193
michael@0 194 #if defined(_PR_DCETHREADS)
michael@0 195 #define PT_PRIO_MIN PRI_OTHER_MIN
michael@0 196 #define PT_PRIO_MAX PRI_OTHER_MAX
michael@0 197 #else /* defined(_PR_DCETHREADS) */
michael@0 198 #include <sys/sched.h>
michael@0 199 #define PT_PRIO_MIN sched_get_priority_min(SCHED_OTHER)
michael@0 200 #define PT_PRIO_MAX sched_get_priority_max(SCHED_OTHER)
michael@0 201 #endif /* defined(_PR_DCETHREADS) */
michael@0 202
michael@0 203 #elif defined(LINUX) || defined(__GNU__) || defined(__GLIBC__) \
michael@0 204 || defined(FREEBSD) || defined(SYMBIAN)
michael@0 205 #define PT_PRIO_MIN sched_get_priority_min(SCHED_OTHER)
michael@0 206 #define PT_PRIO_MAX sched_get_priority_max(SCHED_OTHER)
michael@0 207 #elif defined(NTO)
michael@0 208 /*
michael@0 209 * Neutrino has functions that return the priority range but
michael@0 210 * they return invalid numbers, so I just hard coded these here
michael@0 211 * for now. Jerry.Kirk@Nexarecorp.com
michael@0 212 */
michael@0 213 #define PT_PRIO_MIN 0
michael@0 214 #define PT_PRIO_MAX 30
michael@0 215 #elif defined(SOLARIS)
michael@0 216 /*
michael@0 217 * Solaris doesn't seem to have macros for the min/max priorities.
michael@0 218 * The range of 0-127 is mentioned in the pthread_setschedparam(3T)
michael@0 219 * man pages, and pthread_setschedparam indeed allows 0-127. However,
michael@0 220 * pthread_attr_setschedparam does not allow 0; it allows 1-127.
michael@0 221 */
michael@0 222 #define PT_PRIO_MIN 1
michael@0 223 #define PT_PRIO_MAX 127
michael@0 224 #elif defined(OPENBSD)
michael@0 225 #define PT_PRIO_MIN 0
michael@0 226 #define PT_PRIO_MAX 31
michael@0 227 #elif defined(NETBSD) \
michael@0 228 || defined(BSDI) || defined(DARWIN) || defined(UNIXWARE) \
michael@0 229 || defined(RISCOS) /* XXX */
michael@0 230 #define PT_PRIO_MIN 0
michael@0 231 #define PT_PRIO_MAX 126
michael@0 232 #else
michael@0 233 #error "pthreads is not supported for this architecture"
michael@0 234 #endif
michael@0 235
michael@0 236 /*
michael@0 237 * The _PT_PTHREAD_YIELD function is called from a signal handler.
michael@0 238 * Needed for garbage collection -- Look at PR_Suspend/PR_Resume
michael@0 239 * implementation.
michael@0 240 */
michael@0 241 #if defined(_PR_DCETHREADS)
michael@0 242 #define _PT_PTHREAD_YIELD() pthread_yield()
michael@0 243 #elif defined(OSF1)
michael@0 244 /*
michael@0 245 * sched_yield can't be called from a signal handler. Must use
michael@0 246 * the _np version.
michael@0 247 */
michael@0 248 #define _PT_PTHREAD_YIELD() pthread_yield_np()
michael@0 249 #elif defined(AIX)
michael@0 250 extern int (*_PT_aix_yield_fcn)();
michael@0 251 #define _PT_PTHREAD_YIELD() (*_PT_aix_yield_fcn)()
michael@0 252 #elif defined(IRIX)
michael@0 253 #include <time.h>
michael@0 254 #define _PT_PTHREAD_YIELD() \
michael@0 255 PR_BEGIN_MACRO \
michael@0 256 struct timespec onemillisec = {0}; \
michael@0 257 onemillisec.tv_nsec = 1000000L; \
michael@0 258 nanosleep(&onemillisec,NULL); \
michael@0 259 PR_END_MACRO
michael@0 260 #elif defined(HPUX) || defined(SOLARIS) \
michael@0 261 || defined(LINUX) || defined(__GNU__) || defined(__GLIBC__) \
michael@0 262 || defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) \
michael@0 263 || defined(BSDI) || defined(NTO) || defined(DARWIN) \
michael@0 264 || defined(UNIXWARE) || defined(RISCOS) || defined(SYMBIAN)
michael@0 265 #define _PT_PTHREAD_YIELD() sched_yield()
michael@0 266 #else
michael@0 267 #error "Need to define _PT_PTHREAD_YIELD for this platform"
michael@0 268 #endif
michael@0 269
michael@0 270 #endif /* nspr_pth_defs_h_ */

mercurial