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

📄 machdep.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
字号:
/* Copyright (C) 1987 Sun Microsystems Inc. *//* * This source code is a product of Sun Microsystems, Inc. and is provided * for unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part.  Users * may copy or modify this source code without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * THIS PROGRAM CONTAINS SOURCE CODE COPYRIGHTED BY SUN MICROSYSTEMS, INC. * AND IS LICENSED TO SUNSOFT, INC., A SUBSIDIARY OF SUN MICROSYSTEMS, INC. * SUN MICROSYSTEMS, INC., MAKES NO REPRESENTATIONS ABOUT THE SUITABLITY * OF SUCH SOURCE CODE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT * EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  SUN MICROSYSTEMS, INC. DISCLAIMS * ALL WARRANTIES WITH REGARD TO SUCH SOURCE CODE, INCLUDING ALL IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN * NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM USE OF SUCH SOURCE CODE, REGARDLESS OF THE THEORY OF LIABILITY. *  * This source code is provided with no support and without any obligation on * the part of Sun Microsystems, Inc. to assist in its use, correction,  * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS * SOURCE CODE OR ANY PART THEREOF. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */#include "common.h"#include "queue.h"#include "asynch.h"#include "machsig.h"#include "machdep.h"#include "cntxt.h"#include "lwperror.h"#include "message.h"#include "process.h"#include "schedule.h"#include "agent.h"#include "alloc.h"#include "monitor.h"#include <signal.h>#include "libc/libc.h"#include <sun4/psl.h>#include <sun4/asm_linkage.h>#ifndef lintSCCSID(@(#) machdep.c 1.1 92/07/30 Copyr 1987 Sun Micro);#endif lintint __AllFlushed;	/* TRUE if windows currently flushed *//* * PRIMITIVES contained herein: * lwp_setregs(tid, machstate) * lwp_getregs(tid, machstate) *//* * lwp_setregs -- PRIMITIVE. * Set the context (registers) for a given thread. * Can be used to simulate longjmp-like effects. */intlwp_setregs(tid, machstate)	thread_t tid;	register machstate_t *machstate;{	register lwp_t *pid = (lwp_t *)(tid.thread_id);	CLR_ERROR();	LOCK();	ERROR((pid->lwp_lock != tid.thread_key), LE_NONEXIST);	bcopy((caddr_t)machstate, (caddr_t)&(pid->lwp_machstate),	   sizeof(machstate_t));	pid->lwp_full = TRUE;	/* allow psr, etc. to be loaded too */	UNLOCK();	return (0);}/* * lwp_getregs -- PRIMITIVE. * Get the context (registers) for a given thread. */intlwp_getregs(tid, machstate)	thread_t tid;	register machstate_t *machstate;{	register lwp_t *pid = (lwp_t *)(tid.thread_id);	CLR_ERROR();	LOCK();	ERROR((pid->lwp_lock != tid.thread_key), LE_NONEXIST);	bcopy((caddr_t)&(pid->lwp_machstate), (caddr_t)machstate,	   sizeof(machstate_t));	if (!pid->lwp_full) {	/* where he will be at next swtch() */		machstate->sparc_pc += 8;		machstate->sparc_npc += 8 + 4;	}	UNLOCK();	return (0);}stkalign_t __IdleStack[IDLESTACK];	/* stack for idle thread */stkalign_t *__NuggetSP;		/* nugget stack (when no lwps are running) *//* * The routines here, in except.c, in machsig.c, in cntxt.c, * and those in low.s are machine-dependent parts that need to be changed * when porting to a different environment. * alloc.[ch] may also require modification, especially when paged * memory is needed. *//* * lightweight process to wait for interrupts. */void__idle() {	int i;	LWPTRACE(tr_SCHEDULE, 2, ("idle\n"));	for (;;) {		LWPTRACE(tr_SCHEDULE, 6, ("."));		/*		 * Test for termination. Any lwp's created by		 * the client have had a chance to run before we get		 * here (idle runs at a priority lower than tha		 * client can run). If idle() is the only guy left, there		 * is no hope of a signal coming in as all agents have		 * been destroyed. 		 */		if (__LwpRunCnt == __NActiveSlaves + 1) {/* only slaves, idle */			break;		} else {			/* analogous to PDP-11 WAIT or 68000 STOP instruction */			(void) sigpause(0);	/* avoid chewing up cycles */		}	}	for (i = 0; i < __SlaveThreads; i++) {		if (!SAMETHREAD(__Slaves[i], THREADNULL))			(void)lwp_destroy(__Slaves[i]);	}	__do_exithand();}/* * Upon a caught UNIX signal, __interrupt() is invoked (on the interrupt stack). * Unix takes care of flushing the windows for us. * This routine saves %g's and %o's (since flushing the latter * would save them on the (reused) interrupt stack). * It then invokes __real_sig with interrupts disabled * (signals are set up to not nest. The event list is only accessed * at highest priority). * If LOCKED, __interrupt restores state and returns. * XXX There is room for tuning here since low.s copies things * that real_sig copies as well. */void__real_sig(signum, code, cntxt, addr, regs, yreg)	int signum;	int code;	register struct sigcontext *cntxt;	caddr_t addr;	int *regs;	/* g2-7, o0-7 */	long yreg;	/* %y */{	register lwp_t *cp = __Curproc;	if (__Eventinfo[signum].int_start == TRAPEVENT) { /* synchronous trap */		*(--(int *)cntxt->sc_sp) = cntxt->sc_pc;		*(--(int *)cntxt->sc_sp) = signum;		cntxt->sc_pc = (int)__sigtrap;		cntxt->sc_npc = cntxt->sc_pc + 4;		return;	}	/*	 * indicate that interrupts are masked. No need to DISABLE	 * since interrupts don't nest and we're already at interrupt	 * prio.	 */	__SigLocked++;	if (IS_LOCKED()) {	/* in a critical section */		/*		 * Just save signal info and return.  Since we were in		 * a critical section when the interrupt arrived,		 * __save_event() must be careful to avoid using shared		 * memory structures.  __EventsPending remains TRUE since		 * we haven't completely processed the signal yet.		 */		__save_event(__Curproc, signum, code, addr);		LWPTRACE(tr_ASYNCH, 1, ("CRITICAL SECTION LOCKED\n"));		__SigLocked = 0;	} else { /* not in a critical section */		LOCK();	/* Now in critical section; so LOCK-UNLOCK work ok */		cp->lwp_full = TRUE;		{			register int i;			register int *r = regs;			/* 			 * save all context. UNIX saved %o0, %o6, pc and %g1.			 */			for (i = 0; i < 6; i++)				cp->mch_xglobals[i+2] = *r++;			for (i = 0; i < 8; i++)				cp->mch_xoregs[i] = *r++;		}					/* save signal state (volatile device registers) */		cp->mch_y = yreg;		cp->mch_sp = cntxt->sc_sp;		cp->mch_pc = cntxt->sc_pc;		cp->mch_npc = cntxt->sc_npc;		cp->mch_g1 = cntxt->sc_g1;		cp->mch_o0 = cntxt->sc_o0;		cp->mch_psr = cntxt->sc_psr;		__save_event(cp, signum, code, addr);		LWPTRACE(tr_ASYNCH, 1, ("realsig %d saved full context\n", signum));		__do_agent();	}}/* Hold info to pass to system via sigcleanup() on rti() */struct sigcontext __Context;/* * Full context switch to __Curproc. We use full_swtch whenever * context switching as a result of an interrupt (to return * to pre-interrupt priority), or switching to a process that * was scheduled out as a result of an asynchronous event. * In the former case, if the process was not previously scheduled * out as a result of an interrupt, we dummy up a full context * for sigcleanup. * Always called while LOCKED (once a context is selected by the scheduler, * don't want to trash its state by taking an interrupt before DISABLING). * Restore the volatile and nonvolatile registers saved * in __Curproc's context. * This routine also has the job of restoring interrupt priority, * signal mask and signal stack to the pre-interrupt state. * This is done (atomically) by sigcleanup. */void__full_swtch(){	register struct sigcontext *cntxt = &__Context;	register lwp_t *cp = __Curproc;	DISABLE();	/* in case we were not called at interrupt level */	/*	 * If schedule() was interrupted, for example, __EventsPending	 * can be TRUE when schedule() calls full_swtch().	 * do_agent will enter the scheduler with interrupts disabled	 * so there is no possible recursion here.	 */	if (__EventsPending) {		__do_agent();	}	/*	 * remove __SigLocked and __AsynchLock to achieve the state that	 * we will safely have when sigcleanup returns.	 * Since we return to unlocked state, we must zero rather	 * than decrement.	 */	LOCK_OFF();	cntxt->sc_onstack = FALSE;	cntxt->sc_mask = 0;  /* permit all interrupts */	cntxt->sc_sp = cp->mch_sp;	if (!cp->lwp_full) {		/*		 * We won't do a normal CSWTCH because we need to escape		 * high prio via rti.		 * Dummy up a sigcontext and let rti() return		 * us to where we were at the coroutine call.		 */		cntxt->sc_pc = cp->mch_pc + 8;		cntxt->sc_psr = PSL_USER;		  /* from coroutine call, add 8 to pc to simulate ret */		cntxt->sc_npc = cp->mch_pc + 8 + 4;	} else {		cp->lwp_full = FALSE;		cntxt->sc_pc = cp->mch_pc;		cntxt->sc_npc = cp->mch_npc;		cntxt->sc_g1 = cp->mch_g1;		cntxt->sc_o0 = cp->mch_o0;		cntxt->sc_psr = cp->mch_psr;	}	LWPTRACE(tr_ASYNCH, 2, ("FULL SWTCH: ABOUT TO RETURN TO %x, <pc %x sp %x>\n",	  cp, cntxt->sc_pc, cntxt->sc_sp));	__rti();	__panic("return from sigcleanup");}STATIC stkalign_t Sigstk[INTSTKSZ];	/* stack for handling interrupts *//* Signal stack */STATIC struct sigstack Sss = {	/* stack to use for signals. Leave WINDOWSIZE in case need to flush. */	(caddr_t)STACKTOP(Sigstk, INTSTKSZ - (WINDOWSIZE / sizeof(int))),	FALSE, /* not currently using it */};/* * Create a stack for the nugget to use. This should not come from * paged memory. Allow a frame on this stack just in case. * Create a stack for interrupts to operate on. */void__init_machdep(){	__AllFlushed = FALSE;	__NuggetSP = (stkalign_t *)	  (STACKALIGN	  (((int)MEM_ALLOC(NUGSTACKSIZE)) + NUGSTACKSIZE - MINFRAME));	if (sigstack(&Sss, (struct sigstack *)0) < 0) {		perror("__init_machdep");		__panic("sigstack call failed");	}}

⌨️ 快捷键说明

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