File:  [MW Coherent from dump] / coherent / b / kernel / coh.386 / poll.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:37 2019 UTC (7 years ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/* $Header: /var/lib/cvsd/repos/coherent/coherent/b/kernel/coh.386/poll.c,v 1.1.1.1 2019/05/29 04:56:37 root Exp $ */
/*
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1986
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * [Stream] Polling.
 *
 *	void pollinit() -- allocate polling buffers
 *	int pollopen(qp) -- enable polling  by current process  on given queue
 *	int pollwake(qp) -- wake all processes waiting for poll on given queue
 *	int pollexit() -- terminate all polls enabled by current process
 *	event_t * ep;
 *
 * $Log: poll.c,v $
 * Revision 1.1.1.1  2019/05/29 04:56:37  root
 * coherent
 *
 * Revision 1.3  93/04/14  10:06:42  root
 * r75
 * 
 * Revision 1.2  92/01/06  11:59:56  hal
 * Compile with cc.mwc.
 * 
 * Revision 1.1	88/03/24  16:14:10	src
 * Initial revision
 * 
 * 86/11/19	Allan Cornish		/usr/src/sys/coh/poll.c
 * Ported to Coherent from RTX.
 */

#include <sys/coherent.h>
#include <sys/proc.h>

/*
 * Patchable data.
 */
int	NPOLL  = 0;

/*
 * Private data.
 */
static	event_t	* efreep;

/**
 *
 * event_t *
 * pollinit()		-- allocate event buffers.
 */
event_t *
pollinit()
{
	register event_t * ep;
	register event_t * ap;
	static int first = 1;

	/*
	 * If dynamically growing event pool is specified [NPOLL == 0],
	 * try to allocate an additional cluster of 32 on each call.
	 */
	if (NPOLL == 0) {
		if (ep = kalloc(32 * sizeof(event_t)))
			ap = ep + 32;
	}

	/*
	 * If statically sized event pool is specified [NPOLL != 0],
	 * try to allocate the pool on the first call.
	 */
	else if (first) {
		first = 0;
		if (ep = kalloc(NPOLL * sizeof(event_t)))
			ap = ep + NPOLL;
	}

	/*
	 * If event cluster was allocated, insert into free event queue.
	 */
	if (ep) {
		do {
			ep->e_pnext = efreep;
			efreep = ep;
		} while (++ep < ap);
	}

	return efreep;
}

/**
 *
 * int
 * pollopen(qp) -- enable polling by current process on given event queue
 * event_t * qp;
 */
pollopen(qp)
register event_t * qp;
{
	register event_t * ep;

	/*
	 * Initialize device queue if required.
	 */
	if (qp->e_dnext == 0)
		qp->e_dnext = qp->e_dlast = qp;

	/*
	 * Obtain a free event buffer, or return.
	 */
	if (((ep = efreep) == 0) && ((ep = pollinit()) == 0)) {
		printf("out of poll buffers\n");
		return;
	}

	/*
	 * Remove event buffer from free queue.
	 */
	efreep = ep->e_pnext;

	/*
	 * Record process pointer in event buffer.
	 */
	ep->e_procp = cprocp;

	/*
	 * Insert event at head of process event singularly-linked queue.
	 */
	ep->e_pnext = cprocp->p_polls;
	cprocp->p_polls = ep;

	/*
	 * Insert event at tail of circularly-linked device queue.
	 * This ensures that processes are first-in first-out.
	 */
	ep->e_dnext  = qp;
	(ep->e_dlast = qp->e_dlast)->e_dnext = ep;
	qp->e_dlast  = ep;

	/*
	 * Record last process to enable polling on device.
	 */
	qp->e_procp = cprocp;
}

/**
 *
 * int
 * pollwake(qp) -- wake all processes waiting for poll on given queue
 * event_t * qp;
 *
 * Go through extra step of deferring the pollwake to avoid race condition
 * (in case interrupt handler does a pollwake() during upoll()).
 */
pollwake(qp)
event_t * qp;
{
	void dpollwake();

	defer(dpollwake, qp);
}

void
dpollwake(qp)
event_t * qp;
{
	register event_t * ep = qp;
	register PROC    * pp;

	/*
	 * Clear device process pointer, indicating poll completed.
	 * NOTE: interrupt handlers may have already cleared it.
	 */
	qp->e_procp = 0;

	if (ep = qp->e_dnext) {

		/*
		 * Service circularly-linked polls on device queue.
		 */
		while (ep != qp) {
			/*
			 * Wake process if it is sleeping.
			 */
			if ((pp = ep->e_procp) && ASLEEP(pp))
				wakeup(&pp->p_polls);

			ep = ep->e_dnext;
		}
	}
}

/**
 *
 * int
 * pollexit() -- terminate all polls opened by current process
 */
int
pollexit()
{
	register PROC    * pp = cprocp;
	register event_t * ep;

	/*
	 * Service all polling event buffers enabled by current process.
	 */
	while (ep = pp->p_polls) {

		/*
		 * Remove event buffer from circularly-linked device queue.
		 */
		(ep->e_dnext->e_dlast = ep->e_dlast)->e_dnext = ep->e_dnext;

		/*
		 * Remove event buffer from singularly-linked process queue.
		 */
		pp->p_polls = ep->e_pnext;

		/*
		 * Insert event buffer at head of free event buffer queue.
		 */
		ep->e_pnext = efreep;
		efreep = ep;
	}
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.