1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright 2003 by Sun Microsystems, Inc. All rights reserved. 3*0Sstevel@tonic-gate * Use is subject to license terms. 4*0Sstevel@tonic-gate */ 5*0Sstevel@tonic-gate 6*0Sstevel@tonic-gate /* 7*0Sstevel@tonic-gate * Copyright (c) 1996-1999 by Internet Software Consortium 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any 10*0Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 11*0Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 12*0Sstevel@tonic-gate * 13*0Sstevel@tonic-gate * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 14*0Sstevel@tonic-gate * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 15*0Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 16*0Sstevel@tonic-gate * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 17*0Sstevel@tonic-gate * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 18*0Sstevel@tonic-gate * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 19*0Sstevel@tonic-gate * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20*0Sstevel@tonic-gate * SOFTWARE. 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate 23*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 24*0Sstevel@tonic-gate 25*0Sstevel@tonic-gate /* ev_waits.c - implement deferred function calls for the eventlib 26*0Sstevel@tonic-gate * vix 05dec95 [initial] 27*0Sstevel@tonic-gate */ 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #if !defined(LINT) && !defined(CODECENTER) 30*0Sstevel@tonic-gate static const char rcsid[] = "$Id: ev_waits.c,v 8.12 2002/07/08 05:50:10 marka Exp $"; 31*0Sstevel@tonic-gate #endif 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #include "port_before.h" 34*0Sstevel@tonic-gate #include "fd_setsize.h" 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate #include <errno.h> 37*0Sstevel@tonic-gate 38*0Sstevel@tonic-gate #include <isc/eventlib.h> 39*0Sstevel@tonic-gate #include <isc/assertions.h> 40*0Sstevel@tonic-gate #include "eventlib_p.h" 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate #include "port_after.h" 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate /* Forward. */ 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate static void print_waits(evContext_p *ctx); 47*0Sstevel@tonic-gate static evWaitList * evNewWaitList(evContext_p *); 48*0Sstevel@tonic-gate static void evFreeWaitList(evContext_p *, evWaitList *); 49*0Sstevel@tonic-gate static evWaitList * evGetWaitList(evContext_p *, const void *, int); 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate /* Public. */ 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate /* 55*0Sstevel@tonic-gate * Enter a new wait function on the queue. 56*0Sstevel@tonic-gate */ 57*0Sstevel@tonic-gate int 58*0Sstevel@tonic-gate evWaitFor(evContext opaqueCtx, const void *tag, 59*0Sstevel@tonic-gate evWaitFunc func, void *uap, evWaitID *id) 60*0Sstevel@tonic-gate { 61*0Sstevel@tonic-gate evContext_p *ctx = opaqueCtx.opaque; 62*0Sstevel@tonic-gate evWait *new; 63*0Sstevel@tonic-gate evWaitList *wl = evGetWaitList(ctx, tag, 1); 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate OKNEW(new); 66*0Sstevel@tonic-gate new->func = func; 67*0Sstevel@tonic-gate new->uap = uap; 68*0Sstevel@tonic-gate new->tag = tag; 69*0Sstevel@tonic-gate new->next = NULL; 70*0Sstevel@tonic-gate if (wl->last != NULL) 71*0Sstevel@tonic-gate wl->last->next = new; 72*0Sstevel@tonic-gate else 73*0Sstevel@tonic-gate wl->first = new; 74*0Sstevel@tonic-gate wl->last = new; 75*0Sstevel@tonic-gate if (id != NULL) 76*0Sstevel@tonic-gate id->opaque = new; 77*0Sstevel@tonic-gate if (ctx->debug >= 9) 78*0Sstevel@tonic-gate print_waits(ctx); 79*0Sstevel@tonic-gate return (0); 80*0Sstevel@tonic-gate } 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate /* 83*0Sstevel@tonic-gate * Mark runnable all waiting functions having a certain tag. 84*0Sstevel@tonic-gate */ 85*0Sstevel@tonic-gate int 86*0Sstevel@tonic-gate evDo(evContext opaqueCtx, const void *tag) { 87*0Sstevel@tonic-gate evContext_p *ctx = opaqueCtx.opaque; 88*0Sstevel@tonic-gate evWaitList *wl = evGetWaitList(ctx, tag, 0); 89*0Sstevel@tonic-gate evWait *first; 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate if (!wl) { 92*0Sstevel@tonic-gate errno = ENOENT; 93*0Sstevel@tonic-gate return (-1); 94*0Sstevel@tonic-gate } 95*0Sstevel@tonic-gate 96*0Sstevel@tonic-gate first = wl->first; 97*0Sstevel@tonic-gate INSIST(first != NULL); 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate if (ctx->waitDone.last != NULL) 100*0Sstevel@tonic-gate ctx->waitDone.last->next = first; 101*0Sstevel@tonic-gate else 102*0Sstevel@tonic-gate ctx->waitDone.first = first; 103*0Sstevel@tonic-gate ctx->waitDone.last = wl->last; 104*0Sstevel@tonic-gate evFreeWaitList(ctx, wl); 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate return (0); 107*0Sstevel@tonic-gate } 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate /* 110*0Sstevel@tonic-gate * Remove a waiting (or ready to run) function from the queue. 111*0Sstevel@tonic-gate */ 112*0Sstevel@tonic-gate int 113*0Sstevel@tonic-gate evUnwait(evContext opaqueCtx, evWaitID id) { 114*0Sstevel@tonic-gate evContext_p *ctx = opaqueCtx.opaque; 115*0Sstevel@tonic-gate evWait *this, *prev; 116*0Sstevel@tonic-gate evWaitList *wl; 117*0Sstevel@tonic-gate int found = 0; 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate this = id.opaque; 120*0Sstevel@tonic-gate INSIST(this != NULL); 121*0Sstevel@tonic-gate wl = evGetWaitList(ctx, this->tag, 0); 122*0Sstevel@tonic-gate if (wl != NULL) { 123*0Sstevel@tonic-gate for (prev = NULL, this = wl->first; 124*0Sstevel@tonic-gate this != NULL; 125*0Sstevel@tonic-gate prev = this, this = this->next) 126*0Sstevel@tonic-gate if (this == (evWait *)id.opaque) { 127*0Sstevel@tonic-gate found = 1; 128*0Sstevel@tonic-gate if (prev != NULL) 129*0Sstevel@tonic-gate prev->next = this->next; 130*0Sstevel@tonic-gate else 131*0Sstevel@tonic-gate wl->first = this->next; 132*0Sstevel@tonic-gate if (wl->last == this) 133*0Sstevel@tonic-gate wl->last = prev; 134*0Sstevel@tonic-gate if (wl->first == NULL) 135*0Sstevel@tonic-gate evFreeWaitList(ctx, wl); 136*0Sstevel@tonic-gate break; 137*0Sstevel@tonic-gate } 138*0Sstevel@tonic-gate } 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate if (!found) { 141*0Sstevel@tonic-gate /* Maybe it's done */ 142*0Sstevel@tonic-gate for (prev = NULL, this = ctx->waitDone.first; 143*0Sstevel@tonic-gate this != NULL; 144*0Sstevel@tonic-gate prev = this, this = this->next) 145*0Sstevel@tonic-gate if (this == (evWait *)id.opaque) { 146*0Sstevel@tonic-gate found = 1; 147*0Sstevel@tonic-gate if (prev != NULL) 148*0Sstevel@tonic-gate prev->next = this->next; 149*0Sstevel@tonic-gate else 150*0Sstevel@tonic-gate ctx->waitDone.first = this->next; 151*0Sstevel@tonic-gate if (ctx->waitDone.last == this) 152*0Sstevel@tonic-gate ctx->waitDone.last = prev; 153*0Sstevel@tonic-gate break; 154*0Sstevel@tonic-gate } 155*0Sstevel@tonic-gate } 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate if (!found) { 158*0Sstevel@tonic-gate errno = ENOENT; 159*0Sstevel@tonic-gate return (-1); 160*0Sstevel@tonic-gate } 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate FREE(this); 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate if (ctx->debug >= 9) 165*0Sstevel@tonic-gate print_waits(ctx); 166*0Sstevel@tonic-gate 167*0Sstevel@tonic-gate return (0); 168*0Sstevel@tonic-gate } 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate int 171*0Sstevel@tonic-gate evDefer(evContext opaqueCtx, evWaitFunc func, void *uap) { 172*0Sstevel@tonic-gate evContext_p *ctx = opaqueCtx.opaque; 173*0Sstevel@tonic-gate evWait *new; 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate OKNEW(new); 176*0Sstevel@tonic-gate new->func = func; 177*0Sstevel@tonic-gate new->uap = uap; 178*0Sstevel@tonic-gate new->tag = NULL; 179*0Sstevel@tonic-gate new->next = NULL; 180*0Sstevel@tonic-gate if (ctx->waitDone.last != NULL) 181*0Sstevel@tonic-gate ctx->waitDone.last->next = new; 182*0Sstevel@tonic-gate else 183*0Sstevel@tonic-gate ctx->waitDone.first = new; 184*0Sstevel@tonic-gate ctx->waitDone.last = new; 185*0Sstevel@tonic-gate if (ctx->debug >= 9) 186*0Sstevel@tonic-gate print_waits(ctx); 187*0Sstevel@tonic-gate return (0); 188*0Sstevel@tonic-gate } 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate /* Private. */ 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate static void 193*0Sstevel@tonic-gate print_waits(evContext_p *ctx) { 194*0Sstevel@tonic-gate evWaitList *wl; 195*0Sstevel@tonic-gate evWait *this; 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate evPrintf(ctx, 9, "wait waiting:\n"); 198*0Sstevel@tonic-gate for (wl = ctx->waitLists; wl != NULL; wl = wl->next) { 199*0Sstevel@tonic-gate INSIST(wl->first != NULL); 200*0Sstevel@tonic-gate evPrintf(ctx, 9, " tag %p:", wl->first->tag); 201*0Sstevel@tonic-gate for (this = wl->first; this != NULL; this = this->next) 202*0Sstevel@tonic-gate evPrintf(ctx, 9, " %p", this); 203*0Sstevel@tonic-gate evPrintf(ctx, 9, "\n"); 204*0Sstevel@tonic-gate } 205*0Sstevel@tonic-gate evPrintf(ctx, 9, "wait done:"); 206*0Sstevel@tonic-gate for (this = ctx->waitDone.first; this != NULL; this = this->next) 207*0Sstevel@tonic-gate evPrintf(ctx, 9, " %p", this); 208*0Sstevel@tonic-gate evPrintf(ctx, 9, "\n"); 209*0Sstevel@tonic-gate } 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate static evWaitList * 212*0Sstevel@tonic-gate evNewWaitList(evContext_p *ctx) { 213*0Sstevel@tonic-gate evWaitList *new; 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate NEW(new); 216*0Sstevel@tonic-gate if (new == NULL) 217*0Sstevel@tonic-gate return (NULL); 218*0Sstevel@tonic-gate new->first = new->last = NULL; 219*0Sstevel@tonic-gate new->prev = NULL; 220*0Sstevel@tonic-gate new->next = ctx->waitLists; 221*0Sstevel@tonic-gate if (new->next != NULL) 222*0Sstevel@tonic-gate new->next->prev = new; 223*0Sstevel@tonic-gate ctx->waitLists = new; 224*0Sstevel@tonic-gate return (new); 225*0Sstevel@tonic-gate } 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate static void 228*0Sstevel@tonic-gate evFreeWaitList(evContext_p *ctx, evWaitList *this) { 229*0Sstevel@tonic-gate 230*0Sstevel@tonic-gate INSIST(this != NULL); 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gate if (this->prev != NULL) 233*0Sstevel@tonic-gate this->prev->next = this->next; 234*0Sstevel@tonic-gate else 235*0Sstevel@tonic-gate ctx->waitLists = this->next; 236*0Sstevel@tonic-gate if (this->next != NULL) 237*0Sstevel@tonic-gate this->next->prev = this->prev; 238*0Sstevel@tonic-gate FREE(this); 239*0Sstevel@tonic-gate } 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate static evWaitList * 242*0Sstevel@tonic-gate evGetWaitList(evContext_p *ctx, const void *tag, int should_create) { 243*0Sstevel@tonic-gate evWaitList *this; 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate for (this = ctx->waitLists; this != NULL; this = this->next) { 246*0Sstevel@tonic-gate if (this->first != NULL && this->first->tag == tag) 247*0Sstevel@tonic-gate break; 248*0Sstevel@tonic-gate } 249*0Sstevel@tonic-gate if (this == NULL && should_create) 250*0Sstevel@tonic-gate this = evNewWaitList(ctx); 251*0Sstevel@tonic-gate return (this); 252*0Sstevel@tonic-gate } 253