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 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 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 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 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 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 * 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 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 * 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