xref: /onnv-gate/usr/src/lib/libresolv2/common/isc/ev_waits.c (revision 11038:74b12212b8a2)
10Sstevel@tonic-gate /*
2*11038SRao.Shoaib@Sun.COM  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
30Sstevel@tonic-gate  * Copyright (c) 1996-1999 by Internet Software Consortium
40Sstevel@tonic-gate  *
50Sstevel@tonic-gate  * Permission to use, copy, modify, and distribute this software for any
60Sstevel@tonic-gate  * purpose with or without fee is hereby granted, provided that the above
70Sstevel@tonic-gate  * copyright notice and this permission notice appear in all copies.
80Sstevel@tonic-gate  *
9*11038SRao.Shoaib@Sun.COM  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10*11038SRao.Shoaib@Sun.COM  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*11038SRao.Shoaib@Sun.COM  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
12*11038SRao.Shoaib@Sun.COM  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*11038SRao.Shoaib@Sun.COM  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*11038SRao.Shoaib@Sun.COM  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15*11038SRao.Shoaib@Sun.COM  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
160Sstevel@tonic-gate  */
170Sstevel@tonic-gate 
180Sstevel@tonic-gate /* ev_waits.c - implement deferred function calls for the eventlib
190Sstevel@tonic-gate  * vix 05dec95 [initial]
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate 
220Sstevel@tonic-gate #if !defined(LINT) && !defined(CODECENTER)
23*11038SRao.Shoaib@Sun.COM static const char rcsid[] = "$Id: ev_waits.c,v 1.4 2005/04/27 04:56:36 sra Exp $";
240Sstevel@tonic-gate #endif
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include "port_before.h"
270Sstevel@tonic-gate #include "fd_setsize.h"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #include <errno.h>
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #include <isc/eventlib.h>
320Sstevel@tonic-gate #include <isc/assertions.h>
330Sstevel@tonic-gate #include "eventlib_p.h"
340Sstevel@tonic-gate 
350Sstevel@tonic-gate #include "port_after.h"
360Sstevel@tonic-gate 
370Sstevel@tonic-gate /* Forward. */
380Sstevel@tonic-gate 
390Sstevel@tonic-gate static void		print_waits(evContext_p *ctx);
400Sstevel@tonic-gate static evWaitList *	evNewWaitList(evContext_p *);
410Sstevel@tonic-gate static void		evFreeWaitList(evContext_p *, evWaitList *);
420Sstevel@tonic-gate static evWaitList *	evGetWaitList(evContext_p *, const void *, int);
430Sstevel@tonic-gate 
440Sstevel@tonic-gate 
450Sstevel@tonic-gate /* Public. */
460Sstevel@tonic-gate 
47*11038SRao.Shoaib@Sun.COM /*%
480Sstevel@tonic-gate  * Enter a new wait function on the queue.
490Sstevel@tonic-gate  */
500Sstevel@tonic-gate int
evWaitFor(evContext opaqueCtx,const void * tag,evWaitFunc func,void * uap,evWaitID * id)510Sstevel@tonic-gate evWaitFor(evContext opaqueCtx, const void *tag,
520Sstevel@tonic-gate 	  evWaitFunc func, void *uap, evWaitID *id)
530Sstevel@tonic-gate {
540Sstevel@tonic-gate 	evContext_p *ctx = opaqueCtx.opaque;
550Sstevel@tonic-gate 	evWait *new;
560Sstevel@tonic-gate 	evWaitList *wl = evGetWaitList(ctx, tag, 1);
570Sstevel@tonic-gate 
580Sstevel@tonic-gate 	OKNEW(new);
590Sstevel@tonic-gate 	new->func = func;
600Sstevel@tonic-gate 	new->uap = uap;
610Sstevel@tonic-gate 	new->tag = tag;
620Sstevel@tonic-gate 	new->next = NULL;
630Sstevel@tonic-gate 	if (wl->last != NULL)
640Sstevel@tonic-gate 		wl->last->next = new;
650Sstevel@tonic-gate 	else
660Sstevel@tonic-gate 		wl->first = new;
670Sstevel@tonic-gate 	wl->last = new;
680Sstevel@tonic-gate 	if (id != NULL)
690Sstevel@tonic-gate 		id->opaque = new;
700Sstevel@tonic-gate 	if (ctx->debug >= 9)
710Sstevel@tonic-gate 		print_waits(ctx);
720Sstevel@tonic-gate 	return (0);
730Sstevel@tonic-gate }
740Sstevel@tonic-gate 
75*11038SRao.Shoaib@Sun.COM /*%
760Sstevel@tonic-gate  * Mark runnable all waiting functions having a certain tag.
770Sstevel@tonic-gate  */
780Sstevel@tonic-gate int
evDo(evContext opaqueCtx,const void * tag)790Sstevel@tonic-gate evDo(evContext opaqueCtx, const void *tag) {
800Sstevel@tonic-gate 	evContext_p *ctx = opaqueCtx.opaque;
810Sstevel@tonic-gate 	evWaitList *wl = evGetWaitList(ctx, tag, 0);
820Sstevel@tonic-gate 	evWait *first;
830Sstevel@tonic-gate 
840Sstevel@tonic-gate 	if (!wl) {
850Sstevel@tonic-gate 		errno = ENOENT;
860Sstevel@tonic-gate 		return (-1);
870Sstevel@tonic-gate 	}
880Sstevel@tonic-gate 
890Sstevel@tonic-gate 	first = wl->first;
900Sstevel@tonic-gate 	INSIST(first != NULL);
910Sstevel@tonic-gate 
920Sstevel@tonic-gate 	if (ctx->waitDone.last != NULL)
930Sstevel@tonic-gate 		ctx->waitDone.last->next = first;
940Sstevel@tonic-gate 	else
950Sstevel@tonic-gate 		ctx->waitDone.first = first;
960Sstevel@tonic-gate 	ctx->waitDone.last = wl->last;
970Sstevel@tonic-gate 	evFreeWaitList(ctx, wl);
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 	return (0);
1000Sstevel@tonic-gate }
1010Sstevel@tonic-gate 
102*11038SRao.Shoaib@Sun.COM /*%
1030Sstevel@tonic-gate  * Remove a waiting (or ready to run) function from the queue.
1040Sstevel@tonic-gate  */
1050Sstevel@tonic-gate int
evUnwait(evContext opaqueCtx,evWaitID id)1060Sstevel@tonic-gate evUnwait(evContext opaqueCtx, evWaitID id) {
1070Sstevel@tonic-gate 	evContext_p *ctx = opaqueCtx.opaque;
1080Sstevel@tonic-gate 	evWait *this, *prev;
1090Sstevel@tonic-gate 	evWaitList *wl;
1100Sstevel@tonic-gate 	int found = 0;
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 	this = id.opaque;
1130Sstevel@tonic-gate 	INSIST(this != NULL);
1140Sstevel@tonic-gate 	wl = evGetWaitList(ctx, this->tag, 0);
1150Sstevel@tonic-gate 	if (wl != NULL) {
1160Sstevel@tonic-gate 		for (prev = NULL, this = wl->first;
1170Sstevel@tonic-gate 		     this != NULL;
1180Sstevel@tonic-gate 		     prev = this, this = this->next)
1190Sstevel@tonic-gate 			if (this == (evWait *)id.opaque) {
1200Sstevel@tonic-gate 				found = 1;
1210Sstevel@tonic-gate 				if (prev != NULL)
1220Sstevel@tonic-gate 					prev->next = this->next;
1230Sstevel@tonic-gate 				else
1240Sstevel@tonic-gate 					wl->first = this->next;
1250Sstevel@tonic-gate 				if (wl->last == this)
1260Sstevel@tonic-gate 					wl->last = prev;
1270Sstevel@tonic-gate 				if (wl->first == NULL)
1280Sstevel@tonic-gate 					evFreeWaitList(ctx, wl);
1290Sstevel@tonic-gate 				break;
1300Sstevel@tonic-gate 			}
1310Sstevel@tonic-gate 	}
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate 	if (!found) {
1340Sstevel@tonic-gate 		/* Maybe it's done */
1350Sstevel@tonic-gate 		for (prev = NULL, this = ctx->waitDone.first;
1360Sstevel@tonic-gate 		     this != NULL;
1370Sstevel@tonic-gate 		     prev = this, this = this->next)
1380Sstevel@tonic-gate 			if (this == (evWait *)id.opaque) {
1390Sstevel@tonic-gate 				found = 1;
1400Sstevel@tonic-gate 				if (prev != NULL)
1410Sstevel@tonic-gate 					prev->next = this->next;
1420Sstevel@tonic-gate 				else
1430Sstevel@tonic-gate 					ctx->waitDone.first = this->next;
1440Sstevel@tonic-gate 				if (ctx->waitDone.last == this)
1450Sstevel@tonic-gate 					ctx->waitDone.last = prev;
1460Sstevel@tonic-gate 				break;
1470Sstevel@tonic-gate 			}
1480Sstevel@tonic-gate 	}
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	if (!found) {
1510Sstevel@tonic-gate 		errno = ENOENT;
1520Sstevel@tonic-gate 		return (-1);
1530Sstevel@tonic-gate 	}
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	FREE(this);
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	if (ctx->debug >= 9)
1580Sstevel@tonic-gate 		print_waits(ctx);
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate 	return (0);
1610Sstevel@tonic-gate }
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate int
evDefer(evContext opaqueCtx,evWaitFunc func,void * uap)1640Sstevel@tonic-gate evDefer(evContext opaqueCtx, evWaitFunc func, void *uap) {
1650Sstevel@tonic-gate 	evContext_p *ctx = opaqueCtx.opaque;
1660Sstevel@tonic-gate 	evWait *new;
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 	OKNEW(new);
1690Sstevel@tonic-gate 	new->func = func;
1700Sstevel@tonic-gate 	new->uap = uap;
1710Sstevel@tonic-gate 	new->tag = NULL;
1720Sstevel@tonic-gate 	new->next = NULL;
1730Sstevel@tonic-gate 	if (ctx->waitDone.last != NULL)
1740Sstevel@tonic-gate 		ctx->waitDone.last->next = new;
1750Sstevel@tonic-gate 	else
1760Sstevel@tonic-gate 		ctx->waitDone.first = new;
1770Sstevel@tonic-gate 	ctx->waitDone.last = new;
1780Sstevel@tonic-gate 	if (ctx->debug >= 9)
1790Sstevel@tonic-gate 		print_waits(ctx);
1800Sstevel@tonic-gate 	return (0);
1810Sstevel@tonic-gate }
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate /* Private. */
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate static void
print_waits(evContext_p * ctx)1860Sstevel@tonic-gate print_waits(evContext_p *ctx) {
1870Sstevel@tonic-gate 	evWaitList *wl;
1880Sstevel@tonic-gate 	evWait *this;
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	evPrintf(ctx, 9, "wait waiting:\n");
1910Sstevel@tonic-gate 	for (wl = ctx->waitLists; wl != NULL; wl = wl->next) {
1920Sstevel@tonic-gate 		INSIST(wl->first != NULL);
1930Sstevel@tonic-gate 		evPrintf(ctx, 9, "  tag %p:", wl->first->tag);
1940Sstevel@tonic-gate 		for (this = wl->first; this != NULL; this = this->next)
1950Sstevel@tonic-gate 			evPrintf(ctx, 9, " %p", this);
1960Sstevel@tonic-gate 		evPrintf(ctx, 9, "\n");
1970Sstevel@tonic-gate 	}
1980Sstevel@tonic-gate 	evPrintf(ctx, 9, "wait done:");
1990Sstevel@tonic-gate 	for (this = ctx->waitDone.first; this != NULL; this = this->next)
2000Sstevel@tonic-gate 		evPrintf(ctx, 9, " %p", this);
2010Sstevel@tonic-gate 	evPrintf(ctx, 9, "\n");
2020Sstevel@tonic-gate }
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate static evWaitList *
evNewWaitList(evContext_p * ctx)2050Sstevel@tonic-gate evNewWaitList(evContext_p *ctx) {
2060Sstevel@tonic-gate 	evWaitList *new;
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 	NEW(new);
2090Sstevel@tonic-gate 	if (new == NULL)
2100Sstevel@tonic-gate 		return (NULL);
2110Sstevel@tonic-gate 	new->first = new->last = NULL;
2120Sstevel@tonic-gate 	new->prev = NULL;
2130Sstevel@tonic-gate 	new->next = ctx->waitLists;
2140Sstevel@tonic-gate 	if (new->next != NULL)
2150Sstevel@tonic-gate 		new->next->prev = new;
2160Sstevel@tonic-gate 	ctx->waitLists = new;
2170Sstevel@tonic-gate 	return (new);
2180Sstevel@tonic-gate }
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate static void
evFreeWaitList(evContext_p * ctx,evWaitList * this)2210Sstevel@tonic-gate evFreeWaitList(evContext_p *ctx, evWaitList *this) {
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate 	INSIST(this != NULL);
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 	if (this->prev != NULL)
2260Sstevel@tonic-gate 		this->prev->next = this->next;
2270Sstevel@tonic-gate 	else
2280Sstevel@tonic-gate 		ctx->waitLists = this->next;
2290Sstevel@tonic-gate 	if (this->next != NULL)
2300Sstevel@tonic-gate 		this->next->prev = this->prev;
2310Sstevel@tonic-gate 	FREE(this);
2320Sstevel@tonic-gate }
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate static evWaitList *
evGetWaitList(evContext_p * ctx,const void * tag,int should_create)2350Sstevel@tonic-gate evGetWaitList(evContext_p *ctx, const void *tag, int should_create) {
2360Sstevel@tonic-gate 	evWaitList *this;
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate 	for (this = ctx->waitLists; this != NULL; this = this->next) {
2390Sstevel@tonic-gate 		if (this->first != NULL && this->first->tag == tag)
2400Sstevel@tonic-gate 			break;
2410Sstevel@tonic-gate 	}
2420Sstevel@tonic-gate 	if (this == NULL && should_create)
2430Sstevel@tonic-gate 		this = evNewWaitList(ctx);
2440Sstevel@tonic-gate 	return (this);
2450Sstevel@tonic-gate }
246*11038SRao.Shoaib@Sun.COM 
247*11038SRao.Shoaib@Sun.COM /*! \file */
248