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.

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

mercurial