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

📄 ndet_loop.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef	lint#ifdef sccsstatic	char sccsid[] = "@(#)ndet_loop.c 1.1 92/07/30 Copyr 1985 Sun Micro";#endif#endif/* * Copyright (c) 1985 by Sun Microsystems, Inc. *//* * Ndet_loop.c - Notification loop. */#include <sunwindow/ntfy.h>#include <sunwindow/ndet.h>#include <sunwindow/nint.h>#include <sunwindow/ndis.h>		/* For ndis_dispatch */#include <syscall.h>#include <errno.h>#include <signal.h>#include <stdio.h>		/* For temp debugging */extern	int errno;pkg_private_data u_int	ndet_flags = 0;pkg_private_data NTFY_CLIENT *ndet_clients = 0;pkg_private_data NTFY_CLIENT *ndet_client_latest = 0;pkg_private_data u_int	ndet_sigs_received = 0;pkg_private_data u_int	ndet_sigs_managing = 0;pkg_private_data fd_set	ndet_fasync_mask = 0;  /* Initialized to 0 by the compiler*/pkg_private_data fd_set	ndet_fndelay_mask = 0; /* Maintained, but really used? */pkg_private_data struct	timeval ndet_polling_tv = {0,0};pkg_private_data fd_set	ndet_ibits = 0, ndet_obits = 0, ndet_ebits = 0; /* = 0;  */static	struct timeval ndet_signal_check;	/* Minimum select timeout */pkg_private_data struct sigvec ndet_prev_sigvec[NSIG] = 0;pkg_private void ndet_signal_catcher();pkg_private_data struct sigvec ndet_sigvec = {ndet_signal_catcher, 0, 0};static	int	ndet_signal_code;static	struct	sigcontext *ndet_signal_context;static	void ndet_update_itimer();static	void ndet_send_async_sigs();static	void ndet_fig_fd_change(), ndet_fig_wait3_change(),	    ndet_fig_destroy_change(), ndet_fig_sig_change();static	NTFY_ENUM ndet_sig_send(), ndet_poll_send();static	NTFY_ENUM ndet_itimer_change();static	NTFY_ENUM ndet_destroy_change();static	NTFY_ENUM ndet_sig_change();static	NTFY_ENUM ndet_fd_change();static	NTFY_ENUM ndet_wait3_change();static	NTFY_ENUM ndet_virtual_set_tv_update();static	NTFY_ENUM ndet_async_sig_send();#ifdef	lint/* VARARGS *//* ARGSUSED */int	syscall(a) { return(0);} /* When syscall put in llib-lc then remove */#endif	lintextern Notify_errornotify_start(){	register struct	timeval *timer;	fd_set	ibits, obits, ebits;	register int	nfds;	NDET_ENUM_SEND	enum_send;	int errno_remember = errno;	Notify_error return_code;	FD_ZERO(&ibits); FD_ZERO(&obits); FD_ZERO(&ebits);	/* Notify_start is not reentrant */	if (ndet_flags & NDET_STARTED) {		ntfy_set_errno(NOTIFY_INVAL);		return(notify_errno);	}	/* Always go around the loop at least once */	ndet_flags |= NDET_STARTED;	do {		NTFY_BEGIN_CRITICAL;		/* Ndet_update_*_itimer (below) may set up NDET_ITIMER_ENQ*/		ndet_flags &= ~NDET_ITIMER_ENQ;		/* If nothing has changed then do no set up */		if (ndet_flags & NDET_CONDITION_CHANGE) {			if (ndet_flags & NDET_REAL_CHANGE)				ndet_update_real_itimer();			if (ndet_flags & NDET_VIRTUAL_CHANGE)				ndet_update_virtual_itimer();			if (ndet_flags & NDET_FD_CHANGE)				ndet_fig_fd_change();			if (ndet_flags & NDET_WAIT3_CHANGE)				ndet_fig_wait3_change();			if (ndet_flags & NDET_DESTROY_CHANGE)				ndet_fig_destroy_change();			/*			 * Always handle signal changes last because other			 * ndet_*_change and ndet_update_*_itimer calls may			 * have set NDET_SIGNAL_CHANGE in ndet_flags.			 */			if (ndet_flags & NDET_SIGNAL_CHANGE)				ndet_fig_sig_change();		}		/*		 * Set up select parameters.  Wouldn't get changes from		 * signal processing this time around.  Poll if stuff in		 * the dispatch queue.		 */		timer = (		   ndet_flags & (NDET_POLL | NDET_ITIMER_ENQ | NDET_NO_DELAY) ||		   ndis_clients != NTFY_CLIENT_NULL)?		      &ndet_polling_tv: NTFY_TIMEVAL_NULL;		ibits = ndet_ibits;		obits = ndet_obits;		ebits = ndet_ebits;		NTFY_END_CRITICAL;		/*		 * From the tests of ndet_sigs_received until get into		 * pause or select below is a race condition.		 * It is possible to get a signal during this time that wouldn't		 * get serviced until something breaks us out of the block.		 * Can't get away from this.  UNIX needs a version of select		 * and pause that will simultaneously release blocked signals.		 * We test ndet_sigs_received as late as possible in order		 * to reduce this window of vulnerability.		 */		if (!ntfy_fd_anyset(&ibits) && !ntfy_fd_anyset(&obits) &&		    !ntfy_fd_anyset(&ebits) && timer == NTFY_TIMEVAL_NULL && 		    !ndet_sigs_received) {			if (ndet_sigs_managing != 0) {				/* Wait for interrupt */				pause();			} else {				/* Not detecting ANY conditions */				return_code = NOTIFY_NO_CONDITION;				goto Finish;			}		} else {			/*			 * Hack to avoid race condition described below.			 * notify_signal_check must be called explicitly			 * to enable this mechanism.			 */			if ((timer == NTFY_TIMEVAL_NULL) &&			    (timerisset(&ndet_signal_check)))				timer = &ndet_signal_check;			/*			 * Wait for select to return.			 *			 * Do this ndet_sigs_received test at the last possible			 * nano in order to reduce the unavoidable race			 * condition between detecting signal arrival and			 * making the call to select (which will return with an			 * EINTR when a signal arrives while IN select,			 * not ON THE WAY into select).			 */			nfds = syscall(SYS_select,			    FD_SETSIZE, &ibits, &obits, &ebits,			    (ndet_sigs_received)? &ndet_polling_tv: timer);			errno_remember = errno;			/* See if select returned unconventionally */			if (nfds == -1) {				/* Clear *bits when in an undefined situation */				FD_ZERO(&ibits); FD_ZERO(&obits);				FD_ZERO(&ebits);				switch (errno) {				case EINTR:					/* Signals received */					if (ndet_flags & NDET_STOP_ON_SIG)						(void) notify_stop();					break; /* Out of switch */				case EBADF:					ntfy_set_errno(NOTIFY_BADF);					goto Error;				default:					ntfy_set_errno(NOTIFY_INVAL);					goto Error;				}			} else {				/*				 * Terminate notification loop if ask to				 * stop on sig and received signal before				 * entering select.				 */				if (ndet_flags & NDET_STOP_ON_SIG &&				    ndet_sigs_received) {					(void) notify_stop();					/*					 * Modify errno to indicate that an					 * signal was received during select.					 */					errno_remember = errno = EINTR;				}			/*			 * (timer && (nfds == 0)) means select timer expired.			 * Since will only go off in polling situation and			 * we send poll notifications every time around loop,			 * fall through.			 */			}		}		/* Enqueue detected notifications with the dispatcher */		NTFY_BEGIN_CRITICAL;		/* Set up enumeration record */		enum_send.ibits = ibits;		enum_send.obits = obits;		enum_send.ebits = ebits;		enum_send.wait3 = NTFY_WAIT3_DATA_NULL;		timerclear(&(enum_send.current_tv));		enum_send.sigs = ndet_sigs_received;		ndet_sigs_received = 0;		/* Check for fd related condition */		/*if (ibits || obits || ebits) */		if (ntfy_fd_anyset(&ibits) || ntfy_fd_anyset(&obits) ||		    ntfy_fd_anyset(&ebits))			if (ntfy_enum_conditions(ndet_clients, ndet_fd_send,			    (NTFY_ENUM_DATA)&enum_send) == NTFY_ENUM_TERM)				goto Protected_Error;		/* Check for signal related condition */		if (enum_send.sigs)			/*			 * Use paranoid enum because when get in to			 * ndet_auto_sig_send will do another enumeration			 * that can axe client/condition but not have the			 * opportunity to return NTFY_ENUM_SKIP to the			 * original enumeration (this one).			 */			if(ntfy_paranoid_enum_conditions(ndet_clients,			    ndet_sig_send, (NTFY_ENUM_DATA)&enum_send) ==			    NTFY_ENUM_TERM)				goto Protected_Error;		if (ndet_flags & NDET_POLL)			if (ntfy_enum_conditions(ndet_clients, ndet_poll_send,			    NTFY_ENUM_DATA_NULL) == NTFY_ENUM_TERM)				goto Protected_Error;		NTFY_END_CRITICAL;		/* Dispatch any notification enqueued with the dispatcher */		if (ndis_dispatch() != NOTIFY_OK)			goto Error;	} while (!(ndet_flags & (NDET_STOP | NDET_NO_DELAY)));	return_code = NOTIFY_OK;	goto Finish;Protected_Error:	NTFY_END_CRITICAL;Error:	return_code = notify_errno;Finish:	ndet_flags &= ~(NDET_STOP | NDET_STARTED);	if (ndet_flags & NDET_EXIT_SOON) {		/* Allow everyone to clean up */		(void) notify_die(DESTROY_PROCESS_DEATH);		exit(1);	}	if (ndet_flags & NDET_STOP_ON_SIG) {#ifdef	NTFY_DEBUG_SELECT		char sb[100];		sprintf(sb,		    "errno changed (old=%ld, cur=%ld); reset to old",		    errno_remember, errno);		ntfy_assert(errno == errno_remember, sb);#endif	NTFY_DEBUG_SELECT		errno = errno_remember;	}	return(return_code);}/* * Set flag indicating that should return from notify_start. */extern Notify_errornotify_stop(){	if (ndet_flags & NDET_STARTED) {		ndet_flags |= NDET_STOP;		return(NOTIFY_OK);	} else		return(NOTIFY_NOT_STARTED);}/* * Some fd related condition has changed.  Reset all ndet_*bits. * Enable(disable) notifier auto signal catching of SIGIO and SIGURG. */static voidndet_fig_fd_change(){	u_int sigs_tmp;	ndet_flags &= ~NDET_FD_CHANGE;	/* Remember bits of notifier auto signal catcher */	sigs_tmp = ndet_sigs_auto;	/* Zero out bits */	FD_ZERO(&ndet_ibits); FD_ZERO(&ndet_obits); FD_ZERO(&ndet_ebits); 	ndet_sigs_auto &= ~(SIG_BIT(SIGIO) | SIG_BIT(SIGURG));	/* Recompute all bits */	(void) ntfy_enum_conditions(ndet_clients, ndet_fd_change,	    NTFY_ENUM_DATA_NULL);	/* Toggle notifier auto signal catching if situation changed */	ndet_toggle_auto(sigs_tmp, SIGIO);	ndet_toggle_auto(sigs_tmp, SIGURG);}/* ARGSUSED */static NTFY_ENUMndet_fd_change(client, condition, context)	NTFY_CLIENT *client;	NTFY_CONDITION *condition;	NTFY_ENUM_DATA context;{	switch (condition->type) {	case NTFY_INPUT:		if (FD_ISSET(condition->data.fd, &ndet_fasync_mask))			ndet_sigs_auto |= SIG_BIT(SIGIO);		else			/*ndet_ibits |= bit; */			FD_SET(condition->data.fd, &ndet_ibits);		break;	case NTFY_OUTPUT:		if (FD_ISSET(condition->data.fd, &ndet_fasync_mask))			ndet_sigs_auto |= SIG_BIT(SIGIO);		else			/*ndet_obits |= bit; */			FD_SET(condition->data.fd, &ndet_obits);		break;	case NTFY_EXCEPTION:		if (FD_ISSET(condition->data.fd, &ndet_fasync_mask))			ndet_sigs_auto |= SIG_BIT(SIGURG);		else			/*ndet_ebits |= bit; */			FD_SET(condition->data.fd, &ndet_ebits);		break;	default: {}	}	return(NTFY_ENUM_NEXT);}/* * Some wait3 condition has changed. * Enable(disable) notifier auto signal catching of SIGCHLD. */static	voidndet_fig_wait3_change(){	u_int sigs_tmp;	ndet_flags &= ~NDET_WAIT3_CHANGE;	/* Remember bits of notifier auto signal catcher */	sigs_tmp = ndet_sigs_auto;	/* Zero out bits */	ndet_sigs_auto &= ~SIG_BIT(SIGCHLD);	/* See if any wait conditions */	(void) ntfy_enum_conditions(ndet_clients, ndet_wait3_change,	    NTFY_ENUM_DATA_NULL);	/* Toggle notifier auto signal catching if situation changed */	ndet_toggle_auto(sigs_tmp, SIGCHLD);}/* ARGSUSED */static NTFY_ENUMndet_wait3_change(client, condition, context)	NTFY_CLIENT *client;	NTFY_CONDITION *condition;	NTFY_ENUM_DATA context;{	if (condition->type == NTFY_WAIT3)		ndet_sigs_auto |= SIG_BIT(SIGCHLD);	return(NTFY_ENUM_NEXT);}/* * Some virtual itimer related condition has changed.  Update all virtual * itimers.  Determine minimum wait and set virtual itimer. * Enable(disable) notifier auto signal catching of SIGVTALRM. */pkg_private voidndet_update_virtual_itimer(){	struct timeval ndet_virtual_min();	struct itimerval current_itimer;	NDET_ENUM_ITIMER enum_itimer;	int n;	ndet_flags &= ~(NDET_VIRTUAL_CHANGE | NDET_VIRTUAL_POLL);	/* Initialize virtual itimer update probe */	enum_itimer.type = NTFY_VIRTUAL_ITIMER;	enum_itimer.polling_bit = NDET_VIRTUAL_POLL;	enum_itimer.signal = SIGVTALRM;	enum_itimer.which = ITIMER_VIRTUAL;	enum_itimer.min_func = ndet_virtual_min;	/* Virtual itimers are relative to current state of process itimer */	n = getitimer(ITIMER_VIRTUAL, &current_itimer); /* SYSTEM CALL */	ntfy_assert(n == 0, "Unexpected error: getitimer");	enum_itimer.current_tv = current_itimer.it_value;	/* enum_itimer.min_tv is initialized in ndet_update_itimer. */	/*	 * Update existing virtual itimer conditions and find what process	 * itimer was set to.	 */	ndet_update_itimer(&enum_itimer);	/* Update set_tv in existing virtual itimers */	(void) ntfy_enum_conditions(ndet_clients, ndet_virtual_set_tv_update,	    (NTFY_ENUM_DATA)&enum_itimer.min_tv);}/* * Some real itimer related condition has changed. * Determine minimum wait and set real itimer. * Enable(disable) notifier auto signal catching of SIGALRM. */pkg_private voidndet_update_real_itimer(){	struct timeval ndet_real_min();	NDET_ENUM_ITIMER enum_itimer;	int n;	ndet_flags &= ~(NDET_REAL_CHANGE | NDET_REAL_POLL);	/* Initialize virtual itimer update probe */	enum_itimer.type = NTFY_REAL_ITIMER;	enum_itimer.polling_bit = NDET_REAL_POLL;	enum_itimer.signal = SIGALRM;	enum_itimer.which = ITIMER_REAL;	enum_itimer.min_func = ndet_real_min;	/* Real itimers are relative to current time of day */	n = gettimeofday(&enum_itimer.current_tv,			(struct timezone *)0); /* SYSTEM CALL */

⌨️ 快捷键说明

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