⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 irix.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//*  * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape Portable Runtime (NSPR). *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1998-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. */#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 voidsigchld_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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -