Back to index

lightning-sunbird  0.9+nobinonly
aix.c
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape Portable Runtime (NSPR).
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "primpl.h"
00039 
00040 #ifdef AIX_HAVE_ATOMIC_OP_H
00041 #include <sys/atomic_op.h>
00042 
00043 PRInt32 _AIX_AtomicSet(PRInt32 *val, PRInt32 newval)
00044 {
00045     PRIntn oldval;
00046     boolean_t stored;
00047     oldval = fetch_and_add((atomic_p)val, 0);
00048     do
00049     {
00050         stored = compare_and_swap((atomic_p)val, &oldval, newval);
00051     } while (!stored);
00052     return oldval;
00053 }  /* _AIX_AtomicSet */
00054 #endif /* AIX_HAVE_ATOMIC_OP_H */
00055 
00056 #if defined(AIX_TIMERS)
00057 
00058 #include <sys/time.h>
00059 
00060 static PRUint32 _aix_baseline_epoch;
00061 
00062 static void _MD_AixIntervalInit(void)
00063 {
00064     timebasestruct_t real_time;
00065     read_real_time(&real_time, TIMEBASE_SZ);
00066     (void)time_base_to_time(&real_time, TIMEBASE_SZ);
00067     _aix_baseline_epoch = real_time.tb_high;
00068 }  /* _MD_AixIntervalInit */
00069 
00070 PRIntervalTime _MD_AixGetInterval(void)
00071 {
00072     PRIntn rv;
00073     PRUint64 temp;
00074     timebasestruct_t real_time;
00075     read_real_time(&real_time, TIMEBASE_SZ);
00076     (void)time_base_to_time(&real_time, TIMEBASE_SZ);
00077     /* tb_high is in seconds, tb_low in 10(-9)seconds */
00078     temp = 1000000000ULL * (PRUint64)(real_time.tb_high - _aix_baseline_epoch);
00079     temp += (PRUint64)real_time.tb_low;  /* everything's 10(-9) seconds */
00080     temp >>= 16;  /* now it's something way different */
00081     return (PRIntervalTime)temp;
00082 }  /* _MD_AixGetInterval */
00083 
00084 PRIntervalTime _MD_AixIntervalPerSec(void)
00085 {
00086     return 1000000000ULL >> 16;  /* that's 15258, I think */
00087 }  /* _MD_AixIntervalPerSec */
00088 
00089 #endif /* defined(AIX_TIMERS) */
00090 
00091 #if !defined(PTHREADS_USER)
00092 
00093 #if defined(_PR_PTHREADS)
00094 
00095 /*
00096  * AIX 4.3 has sched_yield().  AIX 4.2 has pthread_yield().
00097  * So we look up the appropriate function pointer at run time.
00098  */
00099 
00100 #include <dlfcn.h>
00101 
00102 int (*_PT_aix_yield_fcn)() = NULL;
00103 int _pr_aix_send_file_use_disabled = 0;
00104 
00105 void _MD_EarlyInit(void)
00106 {
00107     void *main_app_handle;
00108        char *evp;
00109 
00110     main_app_handle = dlopen(NULL, RTLD_NOW);
00111     PR_ASSERT(NULL != main_app_handle);
00112 
00113     _PT_aix_yield_fcn = (int(*)())dlsym(main_app_handle, "sched_yield");
00114     if (!_PT_aix_yield_fcn) {
00115         _PT_aix_yield_fcn = (int(*)())dlsym(main_app_handle,"pthread_yield");
00116         PR_ASSERT(NULL != _PT_aix_yield_fcn);
00117     }
00118     dlclose(main_app_handle);
00119 
00120        if (evp = getenv("NSPR_AIX_SEND_FILE_USE_DISABLED")) {
00121               if (1 == atoi(evp))
00122                      _pr_aix_send_file_use_disabled = 1;
00123        }
00124 
00125 #if defined(AIX_TIMERS)
00126     _MD_AixIntervalInit();
00127 #endif
00128 }
00129 
00130 #else /* _PR_PTHREADS */
00131 
00132 void _MD_EarlyInit(void)
00133 {
00134 #if defined(AIX_TIMERS)
00135     _MD_AixIntervalInit();
00136 #endif
00137 }
00138 
00139 #endif /* _PR_PTHREADS */
00140 
00141 PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
00142 {
00143 #ifndef _PR_PTHREADS
00144     if (isCurrent) {
00145        (void) setjmp(CONTEXT(t));
00146     }
00147     *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
00148     return (PRWord *) CONTEXT(t);
00149 #else
00150        *np = 0;
00151        return NULL;
00152 #endif
00153 }
00154 
00155 #ifndef _PR_PTHREADS
00156 PR_IMPLEMENT(void)
00157 _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri)
00158 {
00159     return;
00160 }
00161 
00162 PR_IMPLEMENT(PRStatus)
00163 _MD_InitializeThread(PRThread *thread)
00164 {
00165        return PR_SUCCESS;
00166 }
00167 
00168 PR_IMPLEMENT(PRStatus)
00169 _MD_WAIT(PRThread *thread, PRIntervalTime ticks)
00170 {
00171     PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
00172     _PR_MD_SWITCH_CONTEXT(thread);
00173     return PR_SUCCESS;
00174 }
00175 
00176 PR_IMPLEMENT(PRStatus)
00177 _MD_WAKEUP_WAITER(PRThread *thread)
00178 {
00179     if (thread) {
00180        PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE));
00181     }
00182     return PR_SUCCESS;
00183 }
00184 
00185 /* These functions should not be called for AIX */
00186 PR_IMPLEMENT(void)
00187 _MD_YIELD(void)
00188 {
00189     PR_NOT_REACHED("_MD_YIELD should not be called for AIX.");
00190 }
00191 
00192 PR_IMPLEMENT(PRStatus)
00193 _MD_CREATE_THREAD(
00194     PRThread *thread,
00195     void (*start) (void *),
00196     PRThreadPriority priority,
00197     PRThreadScope scope,
00198     PRThreadState state,
00199     PRUint32 stackSize)
00200 {
00201     PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for AIX.");
00202 }
00203 #endif /* _PR_PTHREADS */
00204 #endif /* PTHREADS_USER */
00205 
00206 /*
00207  * NSPR 2.0 overrides the system select() and poll() functions.
00208  * On AIX 4.2, we use dlopen("/unix", RTLD_NOW) and dlsym() to get
00209  * at the original system select() and poll() functions.
00210  */
00211 
00212 #if !defined(AIX_RENAME_SELECT)
00213 
00214 #include <sys/select.h>
00215 #include <sys/poll.h>
00216 #include <dlfcn.h>
00217 
00218 static int (*aix_select_fcn)() = NULL;
00219 static int (*aix_poll_fcn)() = NULL;
00220 
00221 int _MD_SELECT(int width, fd_set *r, fd_set *w, fd_set *e, struct timeval *t)
00222 {
00223     int rv;
00224 
00225     if (!aix_select_fcn) {
00226         void *aix_handle;
00227 
00228        aix_handle = dlopen("/unix", RTLD_NOW);
00229        if (!aix_handle) {
00230            PR_SetError(PR_UNKNOWN_ERROR, 0);
00231            return -1;
00232        }
00233        aix_select_fcn = (int(*)())dlsym(aix_handle,"select");
00234         dlclose(aix_handle);
00235        if (!aix_select_fcn) {
00236            PR_SetError(PR_UNKNOWN_ERROR, 0);
00237            return -1;
00238        }
00239     }
00240     rv = (*aix_select_fcn)(width, r, w, e, t);
00241     return rv;
00242 }
00243 
00244 int _MD_POLL(void *listptr, unsigned long nfds, long timeout)
00245 {
00246     int rv;
00247 
00248     if (!aix_poll_fcn) {
00249         void *aix_handle;
00250 
00251        aix_handle = dlopen("/unix", RTLD_NOW);
00252        if (!aix_handle) {
00253            PR_SetError(PR_UNKNOWN_ERROR, 0);
00254            return -1;
00255        }
00256        aix_poll_fcn = (int(*)())dlsym(aix_handle,"poll");
00257         dlclose(aix_handle);
00258        if (!aix_poll_fcn) {
00259            PR_SetError(PR_UNKNOWN_ERROR, 0);
00260            return -1;
00261        }
00262     }
00263     rv = (*aix_poll_fcn)(listptr, nfds, timeout);
00264     return rv;
00265 }
00266 
00267 #else
00268 
00269 /*
00270  * In AIX versions prior to 4.2, we use the two-step rename/link trick.
00271  * The binary must contain at least one "poll" symbol for linker's rename
00272  * to work.  So we must have this dummy function that references poll().
00273  */
00274 #include <sys/poll.h>
00275 void _pr_aix_dummy()
00276 {
00277     poll(0,0,0);
00278 }
00279 
00280 #endif /* !defined(AIX_RENAME_SELECT) */
00281 
00282 #ifdef _PR_HAVE_ATOMIC_CAS
00283 
00284 #include "pratom.h"
00285 
00286 #define _PR_AIX_ATOMIC_LOCK -1
00287 
00288 PR_IMPLEMENT(void)
00289 PR_StackPush(PRStack *stack, PRStackElem *stack_elem)
00290 {
00291 PRStackElem *addr;
00292 boolean_t locked = TRUE;
00293 
00294        /* Is it safe to cast a pointer to an int? */
00295        PR_ASSERT(sizeof(int) == sizeof(PRStackElem *));
00296        do {
00297               while ((addr = stack->prstk_head.prstk_elem_next) ==
00298                                                                              (PRStackElem *)_PR_AIX_ATOMIC_LOCK)
00299                      ;
00300               locked = _check_lock((atomic_p) &stack->prstk_head.prstk_elem_next,
00301                                                  (int) addr, _PR_AIX_ATOMIC_LOCK);
00302        } while (locked == TRUE);
00303        stack_elem->prstk_elem_next = addr;
00304        _clear_lock((atomic_p)&stack->prstk_head.prstk_elem_next, (int)stack_elem);
00305     return;
00306 }
00307 
00308 PR_IMPLEMENT(PRStackElem *)
00309 PR_StackPop(PRStack *stack)
00310 {
00311 PRStackElem *element;
00312 boolean_t locked = TRUE;
00313 
00314        /* Is it safe to cast a pointer to an int? */
00315        PR_ASSERT(sizeof(int) == sizeof(PRStackElem *));
00316        do {
00317               while ((element = stack->prstk_head.prstk_elem_next) ==
00318                                                                       (PRStackElem *) _PR_AIX_ATOMIC_LOCK)
00319                      ;
00320               locked = _check_lock((atomic_p) &stack->prstk_head.prstk_elem_next,
00321                                                  (int)element, _PR_AIX_ATOMIC_LOCK);
00322        } while (locked == TRUE);
00323 
00324        if (element == NULL) {
00325               _clear_lock((atomic_p) &stack->prstk_head.prstk_elem_next, NULL);
00326        } else {
00327               _clear_lock((atomic_p) &stack->prstk_head.prstk_elem_next,
00328                                                                       (int) element->prstk_elem_next);
00329        }
00330        return element;
00331 }
00332 
00333 #endif /* _PR_HAVE_ATOMIC_CAS */