Wed, 31 Dec 2014 06:09:35 +0100
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 */