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

📄 nb.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 <stdio.h>#include <sys/types.h>#include <sys/param.h>#include <sys/time.h>#include <sys/file.h>#include <sys/socket.h>#include <sys/wait.h>#include <netinet/in.h>#include <signal.h>#include <fcntl.h>#include <errno.h>#include <sys/ioctl.h>#include <rpc/types.h>#include <lwp/lwp.h>#include <lwp/lwperror.h>#include <lwp/lwpmachdep.h>#include <lwp/stackdep.h>#include <syscall.h>#include "../queue.h"extern int errno;/* @(#) nb.c 1.1 92/07/30 Copyr 1987 Sun Micro *//* * UNIX functions that can block. * This library maps all potentially blocking system calls * into non-blocking ones. This provides some temporary help * for threads that use system calls until kernel thread support is available. * Because underlying descriptors are marked NB and ASYNCH in UNIX, * this library doesn't work well with other unix processes * sharing descriptors. Also, problems with kill -9 * since you can't catch this to reset a descriptor. * We don't do exit processing (see on_exit) if a default signal action * kills the pod either. * We mark C library special context for threads using system calls. * This preserves errno for these threads. * File descriptors are treated as global state: if two threads * try to open/close the same descriptor, no guarantees hold. * XXX We could improve things by using special contexts to hold * the per-thread info. The only disadvantage is that this could * slow down scheduling slightly for threads that don't use special contexts. *//* * we don't handle flock(2), or sigpause(2). * readv and writev are rarely used so we don't bother with them. * These are the guys we support: * * open(), socket(), pipe(), close(), * read(), write(), * send(), sendto(), sendmsg(), recv(), recvfom(), recvmsg(), * accept(), connect(), * select(); * wait(); */#define	READ	0#define	WRITE	1#define	EXCEPT  2/* info about a descriptor */typedef	struct nb_t {	int issocket;	/* TRUE if descriptor is a socket */	int old_flag;	/* previous value of descriptor flags */} nb_t;/* info about an agent used to monitor a descriptor */typedef	struct agent_t {	struct agent_t *agt_next;	thread_t agt_lwpid;	int agt_event;	caddr_t agt_mem;	thread_t agt_aid;} agent_t;#define	AGT_TYPES 2#define	AGT_SIGIO 0#define	AGT_SIGCHLD 1static nb_t NbDesc[NOFILE];static qheader_t NbAgt[AGT_TYPES];static NbInit = FALSE;static int NbSet[NOFILE];static mon_t AgtMon;#define	INIT() {if (!NbInit) nbio_init(); }static int MyPid;	/* for adding signals to process group */static int NDesc;	/* Number of file descriptors UNIX supports *//* * Initialize non-blocking lwp library. */static voidnbio_init(){	int i;	extern void nbio_lastrites();	extern void fdreset();	static stkalign_t stack[2000];	for (i = 0; i< NOFILE; i++) {		NbDesc[i].issocket = FALSE;		NbDesc[i].old_flag = 0;		NbSet[i] = FALSE;	}	for (i = 0; i < AGT_TYPES; i++)		INIT_QUEUE(&(NbAgt[i]));	MyPid = -getpid();	(void) lwp_create((thread_t *)0, nbio_lastrites, MINPRIO,	    (LWPSERVER | LWPNOLASTRITES), STKTOP(stack), 0);	mon_create(&AgtMon);	NDesc = getdtablesize();	NbInit = TRUE;	on_exit(fdreset, 0);	/* XX should catch signals too? */}/* * Get an agent for a thread to receive unblocking signals on. * There is one agent per event per lwp - agents are stored on a linked list - * probably should be a hash table. * We don't create a new agent each time for two reasons: 1) if we create * and destroy an agent, we may drop signals before having a chance to * create a new one for the new IO, and 2) for efficiency. * Threads must check that the event they receive was really for them: e.g., * see if some IO is really available. * We also mark this thread as a C-library thread so it doesn't drop errno. */static voidget_agent(agent, agt_type)	thread_t *agent;	int agt_type;{	agent_t *agt;	thread_t self;	MONITOR(AgtMon);	lwp_self(&self);	for (agt = (agent_t *)FIRSTQ(&(NbAgt[agt_type]));	    agt != (agent_t *)0; agt = agt->agt_next) {		if (SAMETHREAD(agt->agt_lwpid, self)) {			*agent = agt->agt_aid;			return;		}	}	lwp_libcset(self);	agt = (agent_t *)malloc(sizeof (agent_t));	agt->agt_lwpid = self;	agt->agt_event = agt_type;	agt->agt_mem = (agt_type == AGT_SIGIO) ?	    malloc(sizeof (eventinfo_t)) :	    malloc(sizeof (sigchldev_t));	agt_create(&agt->agt_aid, agt_type == AGT_SIGIO ? SIGIO : SIGCHLD,	    agt->agt_mem);	INS_QUEUE(&(NbAgt[agt_type]), agt);	*agent = agt->agt_aid;}/* * Called each time a client thread dies. * Reclaim its nbio resources. */static voidnbio_lastrites() {	thread_t aid;	eventinfo_t *event;	int argsz;	eventinfo_t lastrites;	thread_t tid;	/* dying thread */	register agent_t *agt;	(void) agt_create(&aid, LASTRITES, (caddr_t)&lastrites);	for (;;) {		(void) msg_recv(&aid, (caddr_t *)&event, &argsz,		    (caddr_t *)0, (int *)0, INFINITY);		tid = event->eventinfo_victimid;		msg_reply(aid);		/*		 * Search for all nbio agents belonging to tid		 * and remove them and their agent memory.		 * The REMX_ITEM is inefficient: should		 * do the search and removal together.		 */		mon_enter(AgtMon);		for (agt = (agent_t *)FIRSTQ(&(NbAgt[AGT_SIGIO]));		    agt != (struct agent_t *)0; agt = agt->agt_next) {			if (SAMETHREAD(agt->agt_lwpid, tid)) {				free(agt->agt_mem);				REMX_ITEM(&(NbAgt[AGT_SIGIO]), agt);				free((caddr_t)agt);				break;			}		}		for (agt = (agent_t *)FIRSTQ(&(NbAgt[AGT_SIGCHLD]));		    agt != (struct agent_t *)0; agt = agt->agt_next) {			if (SAMETHREAD(agt->agt_lwpid, tid)) {				free(agt->agt_mem);				REMX_ITEM(&(NbAgt[AGT_SIGCHLD]), agt);				free((caddr_t)agt);				break;			}		}		mon_exit(AgtMon);	}}/* * mark a descriptor non-blocking. * don't reset descriptor after each IO since another thread * may be using the descriptor. Monitor protection won't solve * the problem since there is no way to atomically release the monitor * upon entry into the kernel. */static intnblk_io(desc, issock)	int desc;	int issock;{	int res;	if (NbSet[desc])		return (0);	/* must set process group for sock io explicitly */	if (issock) {		NbDesc[desc].issocket = TRUE;		if (ioctl(desc, SIOCSPGRP, &MyPid) == -1)			return (-1);	}	if ((res = fcntl(desc, F_GETFL, 0)) == -1) {		return (-1);	} else {		NbDesc[desc].old_flag = res;	}	if (fcntl(desc, F_SETFL, FASYNC|FNDELAY) == -1)		return (-1);	NbSet[desc] = TRUE;	return (0);}/* * Reset all descriptors upon pod termination. */static voidfdreset(){	register int fd;	for (fd = 0; fd < NOFILE; fd++) {		if (NbSet[fd]) {			(void)fcntl(fd, F_SETFL, NbDesc[fd].old_flag);			NbSet[fd] = FALSE;		}	}}/* * Await IO on a descriptor. */static voidblock_io(desc, operation)	int desc;	int operation;{	fd_set rmask, wmask, emask;	register int nready;	FD_ZERO(&rmask); FD_ZERO(&wmask); FD_ZERO(&emask);	switch (operation){	    case READ :		FD_SET(desc, &rmask);		break;	    case WRITE :		FD_SET(desc, &wmask);		break;	}	FD_SET(desc, &emask);	/* always catch exceptions */	errno = 0;	nready =	    block_until_notified(NDesc, &rmask, &wmask, &emask, INFINITY);	if (nready <= 0) {		if (lwp_geterr() != LE_NOERROR)			lwp_perror("block");		if (errno != 0)			perror("block");	}}/* Copy masks for select (which alters its arguments) */static voidset_masks(rmask, wmask, emask, c_rmask, c_wmask, c_emask)	fd_set *rmask, *wmask, *emask, *c_rmask, *c_wmask, *c_emask;{	if (c_rmask != (fd_set *)NULL) {		if (rmask == (fd_set *)NULL) {			FD_ZERO(c_rmask);		} else {			bcopy((caddr_t)rmask, (caddr_t)c_rmask,			    sizeof (fd_set));		}	}	if (c_wmask != (fd_set *)NULL) {		if (wmask == (fd_set *)NULL) {			FD_ZERO(c_wmask);		} else {			bcopy((caddr_t)wmask, (caddr_t)c_wmask,			    sizeof (fd_set));		}	}	if (c_emask != (fd_set *)NULL) {		if (emask == (fd_set *)NULL) {			FD_ZERO(c_emask);		} else {			bcopy((caddr_t)emask, (caddr_t)c_emask,			    sizeof (fd_set));		}	}}/* 'or' together a set of masks into "mask" */static voidor_masks(mask, rmask, wmask, emask)	fd_set *mask, *rmask, *wmask, *emask;{	register int i;	register caddr_t m = (caddr_t)mask;	fd_set temp;	FD_ZERO(&temp);	m = (caddr_t)mask;	if (rmask == (fd_set *)NULL)		rmask = &temp;	if (wmask == (fd_set *)NULL)		wmask = &temp;	if (emask == (fd_set *)NULL)		emask = &temp;	for (i = 0; i < sizeof (fd_set); i++) {		m[i] =		    ((caddr_t)rmask)[i] | ((caddr_t)wmask)[i] |		    ((caddr_t)emask)[i];	}}/* return TRUE if any descriptors in src appear in dst */intmask_match(src, dst)	fd_set *src;	fd_set *dst;{	register int i;	for (i = 0; i < sizeof (fd_set); i++) {		if (((caddr_t)src)[i] & ((caddr_t)dst)[i]) {			return (TRUE);		}	}	return (FALSE);}/* *  Count the number of bits set in a mask. */static intcountbits(mask, width)	fd_set *mask;	int width;{	register int i;	register int total = 0;	register int nbytes;	nbytes = (width - 1 + NBBY) / NBBY;	for (i = 0; i < sizeof (fd_set); i++) {		total += count(((caddr_t)mask)[i]);	}	return (total);}/* count the number of bits in a byte. should really be a table */static intcount(n)	char n;{	register int tocount = (n & 0xff);	register int bits = 0;	while (tocount) {

⌨️ 快捷键说明

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