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

📄 signal.c

📁 用于motorala 68K系列处理器的小实时多任务操作系统 The OMU Kernel was written to provide a cut-down Unix-like O/S for a
💻 C
字号:
/****************************************************************************** *	Signal.c	All signal related stuff ****************************************************************************** * *	The signal table is held in the process table and is an array *	of function addresses. *	If 0 then the default signal is caried out (termination sometimes *	with core). *	If bit 0 is 1 then the signal is ignored *	Else the apropriate function is called *	Note signals available are 1 - 31 ( 0 is not used ) * *	Note the tty handler will set the process controlling tty number *	on the open of a tty into file channel 0. *	This is used to direct process group signals such as SIGQUIT to *	all processes using this tty as control. *	Note all processes without a controling tty have the console *	(tty 0) given to them. * *	Note generaly a signal is only flaged not immediatly executed *	Execution will be done by checkmev() at certain places in the *	kernal (after wrapper() tick() and after any interupt routine that *	could cause a signal). *	Note because of the "C" signal call library operation, which *	maintains an internal jump table for the caught signals, *	a signal should not be acted upon during a kernel "signal" *	system call, else the internal jump table and the kernels *	table will not be the same, with dire consequences. *	It should only return an error if comeing out of a sleep *	to process the signal realy. * *	Calluser()	Calls a user function caught via a signal * *	This bit is extremely and uterly horible, because it is legit *	to long jump from a caught signal to another user function. *	What this bit does is to copy the state of the processor as *	saved in u_regs on the system stack, onto the user stack so *	that the long jump bit can get rid of it if so required. *	The system stack is set back to the previous state and a call *	is made to the user function. If this call returns (no long jump) *	then the state on the user stack will be retrieved and the system *	will return to the system call in progress when *	the signal was caught. Puke! *	Note an error should be flaged useing error() if the process was *	woken up to process the signal * *	Special bits OMU: Note 4 arguments can be passed to the returning *	signal call, by default the first argument is the signal number, *	the following arguments are speciphic to the signal. *	These are used specificaly for the SIGEVFILE, and SIGEVCOMMS signals. *	Note with the SIGEVFILE signal there is a race hazard, such that if a *	signal is pending and another one arives then the later one is ignored. *	If SIGEVCOMMS is used via the coms() syscall then a -1 will be returned *	If the process has still to acknowledge the last coms. * */ # include	"../include/param.h"# include	"../include/inode.h"# include	"../include/signal.h"# include	"../include/procs.h"# include	"../include/state.h"# include	<errno.h>extern	char	swtchflag;/* *	Sigmode()	Sets mode of signal operation */sigmode(smode)int	smode;{	int	osmode;	osmode = cur_proc->sigmode;	cur_proc->sigmode = smode;	return osmode;}/* *	Sigmask()	Masks selected signals */sigmask(smask)unsigned long	smask;{	unsigned long	osmask;	osmask = cur_proc->sigmask;	smask &= ~(1 << SIGKILL);	/* Does not mask kill signal */	cur_proc->sigmask = smask;	return osmask;}/* *	Checkev()	Checks if any event has occured if so do event *			Note processor registers d0 and d1 are used *			thus if calling before or after wrapper these *			need to be saved before calling. *			Mode indicates which events are to be checked *			EVSWTCH		Process switching allowed *			EVSIGQUIT	Quit signals *			EVSIGUSER	User caught signals *			Note this rotine will check all the events *			even if the software mask smask is masking *			action on these events. Call checkmev() for *			normal event checkeing. *			Returns 0 normaly, or the signal number if a *			signal was processed. */checkev(mode)int	mode;{	int	err;	/* Check and act upon any signals for this process */	err = psig(mode);	/* If process switch required do this bit */	if(mode & EVSWTCH){		/* Checks if process switch is required and allowed */		if(swtchflag) pswitch(-1);	}	return err;}/* *	Checkmev()	Check events which are not masked off by the software *			process mask smask. */checkmev(){	int	mode;	/* Gets in mode bit mask of all posible events to be checked */	mode = ~cur_proc->smask & EVALL;	return checkev(mode);}/* *	Signal()	Sets up signal function call addresses (system call) */int (*signal(sig,func))()int sig;int (*func)();{	int (*oldsig)();	/* Checks if signal is valid if so sets it */	if((sig < 1) || (sig >= NSIG)) return (int (*)())error(BADSIG);	if(sig == SIGKILL) return (int (*)())error(BADSIG);	oldsig = cur_proc->signals[sig].func;	/* Checks if function address is legit ie within user text area	 * unless default or ignore signal address.	 */	if((func != SIG_DFL) && (func != SIG_IGN)){		if((cur_proc->psize.entry > (long)func) ||			((cur_proc->psize.entry + cur_proc->psize.tsize) < (long)func))			return (int (*)())error(BADSIG);	}	cur_proc->signals[sig].func = func;	return oldsig;}/* *	Alarm()		Alarm system call, Sets up alarm time. */alarm(seconds)long seconds;{	long sec;	/* Save old value for return and set new value */	sec = cur_proc->alarm;	cur_proc->alarm = seconds;	return sec;}/* *	Sendgrp()	Sends a signal to all processes with tty as *			controlling terminal. Except process 0 (ie Kernel) *			If flag "dosig" is not 0  then actualy do the signal. */sendgrp(tty, sig, dosig)int tty;int sig;char dosig;{	struct procs *proc;	short pid;	/* Work through process table sending signals to apropriate	 * processes note signals are acted upon later.	 */	proc = &proc_table[1];	for(pid = 1; pid < NPROC; pid++){		/* If a process entry exists and is corect tty then set signal*/		if(((proc->stat == SRUN) || (proc->stat == SSLEEP)) &&			(proc->tty == tty)){			proc->sig |= 1<<(sig);			proc->pri = PSIGNAL;			proc->stat = SRUN;			/* Indicate Process switch is required			 */			swtchflag = 1;			if(dosig) pswitch(proc->pid); /* Do signal if required */		}		proc++;	}}/* *	Sendsig()	Send a signal to a particular process *			If dosig is not 0 then actualy do the signal;  */sendsig(pid,sig,dosig)short pid;long sig;char dosig;{	struct procs *proc;	if(pid == 0) return;	proc = &proc_table[pid];	/* If process id given send signal to that one only */	if((proc->stat == SRUN) || (proc->stat == SSLEEP)){		proc->sig |= 1<<(sig);		proc->pri = PSIGNAL;		proc->stat = SRUN;		/* Indicate Process switch is required		 */		swtchflag = 1;		if(dosig){			/* If proccess is in core and locked, do signal */			if((proc->flag & SLOAD) && (proc->flag & (SLOCK|SULOCK)))			pswitch(pid);		}	}}/* *	Anysig()	Checks to see if any process has a signal pending *			returns process number if found -1 if not */anysig(){	struct procs *proc;	short pid;	/* Workthrough process table checking on signals	 */	proc = &proc_table[1];	for(pid = 1; pid < NPROC; pid++){		/* If a process entry exists and has signal return */		if(((proc->stat == SRUN) || (proc->stat == SSLEEP))){			if(issig(proc)) return pid;		}		proc++;	}	return -1;}/* *	Issig()		Checks if signal pending if so returns number *			Ignores ignored signals */issig(proc)struct procs *proc;{	int n;	/* Check all signals recieved ignore defered ones */	while(proc->sig){		if(!(n = fsig(proc))) return 0;		if(!SIGISDEFER(proc->signals[n].func)) return n;		else proc->sig &= ~(1<<(n));	}	return 0;}/* *	Istermsig()	Checks if signal pending and is a default signal *			and not masked, if so returns number, *			ignores ignored signals. */istermsig(proc)struct procs *proc;{	unsigned long i,n;	/* Check for default signals recieved ignore defered ones and masked	 * ones	 */	n = 1;	for(i = 0; i < NSIG; i++){		if((proc->sig & n) && (!(proc->sigmask & n))){			if(SIG_DFL == proc->signals[i].func) return i;			if(SIGISDEFER(proc->signals[i].func)) proc->sig &= ~n;		}		n <<= 1;	}	return 0;}/* *	Fsig()		Find signal number pending 1 - 31 (0 is no signal) *			Ignores Masked signals. */fsig(proc)struct procs *proc;{	unsigned long i,n;	n = 1;	for(i = 0; i < NSIG; i++){		if((proc->sig & n) && (!(proc->sigmask & n))) return i;		n <<= 1;	}	return 0;}/* *	Psig()		Process signal perform action as required *			Called when curent process is in core only *			Normally at the beginning and end of system calls *			If mode is EVSIGUSER will check all signals *			If mode is EVSIGQUIT will only check quit signals *			If process is not in core and pisg() is called, *			psig() will return and process the signal *			at a later time when the process is in core. *			Returns 0 normaly, or the signal number if a user *			caught signal was processed. *			Psig() only processes signals that are not masked *			by the process table entry sigmask. *			If the signal mode for the current process is *			set to SIGMODEOMU, then when a user caught signal *			is processed all signals are masked. *			If the caught signal returns then the signal mask *			is set back to the original value, else the *			user should reset it by means of the sigmask() *			system call. *			Signals are NOT set back to default condition *			when in SIGMODEOMU. */psig(mode)int	mode;{# define	SIGTNONE	0	/* No action */# define	SIGTQUIT	1	/* Signal causes a process exit */# define	SIGTCORE	2	/* Signal causes core and exit */# define	SIGTUSER	3	/* Signal calls a user function */	int	sig, e, a1, a2, a3;	int	(*func)();	char	type;	short	smask, imask;	unsigned long	ssigmask;	sig = 0;	/* Check if signal exists given the mode */	if(mode & EVSIGUSER){		sig = issig(cur_proc);	}	else if(mode & EVSIGQUIT){		sig = istermsig(cur_proc);	}	/* If no valid signal return */	if(!sig) return 0;	/* If signal is masked ignore for now NORE: checked in issig aswell */	if(cur_proc->sigmask & (1<<sig)) return 0;	/* If process is not in core don't do signals, wait until	 * The process is pulled back into core	 */	if(!(cur_proc->flag & SLOAD)) return 0;	/* Disables process switch and No interupts */	smask = smaskon(cur_proc, EVALL);	imask = spl6();	type = SIGTNONE;	a1 = a2 = a3 = 0;	/* Awake process */	cur_proc->stat = SRUN;	cur_proc->sig &= ~(1<<(sig));		/* Acknowledge signal */	func = cur_proc->signals[sig].func;	switch(sig){		/* Signals producing core and that are reset when caught */		case SIGQUIT:		case SIGIOT:		case SIGEMT:		case SIGFPE:		case SIGBUS:		case SIGSEGV:		case SIGSYS:			/* Sets back to default if not SIGMODEOMU */			if(cur_proc->sigmode != SIGMODEOMU){				cur_proc->signals[sig].func = SIG_DFL;			}			/* If signal caught then jump to function */			if(func) type = SIGTUSER;			else type = SIGTCORE;			break;		/* Signals producing core but that are NOT reset when caught */		case SIGILL:		case SIGTRAP:			/* If signal caught then jump to function */			if(func) type = SIGTUSER;			else type = SIGTCORE;			break;		/* Special kill process */		case SIGKILL:			type = SIGTCORE;			break;		case SIGEVFILE:			/* Call process with appropriate args no process quit */			/* Calculates next file pending */			for(e = 0; e < 32; e++)				if(cur_proc->evfile & (1<<e)) break;			a1 = e;			/* Clears event bits to acknowledge event call */			cur_proc->evfile &= ~(1<<e);			/* Sets back to default if not SIGMODEOMU */			if(cur_proc->sigmode != SIGMODEOMU){				cur_proc->signals[sig].func = SIG_DFL;			}			/* If file events are still pending renable signal */			if(cur_proc->evfile) cur_proc->sig |= (1<<SIGEVFILE);			if(func) type = SIGTUSER;			break;		case SIGEVCOMMS:			/* Call process with appropriate args no quit */			a1 = cur_proc->evcoma[0];			a2 = cur_proc->evcoma[1];			a3 = cur_proc->evcoma[2];			/* Clears event bits to acknowledge event call */			cur_proc->evcom = 0;#ifdef TEVENTprintf("COMMS CALLING USER FUNC\n");#endif			/* Sets back to default if not SIGMODEOMU */			if(cur_proc->sigmode != SIGMODEOMU){				cur_proc->signals[sig].func = SIG_DFL;			}			if(func) type = SIGTUSER;#ifdef TEVENTprintf("COMMS RETURNED USER FUNC\n");#endif			break;		default:			/* Sets back to default if not SIGMODEOMU */			if(cur_proc->sigmode != SIGMODEOMU){				cur_proc->signals[sig].func = SIG_DFL;			}			/* If signal caught then jump to function */			if(func) type = SIGTUSER;			else type = SIGTQUIT;	}	/* Renable interupts and process switch as decision has been made */	splx(imask);	smaskoff(cur_proc, smask);	/* Do appropriate action */	switch(type){	case SIGTCORE:		core();		kexit(sig);		break;	case SIGTQUIT:		kexit(sig);		break;	case SIGTUSER:		/* If process is awaiting an event ignore it. */		cur_proc->wchan = 0;		/* If special signal mode mask this signals during user		 * signal processing and return to normal at end.		 */		if(cur_proc->sigmode == SIGMODEOMU){			ssigmask = cur_proc->sigmask;#ifdef	MASKALL			/* Mask all signals except kill signal */			cur_proc->sigmask = MASKALLSIG & ~(1 << SIGKILL);#else			/* This signal */			cur_proc->sigmask |= (1 << sig);#endif		}		calluser(func, sig, a1, a2, a3);		if(cur_proc->sigmode == SIGMODEOMU) cur_proc->sigmask = ssigmask;		break;	}	return sig;}/* *	Core()		Does absolutely nothing! */core(){}

⌨️ 快捷键说明

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