diff options
Diffstat (limited to 'nsprpub/pr/src/md/unix/irix.c')
-rw-r--r-- | nsprpub/pr/src/md/unix/irix.c | 1648 |
1 files changed, 0 insertions, 1648 deletions
diff --git a/nsprpub/pr/src/md/unix/irix.c b/nsprpub/pr/src/md/unix/irix.c deleted file mode 100644 index c57a07b33..000000000 --- a/nsprpub/pr/src/md/unix/irix.c +++ /dev/null @@ -1,1648 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "primpl.h" - -#include <signal.h> - -#include <sys/types.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> -#include <sys/mman.h> -#include <sys/syssgi.h> -#include <sys/time.h> -#include <sys/immu.h> -#include <sys/utsname.h> -#include <sys/sysmp.h> -#include <sys/pda.h> -#include <sys/prctl.h> -#include <sys/wait.h> -#include <sys/resource.h> -#include <sys/procfs.h> -#include <task.h> -#include <dlfcn.h> - -static void _MD_IrixIntervalInit(void); - -#if defined(_PR_PTHREADS) -/* - * for compatibility with classic nspr - */ -void _PR_IRIX_CHILD_PROCESS() -{ -} -#else /* defined(_PR_PTHREADS) */ - -static void irix_detach_sproc(void); -char *_nspr_sproc_private; /* ptr. to private region in every sproc */ - -extern PRUintn _pr_numCPU; - -typedef struct nspr_arena { - PRCList links; - usptr_t *usarena; -} nspr_arena; - -#define ARENA_PTR(qp) \ - ((nspr_arena *) ((char*) (qp) - offsetof(nspr_arena , links))) - -static usptr_t *alloc_new_arena(void); - -PRCList arena_list = PR_INIT_STATIC_CLIST(&arena_list); -ulock_t arena_list_lock; -nspr_arena first_arena; -int _nspr_irix_arena_cnt = 1; - -PRCList sproc_list = PR_INIT_STATIC_CLIST(&sproc_list); -ulock_t sproc_list_lock; - -typedef struct sproc_data { - void (*entry) (void *, size_t); - unsigned inh; - void *arg; - caddr_t sp; - size_t len; - int *pid; - int creator_pid; -} sproc_data; - -typedef struct sproc_params { - PRCList links; - sproc_data sd; -} sproc_params; - -#define SPROC_PARAMS_PTR(qp) \ - ((sproc_params *) ((char*) (qp) - offsetof(sproc_params , links))) - -long _nspr_irix_lock_cnt = 0; -long _nspr_irix_sem_cnt = 0; -long _nspr_irix_pollsem_cnt = 0; - -usptr_t *_pr_usArena; -ulock_t _pr_heapLock; - -usema_t *_pr_irix_exit_sem; -PRInt32 _pr_irix_exit_now = 0; -PRInt32 _pr_irix_process_exit_code = 0; /* exit code for PR_ProcessExit */ -PRInt32 _pr_irix_process_exit = 0; /* process exiting due to call to - PR_ProcessExit */ - -int _pr_irix_primoridal_cpu_fd[2] = { -1, -1 }; -static void (*libc_exit)(int) = NULL; -static void *libc_handle = NULL; - -#define _NSPR_DEF_INITUSERS 100 /* default value of CONF_INITUSERS */ -#define _NSPR_DEF_INITSIZE (4 * 1024 * 1024) /* 4 MB */ - -int _irix_initusers = _NSPR_DEF_INITUSERS; -int _irix_initsize = _NSPR_DEF_INITSIZE; - -PRIntn _pr_io_in_progress, _pr_clock_in_progress; - -PRInt32 _pr_md_irix_sprocs_created, _pr_md_irix_sprocs_failed; -PRInt32 _pr_md_irix_sprocs = 1; -PRCList _pr_md_irix_sproc_list = -PR_INIT_STATIC_CLIST(&_pr_md_irix_sproc_list); - -sigset_t ints_off; -extern sigset_t timer_set; - -#if !defined(PR_SETABORTSIG) -#define PR_SETABORTSIG 18 -#endif -/* - * terminate the entire application if any sproc exits abnormally - */ -PRBool _nspr_terminate_on_error = PR_TRUE; - -/* - * exported interface to set the shared arena parameters - */ -void _PR_Irix_Set_Arena_Params(PRInt32 initusers, PRInt32 initsize) -{ - _irix_initusers = initusers; - _irix_initsize = initsize; -} - -static usptr_t *alloc_new_arena() -{ - return(usinit("/dev/zero")); -} - -static PRStatus new_poll_sem(struct _MDThread *mdthr, int val) -{ -PRIntn _is; -PRStatus rv = PR_SUCCESS; -usema_t *sem = NULL; -PRCList *qp; -nspr_arena *arena; -usptr_t *irix_arena; -PRThread *me = _MD_GET_ATTACHED_THREAD(); - - if (me && !_PR_IS_NATIVE_THREAD(me)) - _PR_INTSOFF(_is); - _PR_LOCK(arena_list_lock); - for (qp = arena_list.next; qp != &arena_list; qp = qp->next) { - arena = ARENA_PTR(qp); - sem = usnewpollsema(arena->usarena, val); - if (sem != NULL) { - mdthr->cvar_pollsem = sem; - mdthr->pollsem_arena = arena->usarena; - break; - } - } - if (sem == NULL) { - /* - * If no space left in the arena allocate a new one. - */ - if (errno == ENOMEM) { - arena = PR_NEWZAP(nspr_arena); - if (arena != NULL) { - irix_arena = alloc_new_arena(); - if (irix_arena) { - PR_APPEND_LINK(&arena->links, &arena_list); - _nspr_irix_arena_cnt++; - arena->usarena = irix_arena; - sem = usnewpollsema(arena->usarena, val); - if (sem != NULL) { - mdthr->cvar_pollsem = sem; - mdthr->pollsem_arena = arena->usarena; - } else - rv = PR_FAILURE; - } else { - PR_DELETE(arena); - rv = PR_FAILURE; - } - - } else - rv = PR_FAILURE; - } else - rv = PR_FAILURE; - } - _PR_UNLOCK(arena_list_lock); - if (me && !_PR_IS_NATIVE_THREAD(me)) - _PR_FAST_INTSON(_is); - if (rv == PR_SUCCESS) - _MD_ATOMIC_INCREMENT(&_nspr_irix_pollsem_cnt); - return rv; -} - -static void free_poll_sem(struct _MDThread *mdthr) -{ -PRIntn _is; -PRThread *me = _MD_GET_ATTACHED_THREAD(); - - if (me && !_PR_IS_NATIVE_THREAD(me)) - _PR_INTSOFF(_is); - usfreepollsema(mdthr->cvar_pollsem, mdthr->pollsem_arena); - if (me && !_PR_IS_NATIVE_THREAD(me)) - _PR_FAST_INTSON(_is); - _MD_ATOMIC_DECREMENT(&_nspr_irix_pollsem_cnt); -} - -static PRStatus new_lock(struct _MDLock *lockp) -{ -PRIntn _is; -PRStatus rv = PR_SUCCESS; -ulock_t lock = NULL; -PRCList *qp; -nspr_arena *arena; -usptr_t *irix_arena; -PRThread *me = _MD_GET_ATTACHED_THREAD(); - - if (me && !_PR_IS_NATIVE_THREAD(me)) - _PR_INTSOFF(_is); - _PR_LOCK(arena_list_lock); - for (qp = arena_list.next; qp != &arena_list; qp = qp->next) { - arena = ARENA_PTR(qp); - lock = usnewlock(arena->usarena); - if (lock != NULL) { - lockp->lock = lock; - lockp->arena = arena->usarena; - break; - } - } - if (lock == NULL) { - /* - * If no space left in the arena allocate a new one. - */ - if (errno == ENOMEM) { - arena = PR_NEWZAP(nspr_arena); - if (arena != NULL) { - irix_arena = alloc_new_arena(); - if (irix_arena) { - PR_APPEND_LINK(&arena->links, &arena_list); - _nspr_irix_arena_cnt++; - arena->usarena = irix_arena; - lock = usnewlock(irix_arena); - if (lock != NULL) { - lockp->lock = lock; - lockp->arena = arena->usarena; - } else - rv = PR_FAILURE; - } else { - PR_DELETE(arena); - rv = PR_FAILURE; - } - - } else - rv = PR_FAILURE; - } else - rv = PR_FAILURE; - } - _PR_UNLOCK(arena_list_lock); - if (me && !_PR_IS_NATIVE_THREAD(me)) - _PR_FAST_INTSON(_is); - if (rv == PR_SUCCESS) - _MD_ATOMIC_INCREMENT(&_nspr_irix_lock_cnt); - return rv; -} - -static void free_lock(struct _MDLock *lockp) -{ -PRIntn _is; -PRThread *me = _MD_GET_ATTACHED_THREAD(); - - if (me && !_PR_IS_NATIVE_THREAD(me)) - _PR_INTSOFF(_is); - usfreelock(lockp->lock, lockp->arena); - if (me && !_PR_IS_NATIVE_THREAD(me)) - _PR_FAST_INTSON(_is); - _MD_ATOMIC_DECREMENT(&_nspr_irix_lock_cnt); -} - -void _MD_FREE_LOCK(struct _MDLock *lockp) -{ - PRIntn _is; - PRThread *me = _MD_GET_ATTACHED_THREAD(); - - if (me && !_PR_IS_NATIVE_THREAD(me)) - _PR_INTSOFF(_is); - free_lock(lockp); - if (me && !_PR_IS_NATIVE_THREAD(me)) - _PR_FAST_INTSON(_is); -} - -/* - * _MD_get_attached_thread - * Return the thread pointer of the current thread if it is attached. - * - * This function is needed for Irix because the thread-local-storage is - * implemented by mmapin'g a page with the MAP_LOCAL flag. This causes the - * sproc-private page to inherit contents of the page of the caller of sproc(). - */ -PRThread *_MD_get_attached_thread(void) -{ - - if (_MD_GET_SPROC_PID() == get_pid()) - return _MD_THIS_THREAD(); - else - return 0; -} - -/* - * _MD_get_current_thread - * Return the thread pointer of the current thread (attaching it if - * necessary) - */ -PRThread *_MD_get_current_thread(void) -{ -PRThread *me; - - me = _MD_GET_ATTACHED_THREAD(); - if (NULL == me) { - me = _PRI_AttachThread( - PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL, 0); - } - PR_ASSERT(me != NULL); - return(me); -} - -/* - * irix_detach_sproc - * auto-detach a sproc when it exits - */ -void irix_detach_sproc(void) -{ -PRThread *me; - - me = _MD_GET_ATTACHED_THREAD(); - if ((me != NULL) && (me->flags & _PR_ATTACHED)) { - _PRI_DetachThread(); - } -} - - -PRStatus _MD_NEW_LOCK(struct _MDLock *lockp) -{ - PRStatus rv; - PRIntn is; - PRThread *me = _MD_GET_ATTACHED_THREAD(); - - if (me && !_PR_IS_NATIVE_THREAD(me)) - _PR_INTSOFF(is); - rv = new_lock(lockp); - if (me && !_PR_IS_NATIVE_THREAD(me)) - _PR_FAST_INTSON(is); - return rv; -} - -static void -sigchld_handler(int sig) -{ - pid_t pid; - int status; - - /* - * If an sproc exited abnormally send a SIGKILL signal to all the - * sprocs in the process to terminate the application - */ - while ((pid = waitpid(0, &status, WNOHANG)) > 0) { - if (WIFSIGNALED(status) && ((WTERMSIG(status) == SIGSEGV) || - (WTERMSIG(status) == SIGBUS) || - (WTERMSIG(status) == SIGABRT) || - (WTERMSIG(status) == SIGILL))) { - - prctl(PR_SETEXITSIG, SIGKILL); - _exit(status); - } - } -} - -static void save_context_and_block(int sig) -{ -PRThread *me = _PR_MD_CURRENT_THREAD(); -_PRCPU *cpu = _PR_MD_CURRENT_CPU(); - - /* - * save context - */ - (void) setjmp(me->md.jb); - /* - * unblock the suspending thread - */ - if (me->cpu) { - /* - * I am a cpu thread, not a user-created GLOBAL thread - */ - unblockproc(cpu->md.suspending_id); - } else { - unblockproc(me->md.suspending_id); - } - /* - * now, block current thread - */ - blockproc(getpid()); -} - -/* -** The irix kernel has a bug in it which causes async connect's which are -** interrupted by a signal to fail terribly (EADDRINUSE is returned). -** We work around the bug by blocking signals during the async connect -** attempt. -*/ -PRInt32 _MD_irix_connect( - PRInt32 osfd, const PRNetAddr *addr, PRInt32 addrlen, PRIntervalTime timeout) -{ - PRInt32 rv; - sigset_t oldset; - - sigprocmask(SIG_BLOCK, &ints_off, &oldset); - rv = connect(osfd, addr, addrlen); - sigprocmask(SIG_SETMASK, &oldset, 0); - - return(rv); -} - -#include "prprf.h" - -/********************************************************************/ -/********************************************************************/ -/*************** Various thread like things for IRIX ****************/ -/********************************************************************/ -/********************************************************************/ - -void *_MD_GetSP(PRThread *t) -{ - PRThread *me = _PR_MD_CURRENT_THREAD(); - void *sp; - - if (me == t) - (void) setjmp(t->md.jb); - - sp = (void *)(t->md.jb[JB_SP]); - PR_ASSERT((sp >= (void *) t->stack->stackBottom) && - (sp <= (void *) (t->stack->stackBottom + t->stack->stackSize))); - return(sp); -} - -void _MD_InitLocks() -{ - char buf[200]; - char *init_users, *init_size; - - PR_snprintf(buf, sizeof(buf), "/dev/zero"); - - if (init_users = getenv("_NSPR_IRIX_INITUSERS")) - _irix_initusers = atoi(init_users); - - if (init_size = getenv("_NSPR_IRIX_INITSIZE")) - _irix_initsize = atoi(init_size); - - usconfig(CONF_INITUSERS, _irix_initusers); - usconfig(CONF_INITSIZE, _irix_initsize); - usconfig(CONF_AUTOGROW, 1); - usconfig(CONF_AUTORESV, 1); - if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0) { - perror("PR_Init: unable to config mutex arena"); - exit(-1); - } - - _pr_usArena = usinit(buf); - if (!_pr_usArena) { - fprintf(stderr, - "PR_Init: Error - unable to create lock/monitor arena\n"); - exit(-1); - } - _pr_heapLock = usnewlock(_pr_usArena); - _nspr_irix_lock_cnt++; - - arena_list_lock = usnewlock(_pr_usArena); - _nspr_irix_lock_cnt++; - - sproc_list_lock = usnewlock(_pr_usArena); - _nspr_irix_lock_cnt++; - - _pr_irix_exit_sem = usnewsema(_pr_usArena, 0); - _nspr_irix_sem_cnt = 1; - - first_arena.usarena = _pr_usArena; - PR_INIT_CLIST(&first_arena.links); - PR_APPEND_LINK(&first_arena.links, &arena_list); -} - -/* _PR_IRIX_CHILD_PROCESS is a private API for Server group */ -void _PR_IRIX_CHILD_PROCESS() -{ -extern PRUint32 _pr_global_threads; - - PR_ASSERT(_PR_MD_CURRENT_CPU() == _pr_primordialCPU); - PR_ASSERT(_pr_numCPU == 1); - PR_ASSERT(_pr_global_threads == 0); - /* - * save the new pid - */ - _pr_primordialCPU->md.id = getpid(); - _MD_SET_SPROC_PID(getpid()); -} - -static PRStatus pr_cvar_wait_sem(PRThread *thread, PRIntervalTime timeout) -{ - int rv; - -#ifdef _PR_USE_POLL - struct pollfd pfd; - int msecs; - - if (timeout == PR_INTERVAL_NO_TIMEOUT) - msecs = -1; - else - msecs = PR_IntervalToMilliseconds(timeout); -#else - struct timeval tv, *tvp; - fd_set rd; - - if(timeout == PR_INTERVAL_NO_TIMEOUT) - tvp = NULL; - else { - tv.tv_sec = PR_IntervalToSeconds(timeout); - tv.tv_usec = PR_IntervalToMicroseconds( - timeout - PR_SecondsToInterval(tv.tv_sec)); - tvp = &tv; - } - FD_ZERO(&rd); - FD_SET(thread->md.cvar_pollsemfd, &rd); -#endif - - /* - * call uspsema only if a previous select call on this semaphore - * did not timeout - */ - if (!thread->md.cvar_pollsem_select) { - rv = _PR_WAIT_SEM(thread->md.cvar_pollsem); - PR_ASSERT(rv >= 0); - } else - rv = 0; -again: - if(!rv) { -#ifdef _PR_USE_POLL - pfd.events = POLLIN; - pfd.fd = thread->md.cvar_pollsemfd; - rv = _MD_POLL(&pfd, 1, msecs); -#else - rv = _MD_SELECT(thread->md.cvar_pollsemfd + 1, &rd, NULL,NULL,tvp); -#endif - if ((rv == -1) && (errno == EINTR)) { - rv = 0; - goto again; - } - PR_ASSERT(rv >= 0); - } - - if (rv > 0) { - /* - * acquired the semaphore, call uspsema next time - */ - thread->md.cvar_pollsem_select = 0; - return PR_SUCCESS; - } else { - /* - * select timed out; must call select, not uspsema, when trying - * to acquire the semaphore the next time - */ - thread->md.cvar_pollsem_select = 1; - return PR_FAILURE; - } -} - -PRStatus _MD_wait(PRThread *thread, PRIntervalTime ticks) -{ - if ( thread->flags & _PR_GLOBAL_SCOPE ) { - _MD_CHECK_FOR_EXIT(); - if (pr_cvar_wait_sem(thread, ticks) == PR_FAILURE) { - _MD_CHECK_FOR_EXIT(); - /* - * wait timed out - */ - _PR_THREAD_LOCK(thread); - if (thread->wait.cvar) { - /* - * The thread will remove itself from the waitQ - * of the cvar in _PR_WaitCondVar - */ - thread->wait.cvar = NULL; - thread->state = _PR_RUNNING; - _PR_THREAD_UNLOCK(thread); - } else { - _PR_THREAD_UNLOCK(thread); - /* - * This thread was woken up by a notifying thread - * at the same time as a timeout; so, consume the - * extra post operation on the semaphore - */ - _MD_CHECK_FOR_EXIT(); - pr_cvar_wait_sem(thread, PR_INTERVAL_NO_TIMEOUT); - } - _MD_CHECK_FOR_EXIT(); - } - } else { - _PR_MD_SWITCH_CONTEXT(thread); - } - return PR_SUCCESS; -} - -PRStatus _MD_WakeupWaiter(PRThread *thread) -{ - PRThread *me = _PR_MD_CURRENT_THREAD(); - PRIntn is; - - PR_ASSERT(_pr_md_idle_cpus >= 0); - if (thread == NULL) { - if (_pr_md_idle_cpus) - _MD_Wakeup_CPUs(); - } else if (!_PR_IS_NATIVE_THREAD(thread)) { - if (_pr_md_idle_cpus) - _MD_Wakeup_CPUs(); - } else { - PR_ASSERT(_PR_IS_NATIVE_THREAD(thread)); - if (!_PR_IS_NATIVE_THREAD(me)) - _PR_INTSOFF(is); - _MD_CVAR_POST_SEM(thread); - if (!_PR_IS_NATIVE_THREAD(me)) - _PR_FAST_INTSON(is); - } - return PR_SUCCESS; -} - -void create_sproc (void (*entry) (void *, size_t), unsigned inh, - void *arg, caddr_t sp, size_t len, int *pid) -{ -sproc_params sparams; -char data; -int rv; -PRThread *me = _PR_MD_CURRENT_THREAD(); - - if (!_PR_IS_NATIVE_THREAD(me) && (_PR_MD_CURRENT_CPU()->id == 0)) { - *pid = sprocsp(entry, /* startup func */ - inh, /* attribute flags */ - arg, /* thread param */ - sp, /* stack address */ - len); /* stack size */ - } else { - sparams.sd.entry = entry; - sparams.sd.inh = inh; - sparams.sd.arg = arg; - sparams.sd.sp = sp; - sparams.sd.len = len; - sparams.sd.pid = pid; - sparams.sd.creator_pid = getpid(); - _PR_LOCK(sproc_list_lock); - PR_APPEND_LINK(&sparams.links, &sproc_list); - rv = write(_pr_irix_primoridal_cpu_fd[1], &data, 1); - PR_ASSERT(rv == 1); - _PR_UNLOCK(sproc_list_lock); - blockproc(getpid()); - } -} - -/* - * _PR_MD_WAKEUP_PRIMORDIAL_CPU - * - * wakeup cpu 0 - */ - -void _PR_MD_WAKEUP_PRIMORDIAL_CPU() -{ -char data = '0'; -int rv; - - rv = write(_pr_irix_primoridal_cpu_fd[1], &data, 1); - PR_ASSERT(rv == 1); -} - -/* - * _PR_MD_primordial_cpu - * - * process events that need to executed by the primordial cpu on each - * iteration through the idle loop - */ - -void _PR_MD_primordial_cpu() -{ -PRCList *qp; -sproc_params *sp; -int pid; - - _PR_LOCK(sproc_list_lock); - while ((qp = sproc_list.next) != &sproc_list) { - sp = SPROC_PARAMS_PTR(qp); - PR_REMOVE_LINK(&sp->links); - pid = sp->sd.creator_pid; - (*(sp->sd.pid)) = sprocsp(sp->sd.entry, /* startup func */ - sp->sd.inh, /* attribute flags */ - sp->sd.arg, /* thread param */ - sp->sd.sp, /* stack address */ - sp->sd.len); /* stack size */ - unblockproc(pid); - } - _PR_UNLOCK(sproc_list_lock); -} - -PRStatus _MD_CreateThread(PRThread *thread, -void (*start)(void *), -PRThreadPriority priority, -PRThreadScope scope, -PRThreadState state, -PRUint32 stackSize) -{ - typedef void (*SprocEntry) (void *, size_t); - SprocEntry spentry = (SprocEntry)start; - PRIntn is; - PRThread *me = _PR_MD_CURRENT_THREAD(); - PRInt32 pid; - PRStatus rv; - - if (!_PR_IS_NATIVE_THREAD(me)) - _PR_INTSOFF(is); - thread->md.cvar_pollsem_select = 0; - thread->flags |= _PR_GLOBAL_SCOPE; - - thread->md.cvar_pollsemfd = -1; - if (new_poll_sem(&thread->md,0) == PR_FAILURE) { - if (!_PR_IS_NATIVE_THREAD(me)) - _PR_FAST_INTSON(is); - return PR_FAILURE; - } - thread->md.cvar_pollsemfd = - _PR_OPEN_POLL_SEM(thread->md.cvar_pollsem); - if ((thread->md.cvar_pollsemfd < 0)) { - free_poll_sem(&thread->md); - if (!_PR_IS_NATIVE_THREAD(me)) - _PR_FAST_INTSON(is); - return PR_FAILURE; - } - - create_sproc(spentry, /* startup func */ - PR_SALL, /* attribute flags */ - (void *)thread, /* thread param */ - NULL, /* stack address */ - stackSize, &pid); /* stack size */ - if (pid > 0) { - _MD_ATOMIC_INCREMENT(&_pr_md_irix_sprocs_created); - _MD_ATOMIC_INCREMENT(&_pr_md_irix_sprocs); - rv = PR_SUCCESS; - if (!_PR_IS_NATIVE_THREAD(me)) - _PR_FAST_INTSON(is); - return rv; - } else { - close(thread->md.cvar_pollsemfd); - thread->md.cvar_pollsemfd = -1; - free_poll_sem(&thread->md); - thread->md.cvar_pollsem = NULL; - _MD_ATOMIC_INCREMENT(&_pr_md_irix_sprocs_failed); - if (!_PR_IS_NATIVE_THREAD(me)) - _PR_FAST_INTSON(is); - return PR_FAILURE; - } -} - -void _MD_CleanThread(PRThread *thread) -{ - if (thread->flags & _PR_GLOBAL_SCOPE) { - close(thread->md.cvar_pollsemfd); - thread->md.cvar_pollsemfd = -1; - free_poll_sem(&thread->md); - thread->md.cvar_pollsem = NULL; - } -} - -void _MD_SetPriority(_MDThread *thread, PRThreadPriority newPri) -{ - return; -} - -extern void _MD_unix_terminate_waitpid_daemon(void); - -void -_MD_CleanupBeforeExit(void) -{ - extern PRInt32 _pr_cpus_exit; - - _MD_unix_terminate_waitpid_daemon(); - - _pr_irix_exit_now = 1; - if (_pr_numCPU > 1) { - /* - * Set a global flag, and wakeup all cpus which will notice the flag - * and exit. - */ - _pr_cpus_exit = getpid(); - _MD_Wakeup_CPUs(); - while(_pr_numCPU > 1) { - _PR_WAIT_SEM(_pr_irix_exit_sem); - _pr_numCPU--; - } - } - /* - * cause global threads on the recycle list to exit - */ - _PR_DEADQ_LOCK; - if (_PR_NUM_DEADNATIVE != 0) { - PRThread *thread; - PRCList *ptr; - - ptr = _PR_DEADNATIVEQ.next; - while( ptr != &_PR_DEADNATIVEQ ) { - thread = _PR_THREAD_PTR(ptr); - _MD_CVAR_POST_SEM(thread); - ptr = ptr->next; - } - } - _PR_DEADQ_UNLOCK; - while(_PR_NUM_DEADNATIVE > 1) { - _PR_WAIT_SEM(_pr_irix_exit_sem); - _PR_DEC_DEADNATIVE; - } -} - -#ifdef _PR_HAVE_SGI_PRDA_PROCMASK -extern void __sgi_prda_procmask(int); -#endif - -PRStatus -_MD_InitAttachedThread(PRThread *thread, PRBool wakeup_parent) -{ - PRStatus rv = PR_SUCCESS; - - if (thread->flags & _PR_GLOBAL_SCOPE) { - if (new_poll_sem(&thread->md,0) == PR_FAILURE) { - return PR_FAILURE; - } - thread->md.cvar_pollsemfd = - _PR_OPEN_POLL_SEM(thread->md.cvar_pollsem); - if ((thread->md.cvar_pollsemfd < 0)) { - free_poll_sem(&thread->md); - return PR_FAILURE; - } - if (_MD_InitThread(thread, PR_FALSE) == PR_FAILURE) { - close(thread->md.cvar_pollsemfd); - thread->md.cvar_pollsemfd = -1; - free_poll_sem(&thread->md); - thread->md.cvar_pollsem = NULL; - return PR_FAILURE; - } - } - return rv; -} - -PRStatus -_MD_InitThread(PRThread *thread, PRBool wakeup_parent) -{ - struct sigaction sigact; - PRStatus rv = PR_SUCCESS; - - if (thread->flags & _PR_GLOBAL_SCOPE) { - thread->md.id = getpid(); - setblockproccnt(thread->md.id, 0); - _MD_SET_SPROC_PID(getpid()); -#ifdef _PR_HAVE_SGI_PRDA_PROCMASK - /* - * enable user-level processing of sigprocmask(); this is an - * undocumented feature available in Irix 6.2, 6.3, 6.4 and 6.5 - */ - __sgi_prda_procmask(USER_LEVEL); -#endif - /* - * set up SIGUSR1 handler; this is used to save state - */ - sigact.sa_handler = save_context_and_block; - sigact.sa_flags = SA_RESTART; - /* - * Must mask clock interrupts - */ - sigact.sa_mask = timer_set; - sigaction(SIGUSR1, &sigact, 0); - - - /* - * PR_SETABORTSIG is a new command implemented in a patch to - * Irix 6.2, 6.3 and 6.4. This causes a signal to be sent to all - * sprocs in the process when one of them terminates abnormally - * - */ - if (prctl(PR_SETABORTSIG, SIGKILL) < 0) { - /* - * if (errno == EINVAL) - * - * PR_SETABORTSIG not supported under this OS. - * You may want to get a recent kernel rollup patch that - * supports this feature. - */ - } - /* - * SIGCLD handler for detecting abormally-terminating - * sprocs and for reaping sprocs - */ - sigact.sa_handler = sigchld_handler; - sigact.sa_flags = SA_RESTART; - sigact.sa_mask = ints_off; - sigaction(SIGCLD, &sigact, NULL); - } - return rv; -} - -/* - * PR_Cleanup should be executed on the primordial sproc; migrate the thread - * to the primordial cpu - */ - -void _PR_MD_PRE_CLEANUP(PRThread *me) -{ -PRIntn is; -_PRCPU *cpu = _pr_primordialCPU; - - PR_ASSERT(cpu); - - me->flags |= _PR_BOUND_THREAD; - - if (me->cpu->id != 0) { - _PR_INTSOFF(is); - _PR_RUNQ_LOCK(cpu); - me->cpu = cpu; - me->state = _PR_RUNNABLE; - _PR_ADD_RUNQ(me, cpu, me->priority); - _PR_RUNQ_UNLOCK(cpu); - _MD_Wakeup_CPUs(); - - _PR_MD_SWITCH_CONTEXT(me); - - _PR_FAST_INTSON(is); - PR_ASSERT(me->cpu->id == 0); - } -} - -/* - * process exiting - */ -PR_EXTERN(void ) _MD_exit(PRIntn status) -{ -PRThread *me = _PR_MD_CURRENT_THREAD(); - - /* - * the exit code of the process is the exit code of the primordial - * sproc - */ - if (!_PR_IS_NATIVE_THREAD(me) && (_PR_MD_CURRENT_CPU()->id == 0)) { - /* - * primordial sproc case: call _exit directly - * Cause SIGKILL to be sent to other sprocs - */ - prctl(PR_SETEXITSIG, SIGKILL); - _exit(status); - } else { - int rv; - char data; - sigset_t set; - - /* - * non-primordial sproc case: cause the primordial sproc, cpu 0, - * to wakeup and call _exit - */ - _pr_irix_process_exit = 1; - _pr_irix_process_exit_code = status; - rv = write(_pr_irix_primoridal_cpu_fd[1], &data, 1); - PR_ASSERT(rv == 1); - /* - * block all signals and wait for SIGKILL to terminate this sproc - */ - sigfillset(&set); - sigsuspend(&set); - /* - * this code doesn't (shouldn't) execute - */ - prctl(PR_SETEXITSIG, SIGKILL); - _exit(status); - } -} - -/* - * Override the exit() function in libc to cause the process to exit - * when the primodial/main nspr thread calls exit. Calls to exit by any - * other thread simply result in a call to the exit function in libc. - * The exit code of the process is the exit code of the primordial - * sproc. - */ - -void exit(int status) -{ -PRThread *me, *thr; -PRCList *qp; - - if (!_pr_initialized) { - if (!libc_exit) { - - if (!libc_handle) - libc_handle = dlopen("libc.so",RTLD_NOW); - if (libc_handle) - libc_exit = (void (*)(int)) dlsym(libc_handle, "exit"); - } - if (libc_exit) - (*libc_exit)(status); - else - _exit(status); - } - - me = _PR_MD_CURRENT_THREAD(); - - if (me == NULL) /* detached thread */ - (*libc_exit)(status); - - PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || - (_PR_MD_CURRENT_CPU())->id == me->cpu->id); - - if (me->flags & _PR_PRIMORDIAL) { - - me->flags |= _PR_BOUND_THREAD; - - PR_ASSERT((_PR_MD_CURRENT_CPU())->id == me->cpu->id); - if (me->cpu->id != 0) { - _PRCPU *cpu = _pr_primordialCPU; - PRIntn is; - - _PR_INTSOFF(is); - _PR_RUNQ_LOCK(cpu); - me->cpu = cpu; - me->state = _PR_RUNNABLE; - _PR_ADD_RUNQ(me, cpu, me->priority); - _PR_RUNQ_UNLOCK(cpu); - _MD_Wakeup_CPUs(); - - _PR_MD_SWITCH_CONTEXT(me); - - _PR_FAST_INTSON(is); - } - - PR_ASSERT((_PR_MD_CURRENT_CPU())->id == 0); - - if (prctl(PR_GETNSHARE) > 1) { -#define SPROC_EXIT_WAIT_TIME 5 - int sleep_cnt = SPROC_EXIT_WAIT_TIME; - - /* - * sprocs still running; caue cpus and recycled global threads - * to exit - */ - _pr_irix_exit_now = 1; - if (_pr_numCPU > 1) { - _MD_Wakeup_CPUs(); - } - _PR_DEADQ_LOCK; - if (_PR_NUM_DEADNATIVE != 0) { - PRThread *thread; - PRCList *ptr; - - ptr = _PR_DEADNATIVEQ.next; - while( ptr != &_PR_DEADNATIVEQ ) { - thread = _PR_THREAD_PTR(ptr); - _MD_CVAR_POST_SEM(thread); - ptr = ptr->next; - } - } - - while (sleep_cnt-- > 0) { - if (waitpid(0, NULL, WNOHANG) >= 0) - sleep(1); - else - break; - } - prctl(PR_SETEXITSIG, SIGKILL); - } - (*libc_exit)(status); - } else { - /* - * non-primordial thread; simply call exit in libc. - */ - (*libc_exit)(status); - } -} - - -void -_MD_InitRunningCPU(_PRCPU *cpu) -{ - extern int _pr_md_pipefd[2]; - - _MD_unix_init_running_cpu(cpu); - cpu->md.id = getpid(); - _MD_SET_SPROC_PID(getpid()); - if (_pr_md_pipefd[0] >= 0) { - _PR_IOQ_MAX_OSFD(cpu) = _pr_md_pipefd[0]; -#ifndef _PR_USE_POLL - FD_SET(_pr_md_pipefd[0], &_PR_FD_READ_SET(cpu)); -#endif - } -} - -void -_MD_ExitThread(PRThread *thread) -{ - if (thread->flags & _PR_GLOBAL_SCOPE) { - _MD_ATOMIC_DECREMENT(&_pr_md_irix_sprocs); - _MD_CLEAN_THREAD(thread); - _MD_SET_CURRENT_THREAD(NULL); - } -} - -void -_MD_SuspendCPU(_PRCPU *cpu) -{ - PRInt32 rv; - - cpu->md.suspending_id = getpid(); - rv = kill(cpu->md.id, SIGUSR1); - PR_ASSERT(rv == 0); - /* - * now, block the current thread/cpu until woken up by the suspended - * thread from it's SIGUSR1 signal handler - */ - blockproc(getpid()); - -} - -void -_MD_ResumeCPU(_PRCPU *cpu) -{ - unblockproc(cpu->md.id); -} - -#if 0 -/* - * save the register context of a suspended sproc - */ -void get_context(PRThread *thr) -{ - int len, fd; - char pidstr[24]; - char path[24]; - - /* - * open the file corresponding to this process in procfs - */ - sprintf(path,"/proc/%s","00000"); - len = strlen(path); - sprintf(pidstr,"%d",thr->md.id); - len -= strlen(pidstr); - sprintf(path + len,"%s",pidstr); - fd = open(path,O_RDONLY); - if (fd >= 0) { - (void) ioctl(fd, PIOCGREG, thr->md.gregs); - close(fd); - } - return; -} -#endif /* 0 */ - -void -_MD_SuspendThread(PRThread *thread) -{ - PRInt32 rv; - - PR_ASSERT((thread->flags & _PR_GLOBAL_SCOPE) && - _PR_IS_GCABLE_THREAD(thread)); - - thread->md.suspending_id = getpid(); - rv = kill(thread->md.id, SIGUSR1); - PR_ASSERT(rv == 0); - /* - * now, block the current thread/cpu until woken up by the suspended - * thread from it's SIGUSR1 signal handler - */ - blockproc(getpid()); -} - -void -_MD_ResumeThread(PRThread *thread) -{ - PR_ASSERT((thread->flags & _PR_GLOBAL_SCOPE) && - _PR_IS_GCABLE_THREAD(thread)); - (void)unblockproc(thread->md.id); -} - -/* - * return the set of processors available for scheduling procs in the - * "mask" argument - */ -PRInt32 _MD_GetThreadAffinityMask(PRThread *unused, PRUint32 *mask) -{ - PRInt32 nprocs, rv; - struct pda_stat *pstat; -#define MAX_PROCESSORS 32 - - nprocs = sysmp(MP_NPROCS); - if (nprocs < 0) - return(-1); - pstat = (struct pda_stat*)PR_MALLOC(sizeof(struct pda_stat) * nprocs); - if (pstat == NULL) - return(-1); - rv = sysmp(MP_STAT, pstat); - if (rv < 0) { - PR_DELETE(pstat); - return(-1); - } - /* - * look at the first 32 cpus - */ - nprocs = (nprocs > MAX_PROCESSORS) ? MAX_PROCESSORS : nprocs; - *mask = 0; - while (nprocs) { - if ((pstat->p_flags & PDAF_ENABLED) && - !(pstat->p_flags & PDAF_ISOLATED)) { - *mask |= (1 << pstat->p_cpuid); - } - nprocs--; - pstat++; - } - return 0; -} - -static char *_thr_state[] = { - "UNBORN", - "RUNNABLE", - "RUNNING", - "LOCK_WAIT", - "COND_WAIT", - "JOIN_WAIT", - "IO_WAIT", - "SUSPENDED", - "DEAD" -}; - -void _PR_List_Threads() -{ - PRThread *thr; - void *handle; - struct _PRCPU *cpu; - PRCList *qp; - int len, fd; - char pidstr[24]; - char path[24]; - prpsinfo_t pinfo; - - - printf("\n%s %-s\n"," ","LOCAL Threads"); - printf("%s %-s\n"," ","----- -------"); - printf("%s %-14s %-10s %-12s %-3s %-10s %-10s %-12s\n\n"," ", - "Thread", "State", "Wait-Handle", - "Cpu","Stk-Base","Stk-Sz","SP"); - for (qp = _PR_ACTIVE_LOCAL_THREADQ().next; - qp != &_PR_ACTIVE_LOCAL_THREADQ(); qp = qp->next) { - thr = _PR_ACTIVE_THREAD_PTR(qp); - printf("%s 0x%-12x %-10s "," ",thr,_thr_state[thr->state]); - if (thr->state == _PR_LOCK_WAIT) - handle = thr->wait.lock; - else if (thr->state == _PR_COND_WAIT) - handle = thr->wait.cvar; - else - handle = NULL; - if (handle) - printf("0x%-10x ",handle); - else - printf("%-12s "," "); - printf("%-3d ",thr->cpu->id); - printf("0x%-8x ",thr->stack->stackBottom); - printf("0x%-8x ",thr->stack->stackSize); - printf("0x%-10x\n",thr->md.jb[JB_SP]); - } - - printf("\n%s %-s\n"," ","GLOBAL Threads"); - printf("%s %-s\n"," ","------ -------"); - printf("%s %-14s %-6s %-12s %-12s %-12s %-12s\n\n"," ","Thread", - "Pid","State","Wait-Handle", - "Stk-Base","Stk-Sz"); - - for (qp = _PR_ACTIVE_GLOBAL_THREADQ().next; - qp != &_PR_ACTIVE_GLOBAL_THREADQ(); qp = qp->next) { - thr = _PR_ACTIVE_THREAD_PTR(qp); - if (thr->cpu != NULL) - continue; /* it is a cpu thread */ - printf("%s 0x%-12x %-6d "," ",thr,thr->md.id); - /* - * check if the sproc is still running - * first call prctl(PR_GETSHMASK,pid) to check if - * the process is part of the share group (the pid - * could have been recycled by the OS) - */ - if (prctl(PR_GETSHMASK,thr->md.id) < 0) { - printf("%-12s\n","TERMINATED"); - continue; - } - /* - * Now, check if the sproc terminated and is in zombie - * state - */ - sprintf(path,"/proc/pinfo/%s","00000"); - len = strlen(path); - sprintf(pidstr,"%d",thr->md.id); - len -= strlen(pidstr); - sprintf(path + len,"%s",pidstr); - fd = open(path,O_RDONLY); - if (fd >= 0) { - if (ioctl(fd, PIOCPSINFO, &pinfo) < 0) - printf("%-12s ","TERMINATED"); - else if (pinfo.pr_zomb) - printf("%-12s ","TERMINATED"); - else - printf("%-12s ",_thr_state[thr->state]); - close(fd); - } else { - printf("%-12s ","TERMINATED"); - } - - if (thr->state == _PR_LOCK_WAIT) - handle = thr->wait.lock; - else if (thr->state == _PR_COND_WAIT) - handle = thr->wait.cvar; - else - handle = NULL; - if (handle) - printf("%-12x ",handle); - else - printf("%-12s "," "); - printf("0x%-10x ",thr->stack->stackBottom); - printf("0x%-10x\n",thr->stack->stackSize); - } - - printf("\n%s %-s\n"," ","CPUs"); - printf("%s %-s\n"," ","----"); - printf("%s %-14s %-6s %-12s \n\n"," ","Id","Pid","State"); - - - for (qp = _PR_CPUQ().next; qp != &_PR_CPUQ(); qp = qp->next) { - cpu = _PR_CPU_PTR(qp); - printf("%s %-14d %-6d "," ",cpu->id,cpu->md.id); - /* - * check if the sproc is still running - * first call prctl(PR_GETSHMASK,pid) to check if - * the process is part of the share group (the pid - * could have been recycled by the OS) - */ - if (prctl(PR_GETSHMASK,cpu->md.id) < 0) { - printf("%-12s\n","TERMINATED"); - continue; - } - /* - * Now, check if the sproc terminated and is in zombie - * state - */ - sprintf(path,"/proc/pinfo/%s","00000"); - len = strlen(path); - sprintf(pidstr,"%d",cpu->md.id); - len -= strlen(pidstr); - sprintf(path + len,"%s",pidstr); - fd = open(path,O_RDONLY); - if (fd >= 0) { - if (ioctl(fd, PIOCPSINFO, &pinfo) < 0) - printf("%-12s\n","TERMINATED"); - else if (pinfo.pr_zomb) - printf("%-12s\n","TERMINATED"); - else - printf("%-12s\n","RUNNING"); - close(fd); - } else { - printf("%-12s\n","TERMINATED"); - } - - } - fflush(stdout); -} -#endif /* defined(_PR_PTHREADS) */ - -PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) -{ -#if !defined(_PR_PTHREADS) - if (isCurrent) { - (void) setjmp(t->md.jb); - } - *np = sizeof(t->md.jb) / sizeof(PRWord); - return (PRWord *) (t->md.jb); -#else - *np = 0; - return NULL; -#endif -} - -void _MD_EarlyInit(void) -{ -#if !defined(_PR_PTHREADS) - char *eval; - int fd; - extern int __ateachexit(void (*func)(void)); - - sigemptyset(&ints_off); - sigaddset(&ints_off, SIGALRM); - sigaddset(&ints_off, SIGIO); - sigaddset(&ints_off, SIGCLD); - - if (eval = getenv("_NSPR_TERMINATE_ON_ERROR")) - _nspr_terminate_on_error = (0 == atoi(eval) == 0) ? PR_FALSE : PR_TRUE; - - fd = open("/dev/zero",O_RDWR , 0); - if (fd < 0) { - perror("open /dev/zero failed"); - exit(1); - } - /* - * Set up the sproc private data area. - * This region exists at the same address, _nspr_sproc_private, for - * every sproc, but each sproc gets a private copy of the region. - */ - _nspr_sproc_private = (char*)mmap(0, _pr_pageSize, PROT_READ | PROT_WRITE, - MAP_PRIVATE| MAP_LOCAL, fd, 0); - if (_nspr_sproc_private == (void*)-1) { - perror("mmap /dev/zero failed"); - exit(1); - } - _MD_SET_SPROC_PID(getpid()); - close(fd); - __ateachexit(irix_detach_sproc); -#endif - _MD_IrixIntervalInit(); -} /* _MD_EarlyInit */ - -void _MD_IrixInit(void) -{ -#if !defined(_PR_PTHREADS) - struct sigaction sigact; - PRThread *me = _PR_MD_CURRENT_THREAD(); - int rv; - -#ifdef _PR_HAVE_SGI_PRDA_PROCMASK - /* - * enable user-level processing of sigprocmask(); this is an undocumented - * feature available in Irix 6.2, 6.3, 6.4 and 6.5 - */ - __sgi_prda_procmask(USER_LEVEL); -#endif - - /* - * set up SIGUSR1 handler; this is used to save state - * during PR_SuspendAll - */ - sigact.sa_handler = save_context_and_block; - sigact.sa_flags = SA_RESTART; - sigact.sa_mask = ints_off; - sigaction(SIGUSR1, &sigact, 0); - - /* - * Change the name of the core file from core to core.pid, - * This is inherited by the sprocs created by this process - */ -#ifdef PR_COREPID - prctl(PR_COREPID, 0, 1); -#endif - /* - * Irix-specific terminate on error processing - */ - /* - * PR_SETABORTSIG is a new command implemented in a patch to - * Irix 6.2, 6.3 and 6.4. This causes a signal to be sent to all - * sprocs in the process when one of them terminates abnormally - * - */ - if (prctl(PR_SETABORTSIG, SIGKILL) < 0) { - /* - * if (errno == EINVAL) - * - * PR_SETABORTSIG not supported under this OS. - * You may want to get a recent kernel rollup patch that - * supports this feature. - * - */ - } - /* - * PR_SETEXITSIG - send the SIGCLD signal to the parent - * sproc when any sproc terminates - * - * This is used to cause the entire application to - * terminate when any sproc terminates abnormally by - * receipt of a SIGSEGV, SIGBUS or SIGABRT signal. - * If this is not done, the application may seem - * "hung" to the user because the other sprocs may be - * waiting for resources held by the - * abnormally-terminating sproc. - */ - prctl(PR_SETEXITSIG, 0); - - sigact.sa_handler = sigchld_handler; - sigact.sa_flags = SA_RESTART; - sigact.sa_mask = ints_off; - sigaction(SIGCLD, &sigact, NULL); - - /* - * setup stack fields for the primordial thread - */ - me->stack->stackSize = prctl(PR_GETSTACKSIZE); - me->stack->stackBottom = me->stack->stackTop - me->stack->stackSize; - - rv = pipe(_pr_irix_primoridal_cpu_fd); - PR_ASSERT(rv == 0); -#ifndef _PR_USE_POLL - _PR_IOQ_MAX_OSFD(me->cpu) = _pr_irix_primoridal_cpu_fd[0]; - FD_SET(_pr_irix_primoridal_cpu_fd[0], &_PR_FD_READ_SET(me->cpu)); -#endif - - libc_handle = dlopen("libc.so",RTLD_NOW); - PR_ASSERT(libc_handle != NULL); - libc_exit = (void (*)(int)) dlsym(libc_handle, "exit"); - PR_ASSERT(libc_exit != NULL); - /* dlclose(libc_handle); */ - -#endif /* _PR_PTHREADS */ - - _PR_UnixInit(); -} - -/**************************************************************************/ -/************** code and such for NSPR 2.0's interval times ***************/ -/**************************************************************************/ - -#define PR_PSEC_PER_SEC 1000000000000ULL /* 10^12 */ - -#ifndef SGI_CYCLECNTR_SIZE -#define SGI_CYCLECNTR_SIZE 165 /* Size user needs to use to read CC */ -#endif - -static PRIntn mmem_fd = -1; -static PRIntn clock_width = 0; -static void *iotimer_addr = NULL; -static PRUint32 pr_clock_mask = 0; -static PRUint32 pr_clock_shift = 0; -static PRIntervalTime pr_ticks = 0; -static PRUint32 pr_clock_granularity = 1; -static PRUint32 pr_previous = 0, pr_residual = 0; -static PRUint32 pr_ticks_per_second = 0; - -extern PRIntervalTime _PR_UNIX_GetInterval(void); -extern PRIntervalTime _PR_UNIX_TicksPerSecond(void); - -static void _MD_IrixIntervalInit(void) -{ - /* - * As much as I would like, the service available through this - * interface on R3000's (aka, IP12) just isn't going to make it. - * The register is only 24 bits wide, and rolls over at a verocious - * rate. - */ - PRUint32 one_tick = 0; - struct utsname utsinfo; - uname(&utsinfo); - if ((strncmp("IP12", utsinfo.machine, 4) != 0) - && ((mmem_fd = open("/dev/mmem", O_RDONLY)) != -1)) - { - int poffmask = getpagesize() - 1; - __psunsigned_t phys_addr, raddr, cycleval; - - phys_addr = syssgi(SGI_QUERY_CYCLECNTR, &cycleval); - raddr = phys_addr & ~poffmask; - iotimer_addr = mmap( - 0, poffmask, PROT_READ, MAP_PRIVATE, mmem_fd, (__psint_t)raddr); - - clock_width = syssgi(SGI_CYCLECNTR_SIZE); - if (clock_width < 0) - { - /* - * We must be executing on a 6.0 or earlier system, since the - * SGI_CYCLECNTR_SIZE call is not supported. - * - * The only pre-6.1 platforms with 64-bit counters are - * IP19 and IP21 (Challenge, PowerChallenge, Onyx). - */ - if (!strncmp(utsinfo.machine, "IP19", 4) || - !strncmp(utsinfo.machine, "IP21", 4)) - clock_width = 64; - else - clock_width = 32; - } - - /* - * 'cycleval' is picoseconds / increment of the counter. - * I'm pushing for a tick to be 100 microseconds, 10^(-4). - * That leaves 10^(-8) left over, or 10^8 / cycleval. - * Did I do that right? - */ - - one_tick = 100000000UL / cycleval ; /* 100 microseconds */ - - while (0 != one_tick) - { - pr_clock_shift += 1; - one_tick = one_tick >> 1; - pr_clock_granularity = pr_clock_granularity << 1; - } - pr_clock_mask = pr_clock_granularity - 1; /* to make a mask out of it */ - pr_ticks_per_second = PR_PSEC_PER_SEC - / ((PRUint64)pr_clock_granularity * (PRUint64)cycleval); - - iotimer_addr = (void*) - ((__psunsigned_t)iotimer_addr + (phys_addr & poffmask)); - } - else - { - pr_ticks_per_second = _PR_UNIX_TicksPerSecond(); - } -} /* _MD_IrixIntervalInit */ - -PRIntervalTime _MD_IrixIntervalPerSec(void) -{ - return pr_ticks_per_second; -} - -PRIntervalTime _MD_IrixGetInterval(void) -{ - if (mmem_fd != -1) - { - if (64 == clock_width) - { - PRUint64 temp = *(PRUint64*)iotimer_addr; - pr_ticks = (PRIntervalTime)(temp >> pr_clock_shift); - } - else - { - PRIntervalTime ticks = pr_ticks; - PRUint32 now = *(PRUint32*)iotimer_addr, temp; - PRUint32 residual = pr_residual, previous = pr_previous; - - temp = now - previous + residual; - residual = temp & pr_clock_mask; - ticks += temp >> pr_clock_shift; - - pr_previous = now; - pr_residual = residual; - pr_ticks = ticks; - } - } - else - { - /* - * No fast access. Use the time of day clock. This isn't the - * right answer since this clock can get set back, tick at odd - * rates, and it's expensive to acqurie. - */ - pr_ticks = _PR_UNIX_GetInterval(); - } - return pr_ticks; -} /* _MD_IrixGetInterval */ - |