nsprpub/pr/src/md/unix/aix.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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 #include "primpl.h"
michael@0 7
michael@0 8 #ifdef AIX_HAVE_ATOMIC_OP_H
michael@0 9 #include <sys/atomic_op.h>
michael@0 10
michael@0 11 PRInt32 _AIX_AtomicSet(PRInt32 *val, PRInt32 newval)
michael@0 12 {
michael@0 13 PRIntn oldval;
michael@0 14 boolean_t stored;
michael@0 15 oldval = fetch_and_add((atomic_p)val, 0);
michael@0 16 do
michael@0 17 {
michael@0 18 stored = compare_and_swap((atomic_p)val, &oldval, newval);
michael@0 19 } while (!stored);
michael@0 20 return oldval;
michael@0 21 } /* _AIX_AtomicSet */
michael@0 22 #endif /* AIX_HAVE_ATOMIC_OP_H */
michael@0 23
michael@0 24 #if defined(AIX_TIMERS)
michael@0 25
michael@0 26 #include <sys/time.h>
michael@0 27
michael@0 28 static PRUint32 _aix_baseline_epoch;
michael@0 29
michael@0 30 static void _MD_AixIntervalInit(void)
michael@0 31 {
michael@0 32 timebasestruct_t real_time;
michael@0 33 read_real_time(&real_time, TIMEBASE_SZ);
michael@0 34 (void)time_base_to_time(&real_time, TIMEBASE_SZ);
michael@0 35 _aix_baseline_epoch = real_time.tb_high;
michael@0 36 } /* _MD_AixIntervalInit */
michael@0 37
michael@0 38 PRIntervalTime _MD_AixGetInterval(void)
michael@0 39 {
michael@0 40 PRIntn rv;
michael@0 41 PRUint64 temp;
michael@0 42 timebasestruct_t real_time;
michael@0 43 read_real_time(&real_time, TIMEBASE_SZ);
michael@0 44 (void)time_base_to_time(&real_time, TIMEBASE_SZ);
michael@0 45 /* tb_high is in seconds, tb_low in 10(-9)seconds */
michael@0 46 temp = 1000000000ULL * (PRUint64)(real_time.tb_high - _aix_baseline_epoch);
michael@0 47 temp += (PRUint64)real_time.tb_low; /* everything's 10(-9) seconds */
michael@0 48 temp >>= 16; /* now it's something way different */
michael@0 49 return (PRIntervalTime)temp;
michael@0 50 } /* _MD_AixGetInterval */
michael@0 51
michael@0 52 PRIntervalTime _MD_AixIntervalPerSec(void)
michael@0 53 {
michael@0 54 return 1000000000ULL >> 16; /* that's 15258, I think */
michael@0 55 } /* _MD_AixIntervalPerSec */
michael@0 56
michael@0 57 #endif /* defined(AIX_TIMERS) */
michael@0 58
michael@0 59 #if !defined(PTHREADS_USER)
michael@0 60
michael@0 61 #if defined(_PR_PTHREADS)
michael@0 62
michael@0 63 /*
michael@0 64 * AIX 4.3 has sched_yield(). AIX 4.2 has pthread_yield().
michael@0 65 * So we look up the appropriate function pointer at run time.
michael@0 66 */
michael@0 67
michael@0 68 #include <dlfcn.h>
michael@0 69
michael@0 70 int (*_PT_aix_yield_fcn)() = NULL;
michael@0 71 int _pr_aix_send_file_use_disabled = 0;
michael@0 72
michael@0 73 void _MD_EarlyInit(void)
michael@0 74 {
michael@0 75 void *main_app_handle;
michael@0 76 char *evp;
michael@0 77
michael@0 78 main_app_handle = dlopen(NULL, RTLD_NOW);
michael@0 79 PR_ASSERT(NULL != main_app_handle);
michael@0 80
michael@0 81 _PT_aix_yield_fcn = (int(*)())dlsym(main_app_handle, "sched_yield");
michael@0 82 if (!_PT_aix_yield_fcn) {
michael@0 83 _PT_aix_yield_fcn = (int(*)())dlsym(main_app_handle,"pthread_yield");
michael@0 84 PR_ASSERT(NULL != _PT_aix_yield_fcn);
michael@0 85 }
michael@0 86 dlclose(main_app_handle);
michael@0 87
michael@0 88 if (evp = getenv("NSPR_AIX_SEND_FILE_USE_DISABLED")) {
michael@0 89 if (1 == atoi(evp))
michael@0 90 _pr_aix_send_file_use_disabled = 1;
michael@0 91 }
michael@0 92
michael@0 93 #if defined(AIX_TIMERS)
michael@0 94 _MD_AixIntervalInit();
michael@0 95 #endif
michael@0 96 }
michael@0 97
michael@0 98 #else /* _PR_PTHREADS */
michael@0 99
michael@0 100 void _MD_EarlyInit(void)
michael@0 101 {
michael@0 102 #if defined(AIX_TIMERS)
michael@0 103 _MD_AixIntervalInit();
michael@0 104 #endif
michael@0 105 }
michael@0 106
michael@0 107 #endif /* _PR_PTHREADS */
michael@0 108
michael@0 109 PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
michael@0 110 {
michael@0 111 #ifndef _PR_PTHREADS
michael@0 112 if (isCurrent) {
michael@0 113 (void) setjmp(CONTEXT(t));
michael@0 114 }
michael@0 115 *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
michael@0 116 return (PRWord *) CONTEXT(t);
michael@0 117 #else
michael@0 118 *np = 0;
michael@0 119 return NULL;
michael@0 120 #endif
michael@0 121 }
michael@0 122
michael@0 123 #ifndef _PR_PTHREADS
michael@0 124 PR_IMPLEMENT(void)
michael@0 125 _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
michael@0 126 {
michael@0 127 return;
michael@0 128 }
michael@0 129
michael@0 130 PR_IMPLEMENT(PRStatus)
michael@0 131 _MD_InitializeThread(PRThread *thread)
michael@0 132 {
michael@0 133 return PR_SUCCESS;
michael@0 134 }
michael@0 135
michael@0 136 PR_IMPLEMENT(PRStatus)
michael@0 137 _MD_WAIT(PRThread *thread, PRIntervalTime ticks)
michael@0 138 {
michael@0 139 PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
michael@0 140 _PR_MD_SWITCH_CONTEXT(thread);
michael@0 141 return PR_SUCCESS;
michael@0 142 }
michael@0 143
michael@0 144 PR_IMPLEMENT(PRStatus)
michael@0 145 _MD_WAKEUP_WAITER(PRThread *thread)
michael@0 146 {
michael@0 147 if (thread) {
michael@0 148 PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
michael@0 149 }
michael@0 150 return PR_SUCCESS;
michael@0 151 }
michael@0 152
michael@0 153 /* These functions should not be called for AIX */
michael@0 154 PR_IMPLEMENT(void)
michael@0 155 _MD_YIELD(void)
michael@0 156 {
michael@0 157 PR_NOT_REACHED("_MD_YIELD should not be called for AIX.");
michael@0 158 }
michael@0 159
michael@0 160 PR_IMPLEMENT(PRStatus)
michael@0 161 _MD_CREATE_THREAD(
michael@0 162 PRThread *thread,
michael@0 163 void (*start) (void *),
michael@0 164 PRThreadPriority priority,
michael@0 165 PRThreadScope scope,
michael@0 166 PRThreadState state,
michael@0 167 PRUint32 stackSize)
michael@0 168 {
michael@0 169 PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for AIX.");
michael@0 170 }
michael@0 171 #endif /* _PR_PTHREADS */
michael@0 172 #endif /* PTHREADS_USER */
michael@0 173
michael@0 174 /*
michael@0 175 * NSPR 2.0 overrides the system select() and poll() functions.
michael@0 176 * On AIX 4.2, we use dlopen("/unix", RTLD_NOW) and dlsym() to get
michael@0 177 * at the original system select() and poll() functions.
michael@0 178 */
michael@0 179
michael@0 180 #if !defined(AIX_RENAME_SELECT)
michael@0 181
michael@0 182 #include <sys/select.h>
michael@0 183 #include <sys/poll.h>
michael@0 184 #include <dlfcn.h>
michael@0 185
michael@0 186 static int (*aix_select_fcn)() = NULL;
michael@0 187 static int (*aix_poll_fcn)() = NULL;
michael@0 188
michael@0 189 int _MD_SELECT(int width, fd_set *r, fd_set *w, fd_set *e, struct timeval *t)
michael@0 190 {
michael@0 191 int rv;
michael@0 192
michael@0 193 if (!aix_select_fcn) {
michael@0 194 void *aix_handle;
michael@0 195
michael@0 196 aix_handle = dlopen("/unix", RTLD_NOW);
michael@0 197 if (!aix_handle) {
michael@0 198 PR_SetError(PR_UNKNOWN_ERROR, 0);
michael@0 199 return -1;
michael@0 200 }
michael@0 201 aix_select_fcn = (int(*)())dlsym(aix_handle,"select");
michael@0 202 dlclose(aix_handle);
michael@0 203 if (!aix_select_fcn) {
michael@0 204 PR_SetError(PR_UNKNOWN_ERROR, 0);
michael@0 205 return -1;
michael@0 206 }
michael@0 207 }
michael@0 208 rv = (*aix_select_fcn)(width, r, w, e, t);
michael@0 209 return rv;
michael@0 210 }
michael@0 211
michael@0 212 int _MD_POLL(void *listptr, unsigned long nfds, long timeout)
michael@0 213 {
michael@0 214 int rv;
michael@0 215
michael@0 216 if (!aix_poll_fcn) {
michael@0 217 void *aix_handle;
michael@0 218
michael@0 219 aix_handle = dlopen("/unix", RTLD_NOW);
michael@0 220 if (!aix_handle) {
michael@0 221 PR_SetError(PR_UNKNOWN_ERROR, 0);
michael@0 222 return -1;
michael@0 223 }
michael@0 224 aix_poll_fcn = (int(*)())dlsym(aix_handle,"poll");
michael@0 225 dlclose(aix_handle);
michael@0 226 if (!aix_poll_fcn) {
michael@0 227 PR_SetError(PR_UNKNOWN_ERROR, 0);
michael@0 228 return -1;
michael@0 229 }
michael@0 230 }
michael@0 231 rv = (*aix_poll_fcn)(listptr, nfds, timeout);
michael@0 232 return rv;
michael@0 233 }
michael@0 234
michael@0 235 #else
michael@0 236
michael@0 237 /*
michael@0 238 * In AIX versions prior to 4.2, we use the two-step rename/link trick.
michael@0 239 * The binary must contain at least one "poll" symbol for linker's rename
michael@0 240 * to work. So we must have this dummy function that references poll().
michael@0 241 */
michael@0 242 #include <sys/poll.h>
michael@0 243 void _pr_aix_dummy()
michael@0 244 {
michael@0 245 poll(0,0,0);
michael@0 246 }
michael@0 247
michael@0 248 #endif /* !defined(AIX_RENAME_SELECT) */
michael@0 249
michael@0 250 #ifdef _PR_HAVE_ATOMIC_CAS
michael@0 251
michael@0 252 #include "pratom.h"
michael@0 253
michael@0 254 #define _PR_AIX_ATOMIC_LOCK -1
michael@0 255
michael@0 256 PR_IMPLEMENT(void)
michael@0 257 PR_StackPush(PRStack *stack, PRStackElem *stack_elem)
michael@0 258 {
michael@0 259 PRStackElem *addr;
michael@0 260 boolean_t locked = TRUE;
michael@0 261
michael@0 262 /* Is it safe to cast a pointer to an int? */
michael@0 263 PR_ASSERT(sizeof(int) == sizeof(PRStackElem *));
michael@0 264 do {
michael@0 265 while ((addr = stack->prstk_head.prstk_elem_next) ==
michael@0 266 (PRStackElem *)_PR_AIX_ATOMIC_LOCK)
michael@0 267 ;
michael@0 268 locked = _check_lock((atomic_p) &stack->prstk_head.prstk_elem_next,
michael@0 269 (int) addr, _PR_AIX_ATOMIC_LOCK);
michael@0 270 } while (locked == TRUE);
michael@0 271 stack_elem->prstk_elem_next = addr;
michael@0 272 _clear_lock((atomic_p)&stack->prstk_head.prstk_elem_next, (int)stack_elem);
michael@0 273 return;
michael@0 274 }
michael@0 275
michael@0 276 PR_IMPLEMENT(PRStackElem *)
michael@0 277 PR_StackPop(PRStack *stack)
michael@0 278 {
michael@0 279 PRStackElem *element;
michael@0 280 boolean_t locked = TRUE;
michael@0 281
michael@0 282 /* Is it safe to cast a pointer to an int? */
michael@0 283 PR_ASSERT(sizeof(int) == sizeof(PRStackElem *));
michael@0 284 do {
michael@0 285 while ((element = stack->prstk_head.prstk_elem_next) ==
michael@0 286 (PRStackElem *) _PR_AIX_ATOMIC_LOCK)
michael@0 287 ;
michael@0 288 locked = _check_lock((atomic_p) &stack->prstk_head.prstk_elem_next,
michael@0 289 (int)element, _PR_AIX_ATOMIC_LOCK);
michael@0 290 } while (locked == TRUE);
michael@0 291
michael@0 292 if (element == NULL) {
michael@0 293 _clear_lock((atomic_p) &stack->prstk_head.prstk_elem_next, NULL);
michael@0 294 } else {
michael@0 295 _clear_lock((atomic_p) &stack->prstk_head.prstk_elem_next,
michael@0 296 (int) element->prstk_elem_next);
michael@0 297 }
michael@0 298 return element;
michael@0 299 }
michael@0 300
michael@0 301 #endif /* _PR_HAVE_ATOMIC_CAS */

mercurial