1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/src/md/unix/aix.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,301 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "primpl.h" 1.10 + 1.11 +#ifdef AIX_HAVE_ATOMIC_OP_H 1.12 +#include <sys/atomic_op.h> 1.13 + 1.14 +PRInt32 _AIX_AtomicSet(PRInt32 *val, PRInt32 newval) 1.15 +{ 1.16 + PRIntn oldval; 1.17 + boolean_t stored; 1.18 + oldval = fetch_and_add((atomic_p)val, 0); 1.19 + do 1.20 + { 1.21 + stored = compare_and_swap((atomic_p)val, &oldval, newval); 1.22 + } while (!stored); 1.23 + return oldval; 1.24 +} /* _AIX_AtomicSet */ 1.25 +#endif /* AIX_HAVE_ATOMIC_OP_H */ 1.26 + 1.27 +#if defined(AIX_TIMERS) 1.28 + 1.29 +#include <sys/time.h> 1.30 + 1.31 +static PRUint32 _aix_baseline_epoch; 1.32 + 1.33 +static void _MD_AixIntervalInit(void) 1.34 +{ 1.35 + timebasestruct_t real_time; 1.36 + read_real_time(&real_time, TIMEBASE_SZ); 1.37 + (void)time_base_to_time(&real_time, TIMEBASE_SZ); 1.38 + _aix_baseline_epoch = real_time.tb_high; 1.39 +} /* _MD_AixIntervalInit */ 1.40 + 1.41 +PRIntervalTime _MD_AixGetInterval(void) 1.42 +{ 1.43 + PRIntn rv; 1.44 + PRUint64 temp; 1.45 + timebasestruct_t real_time; 1.46 + read_real_time(&real_time, TIMEBASE_SZ); 1.47 + (void)time_base_to_time(&real_time, TIMEBASE_SZ); 1.48 + /* tb_high is in seconds, tb_low in 10(-9)seconds */ 1.49 + temp = 1000000000ULL * (PRUint64)(real_time.tb_high - _aix_baseline_epoch); 1.50 + temp += (PRUint64)real_time.tb_low; /* everything's 10(-9) seconds */ 1.51 + temp >>= 16; /* now it's something way different */ 1.52 + return (PRIntervalTime)temp; 1.53 +} /* _MD_AixGetInterval */ 1.54 + 1.55 +PRIntervalTime _MD_AixIntervalPerSec(void) 1.56 +{ 1.57 + return 1000000000ULL >> 16; /* that's 15258, I think */ 1.58 +} /* _MD_AixIntervalPerSec */ 1.59 + 1.60 +#endif /* defined(AIX_TIMERS) */ 1.61 + 1.62 +#if !defined(PTHREADS_USER) 1.63 + 1.64 +#if defined(_PR_PTHREADS) 1.65 + 1.66 +/* 1.67 + * AIX 4.3 has sched_yield(). AIX 4.2 has pthread_yield(). 1.68 + * So we look up the appropriate function pointer at run time. 1.69 + */ 1.70 + 1.71 +#include <dlfcn.h> 1.72 + 1.73 +int (*_PT_aix_yield_fcn)() = NULL; 1.74 +int _pr_aix_send_file_use_disabled = 0; 1.75 + 1.76 +void _MD_EarlyInit(void) 1.77 +{ 1.78 + void *main_app_handle; 1.79 + char *evp; 1.80 + 1.81 + main_app_handle = dlopen(NULL, RTLD_NOW); 1.82 + PR_ASSERT(NULL != main_app_handle); 1.83 + 1.84 + _PT_aix_yield_fcn = (int(*)())dlsym(main_app_handle, "sched_yield"); 1.85 + if (!_PT_aix_yield_fcn) { 1.86 + _PT_aix_yield_fcn = (int(*)())dlsym(main_app_handle,"pthread_yield"); 1.87 + PR_ASSERT(NULL != _PT_aix_yield_fcn); 1.88 + } 1.89 + dlclose(main_app_handle); 1.90 + 1.91 + if (evp = getenv("NSPR_AIX_SEND_FILE_USE_DISABLED")) { 1.92 + if (1 == atoi(evp)) 1.93 + _pr_aix_send_file_use_disabled = 1; 1.94 + } 1.95 + 1.96 +#if defined(AIX_TIMERS) 1.97 + _MD_AixIntervalInit(); 1.98 +#endif 1.99 +} 1.100 + 1.101 +#else /* _PR_PTHREADS */ 1.102 + 1.103 +void _MD_EarlyInit(void) 1.104 +{ 1.105 +#if defined(AIX_TIMERS) 1.106 + _MD_AixIntervalInit(); 1.107 +#endif 1.108 +} 1.109 + 1.110 +#endif /* _PR_PTHREADS */ 1.111 + 1.112 +PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) 1.113 +{ 1.114 +#ifndef _PR_PTHREADS 1.115 + if (isCurrent) { 1.116 + (void) setjmp(CONTEXT(t)); 1.117 + } 1.118 + *np = sizeof(CONTEXT(t)) / sizeof(PRWord); 1.119 + return (PRWord *) CONTEXT(t); 1.120 +#else 1.121 + *np = 0; 1.122 + return NULL; 1.123 +#endif 1.124 +} 1.125 + 1.126 +#ifndef _PR_PTHREADS 1.127 +PR_IMPLEMENT(void) 1.128 +_MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri) 1.129 +{ 1.130 + return; 1.131 +} 1.132 + 1.133 +PR_IMPLEMENT(PRStatus) 1.134 +_MD_InitializeThread(PRThread *thread) 1.135 +{ 1.136 + return PR_SUCCESS; 1.137 +} 1.138 + 1.139 +PR_IMPLEMENT(PRStatus) 1.140 +_MD_WAIT(PRThread *thread, PRIntervalTime ticks) 1.141 +{ 1.142 + PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); 1.143 + _PR_MD_SWITCH_CONTEXT(thread); 1.144 + return PR_SUCCESS; 1.145 +} 1.146 + 1.147 +PR_IMPLEMENT(PRStatus) 1.148 +_MD_WAKEUP_WAITER(PRThread *thread) 1.149 +{ 1.150 + if (thread) { 1.151 + PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); 1.152 + } 1.153 + return PR_SUCCESS; 1.154 +} 1.155 + 1.156 +/* These functions should not be called for AIX */ 1.157 +PR_IMPLEMENT(void) 1.158 +_MD_YIELD(void) 1.159 +{ 1.160 + PR_NOT_REACHED("_MD_YIELD should not be called for AIX."); 1.161 +} 1.162 + 1.163 +PR_IMPLEMENT(PRStatus) 1.164 +_MD_CREATE_THREAD( 1.165 + PRThread *thread, 1.166 + void (*start) (void *), 1.167 + PRThreadPriority priority, 1.168 + PRThreadScope scope, 1.169 + PRThreadState state, 1.170 + PRUint32 stackSize) 1.171 +{ 1.172 + PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for AIX."); 1.173 +} 1.174 +#endif /* _PR_PTHREADS */ 1.175 +#endif /* PTHREADS_USER */ 1.176 + 1.177 +/* 1.178 + * NSPR 2.0 overrides the system select() and poll() functions. 1.179 + * On AIX 4.2, we use dlopen("/unix", RTLD_NOW) and dlsym() to get 1.180 + * at the original system select() and poll() functions. 1.181 + */ 1.182 + 1.183 +#if !defined(AIX_RENAME_SELECT) 1.184 + 1.185 +#include <sys/select.h> 1.186 +#include <sys/poll.h> 1.187 +#include <dlfcn.h> 1.188 + 1.189 +static int (*aix_select_fcn)() = NULL; 1.190 +static int (*aix_poll_fcn)() = NULL; 1.191 + 1.192 +int _MD_SELECT(int width, fd_set *r, fd_set *w, fd_set *e, struct timeval *t) 1.193 +{ 1.194 + int rv; 1.195 + 1.196 + if (!aix_select_fcn) { 1.197 + void *aix_handle; 1.198 + 1.199 + aix_handle = dlopen("/unix", RTLD_NOW); 1.200 + if (!aix_handle) { 1.201 + PR_SetError(PR_UNKNOWN_ERROR, 0); 1.202 + return -1; 1.203 + } 1.204 + aix_select_fcn = (int(*)())dlsym(aix_handle,"select"); 1.205 + dlclose(aix_handle); 1.206 + if (!aix_select_fcn) { 1.207 + PR_SetError(PR_UNKNOWN_ERROR, 0); 1.208 + return -1; 1.209 + } 1.210 + } 1.211 + rv = (*aix_select_fcn)(width, r, w, e, t); 1.212 + return rv; 1.213 +} 1.214 + 1.215 +int _MD_POLL(void *listptr, unsigned long nfds, long timeout) 1.216 +{ 1.217 + int rv; 1.218 + 1.219 + if (!aix_poll_fcn) { 1.220 + void *aix_handle; 1.221 + 1.222 + aix_handle = dlopen("/unix", RTLD_NOW); 1.223 + if (!aix_handle) { 1.224 + PR_SetError(PR_UNKNOWN_ERROR, 0); 1.225 + return -1; 1.226 + } 1.227 + aix_poll_fcn = (int(*)())dlsym(aix_handle,"poll"); 1.228 + dlclose(aix_handle); 1.229 + if (!aix_poll_fcn) { 1.230 + PR_SetError(PR_UNKNOWN_ERROR, 0); 1.231 + return -1; 1.232 + } 1.233 + } 1.234 + rv = (*aix_poll_fcn)(listptr, nfds, timeout); 1.235 + return rv; 1.236 +} 1.237 + 1.238 +#else 1.239 + 1.240 +/* 1.241 + * In AIX versions prior to 4.2, we use the two-step rename/link trick. 1.242 + * The binary must contain at least one "poll" symbol for linker's rename 1.243 + * to work. So we must have this dummy function that references poll(). 1.244 + */ 1.245 +#include <sys/poll.h> 1.246 +void _pr_aix_dummy() 1.247 +{ 1.248 + poll(0,0,0); 1.249 +} 1.250 + 1.251 +#endif /* !defined(AIX_RENAME_SELECT) */ 1.252 + 1.253 +#ifdef _PR_HAVE_ATOMIC_CAS 1.254 + 1.255 +#include "pratom.h" 1.256 + 1.257 +#define _PR_AIX_ATOMIC_LOCK -1 1.258 + 1.259 +PR_IMPLEMENT(void) 1.260 +PR_StackPush(PRStack *stack, PRStackElem *stack_elem) 1.261 +{ 1.262 +PRStackElem *addr; 1.263 +boolean_t locked = TRUE; 1.264 + 1.265 + /* Is it safe to cast a pointer to an int? */ 1.266 + PR_ASSERT(sizeof(int) == sizeof(PRStackElem *)); 1.267 + do { 1.268 + while ((addr = stack->prstk_head.prstk_elem_next) == 1.269 + (PRStackElem *)_PR_AIX_ATOMIC_LOCK) 1.270 + ; 1.271 + locked = _check_lock((atomic_p) &stack->prstk_head.prstk_elem_next, 1.272 + (int) addr, _PR_AIX_ATOMIC_LOCK); 1.273 + } while (locked == TRUE); 1.274 + stack_elem->prstk_elem_next = addr; 1.275 + _clear_lock((atomic_p)&stack->prstk_head.prstk_elem_next, (int)stack_elem); 1.276 + return; 1.277 +} 1.278 + 1.279 +PR_IMPLEMENT(PRStackElem *) 1.280 +PR_StackPop(PRStack *stack) 1.281 +{ 1.282 +PRStackElem *element; 1.283 +boolean_t locked = TRUE; 1.284 + 1.285 + /* Is it safe to cast a pointer to an int? */ 1.286 + PR_ASSERT(sizeof(int) == sizeof(PRStackElem *)); 1.287 + do { 1.288 + while ((element = stack->prstk_head.prstk_elem_next) == 1.289 + (PRStackElem *) _PR_AIX_ATOMIC_LOCK) 1.290 + ; 1.291 + locked = _check_lock((atomic_p) &stack->prstk_head.prstk_elem_next, 1.292 + (int)element, _PR_AIX_ATOMIC_LOCK); 1.293 + } while (locked == TRUE); 1.294 + 1.295 + if (element == NULL) { 1.296 + _clear_lock((atomic_p) &stack->prstk_head.prstk_elem_next, NULL); 1.297 + } else { 1.298 + _clear_lock((atomic_p) &stack->prstk_head.prstk_elem_next, 1.299 + (int) element->prstk_elem_next); 1.300 + } 1.301 + return element; 1.302 +} 1.303 + 1.304 +#endif /* _PR_HAVE_ATOMIC_CAS */