17c478bd9Sstevel@tonic-gate /* 2*9525b14bSRao Shoaib * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 37c478bd9Sstevel@tonic-gate * Copyright (c) 1996-1999 by Internet Software Consortium 47c478bd9Sstevel@tonic-gate * 57c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any 67c478bd9Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 77c478bd9Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 87c478bd9Sstevel@tonic-gate * 9*9525b14bSRao Shoaib * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 10*9525b14bSRao Shoaib * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11*9525b14bSRao Shoaib * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 12*9525b14bSRao Shoaib * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13*9525b14bSRao Shoaib * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14*9525b14bSRao Shoaib * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 15*9525b14bSRao Shoaib * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 167c478bd9Sstevel@tonic-gate */ 177c478bd9Sstevel@tonic-gate 187c478bd9Sstevel@tonic-gate /* ev_waits.c - implement deferred function calls for the eventlib 197c478bd9Sstevel@tonic-gate * vix 05dec95 [initial] 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate 227c478bd9Sstevel@tonic-gate #if !defined(LINT) && !defined(CODECENTER) 23*9525b14bSRao Shoaib static const char rcsid[] = "$Id: ev_waits.c,v 1.4 2005/04/27 04:56:36 sra Exp $"; 247c478bd9Sstevel@tonic-gate #endif 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include "port_before.h" 277c478bd9Sstevel@tonic-gate #include "fd_setsize.h" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <errno.h> 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include <isc/eventlib.h> 327c478bd9Sstevel@tonic-gate #include <isc/assertions.h> 337c478bd9Sstevel@tonic-gate #include "eventlib_p.h" 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate #include "port_after.h" 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate /* Forward. */ 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate static void print_waits(evContext_p *ctx); 407c478bd9Sstevel@tonic-gate static evWaitList * evNewWaitList(evContext_p *); 417c478bd9Sstevel@tonic-gate static void evFreeWaitList(evContext_p *, evWaitList *); 427c478bd9Sstevel@tonic-gate static evWaitList * evGetWaitList(evContext_p *, const void *, int); 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate /* Public. */ 467c478bd9Sstevel@tonic-gate 47*9525b14bSRao Shoaib /*% 487c478bd9Sstevel@tonic-gate * Enter a new wait function on the queue. 497c478bd9Sstevel@tonic-gate */ 507c478bd9Sstevel@tonic-gate int 517c478bd9Sstevel@tonic-gate evWaitFor(evContext opaqueCtx, const void *tag, 527c478bd9Sstevel@tonic-gate evWaitFunc func, void *uap, evWaitID *id) 537c478bd9Sstevel@tonic-gate { 547c478bd9Sstevel@tonic-gate evContext_p *ctx = opaqueCtx.opaque; 557c478bd9Sstevel@tonic-gate evWait *new; 567c478bd9Sstevel@tonic-gate evWaitList *wl = evGetWaitList(ctx, tag, 1); 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate OKNEW(new); 597c478bd9Sstevel@tonic-gate new->func = func; 607c478bd9Sstevel@tonic-gate new->uap = uap; 617c478bd9Sstevel@tonic-gate new->tag = tag; 627c478bd9Sstevel@tonic-gate new->next = NULL; 637c478bd9Sstevel@tonic-gate if (wl->last != NULL) 647c478bd9Sstevel@tonic-gate wl->last->next = new; 657c478bd9Sstevel@tonic-gate else 667c478bd9Sstevel@tonic-gate wl->first = new; 677c478bd9Sstevel@tonic-gate wl->last = new; 687c478bd9Sstevel@tonic-gate if (id != NULL) 697c478bd9Sstevel@tonic-gate id->opaque = new; 707c478bd9Sstevel@tonic-gate if (ctx->debug >= 9) 717c478bd9Sstevel@tonic-gate print_waits(ctx); 727c478bd9Sstevel@tonic-gate return (0); 737c478bd9Sstevel@tonic-gate } 747c478bd9Sstevel@tonic-gate 75*9525b14bSRao Shoaib /*% 767c478bd9Sstevel@tonic-gate * Mark runnable all waiting functions having a certain tag. 777c478bd9Sstevel@tonic-gate */ 787c478bd9Sstevel@tonic-gate int 797c478bd9Sstevel@tonic-gate evDo(evContext opaqueCtx, const void *tag) { 807c478bd9Sstevel@tonic-gate evContext_p *ctx = opaqueCtx.opaque; 817c478bd9Sstevel@tonic-gate evWaitList *wl = evGetWaitList(ctx, tag, 0); 827c478bd9Sstevel@tonic-gate evWait *first; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate if (!wl) { 857c478bd9Sstevel@tonic-gate errno = ENOENT; 867c478bd9Sstevel@tonic-gate return (-1); 877c478bd9Sstevel@tonic-gate } 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate first = wl->first; 907c478bd9Sstevel@tonic-gate INSIST(first != NULL); 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate if (ctx->waitDone.last != NULL) 937c478bd9Sstevel@tonic-gate ctx->waitDone.last->next = first; 947c478bd9Sstevel@tonic-gate else 957c478bd9Sstevel@tonic-gate ctx->waitDone.first = first; 967c478bd9Sstevel@tonic-gate ctx->waitDone.last = wl->last; 977c478bd9Sstevel@tonic-gate evFreeWaitList(ctx, wl); 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate return (0); 1007c478bd9Sstevel@tonic-gate } 1017c478bd9Sstevel@tonic-gate 102*9525b14bSRao Shoaib /*% 1037c478bd9Sstevel@tonic-gate * Remove a waiting (or ready to run) function from the queue. 1047c478bd9Sstevel@tonic-gate */ 1057c478bd9Sstevel@tonic-gate int 1067c478bd9Sstevel@tonic-gate evUnwait(evContext opaqueCtx, evWaitID id) { 1077c478bd9Sstevel@tonic-gate evContext_p *ctx = opaqueCtx.opaque; 1087c478bd9Sstevel@tonic-gate evWait *this, *prev; 1097c478bd9Sstevel@tonic-gate evWaitList *wl; 1107c478bd9Sstevel@tonic-gate int found = 0; 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate this = id.opaque; 1137c478bd9Sstevel@tonic-gate INSIST(this != NULL); 1147c478bd9Sstevel@tonic-gate wl = evGetWaitList(ctx, this->tag, 0); 1157c478bd9Sstevel@tonic-gate if (wl != NULL) { 1167c478bd9Sstevel@tonic-gate for (prev = NULL, this = wl->first; 1177c478bd9Sstevel@tonic-gate this != NULL; 1187c478bd9Sstevel@tonic-gate prev = this, this = this->next) 1197c478bd9Sstevel@tonic-gate if (this == (evWait *)id.opaque) { 1207c478bd9Sstevel@tonic-gate found = 1; 1217c478bd9Sstevel@tonic-gate if (prev != NULL) 1227c478bd9Sstevel@tonic-gate prev->next = this->next; 1237c478bd9Sstevel@tonic-gate else 1247c478bd9Sstevel@tonic-gate wl->first = this->next; 1257c478bd9Sstevel@tonic-gate if (wl->last == this) 1267c478bd9Sstevel@tonic-gate wl->last = prev; 1277c478bd9Sstevel@tonic-gate if (wl->first == NULL) 1287c478bd9Sstevel@tonic-gate evFreeWaitList(ctx, wl); 1297c478bd9Sstevel@tonic-gate break; 1307c478bd9Sstevel@tonic-gate } 1317c478bd9Sstevel@tonic-gate } 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate if (!found) { 1347c478bd9Sstevel@tonic-gate /* Maybe it's done */ 1357c478bd9Sstevel@tonic-gate for (prev = NULL, this = ctx->waitDone.first; 1367c478bd9Sstevel@tonic-gate this != NULL; 1377c478bd9Sstevel@tonic-gate prev = this, this = this->next) 1387c478bd9Sstevel@tonic-gate if (this == (evWait *)id.opaque) { 1397c478bd9Sstevel@tonic-gate found = 1; 1407c478bd9Sstevel@tonic-gate if (prev != NULL) 1417c478bd9Sstevel@tonic-gate prev->next = this->next; 1427c478bd9Sstevel@tonic-gate else 1437c478bd9Sstevel@tonic-gate ctx->waitDone.first = this->next; 1447c478bd9Sstevel@tonic-gate if (ctx->waitDone.last == this) 1457c478bd9Sstevel@tonic-gate ctx->waitDone.last = prev; 1467c478bd9Sstevel@tonic-gate break; 1477c478bd9Sstevel@tonic-gate } 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate if (!found) { 1517c478bd9Sstevel@tonic-gate errno = ENOENT; 1527c478bd9Sstevel@tonic-gate return (-1); 1537c478bd9Sstevel@tonic-gate } 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate FREE(this); 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate if (ctx->debug >= 9) 1587c478bd9Sstevel@tonic-gate print_waits(ctx); 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate return (0); 1617c478bd9Sstevel@tonic-gate } 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate int 1647c478bd9Sstevel@tonic-gate evDefer(evContext opaqueCtx, evWaitFunc func, void *uap) { 1657c478bd9Sstevel@tonic-gate evContext_p *ctx = opaqueCtx.opaque; 1667c478bd9Sstevel@tonic-gate evWait *new; 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate OKNEW(new); 1697c478bd9Sstevel@tonic-gate new->func = func; 1707c478bd9Sstevel@tonic-gate new->uap = uap; 1717c478bd9Sstevel@tonic-gate new->tag = NULL; 1727c478bd9Sstevel@tonic-gate new->next = NULL; 1737c478bd9Sstevel@tonic-gate if (ctx->waitDone.last != NULL) 1747c478bd9Sstevel@tonic-gate ctx->waitDone.last->next = new; 1757c478bd9Sstevel@tonic-gate else 1767c478bd9Sstevel@tonic-gate ctx->waitDone.first = new; 1777c478bd9Sstevel@tonic-gate ctx->waitDone.last = new; 1787c478bd9Sstevel@tonic-gate if (ctx->debug >= 9) 1797c478bd9Sstevel@tonic-gate print_waits(ctx); 1807c478bd9Sstevel@tonic-gate return (0); 1817c478bd9Sstevel@tonic-gate } 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate /* Private. */ 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate static void 1867c478bd9Sstevel@tonic-gate print_waits(evContext_p *ctx) { 1877c478bd9Sstevel@tonic-gate evWaitList *wl; 1887c478bd9Sstevel@tonic-gate evWait *this; 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate evPrintf(ctx, 9, "wait waiting:\n"); 1917c478bd9Sstevel@tonic-gate for (wl = ctx->waitLists; wl != NULL; wl = wl->next) { 1927c478bd9Sstevel@tonic-gate INSIST(wl->first != NULL); 1937c478bd9Sstevel@tonic-gate evPrintf(ctx, 9, " tag %p:", wl->first->tag); 1947c478bd9Sstevel@tonic-gate for (this = wl->first; this != NULL; this = this->next) 1957c478bd9Sstevel@tonic-gate evPrintf(ctx, 9, " %p", this); 1967c478bd9Sstevel@tonic-gate evPrintf(ctx, 9, "\n"); 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate evPrintf(ctx, 9, "wait done:"); 1997c478bd9Sstevel@tonic-gate for (this = ctx->waitDone.first; this != NULL; this = this->next) 2007c478bd9Sstevel@tonic-gate evPrintf(ctx, 9, " %p", this); 2017c478bd9Sstevel@tonic-gate evPrintf(ctx, 9, "\n"); 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate static evWaitList * 2057c478bd9Sstevel@tonic-gate evNewWaitList(evContext_p *ctx) { 2067c478bd9Sstevel@tonic-gate evWaitList *new; 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate NEW(new); 2097c478bd9Sstevel@tonic-gate if (new == NULL) 2107c478bd9Sstevel@tonic-gate return (NULL); 2117c478bd9Sstevel@tonic-gate new->first = new->last = NULL; 2127c478bd9Sstevel@tonic-gate new->prev = NULL; 2137c478bd9Sstevel@tonic-gate new->next = ctx->waitLists; 2147c478bd9Sstevel@tonic-gate if (new->next != NULL) 2157c478bd9Sstevel@tonic-gate new->next->prev = new; 2167c478bd9Sstevel@tonic-gate ctx->waitLists = new; 2177c478bd9Sstevel@tonic-gate return (new); 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate static void 2217c478bd9Sstevel@tonic-gate evFreeWaitList(evContext_p *ctx, evWaitList *this) { 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate INSIST(this != NULL); 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate if (this->prev != NULL) 2267c478bd9Sstevel@tonic-gate this->prev->next = this->next; 2277c478bd9Sstevel@tonic-gate else 2287c478bd9Sstevel@tonic-gate ctx->waitLists = this->next; 2297c478bd9Sstevel@tonic-gate if (this->next != NULL) 2307c478bd9Sstevel@tonic-gate this->next->prev = this->prev; 2317c478bd9Sstevel@tonic-gate FREE(this); 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate static evWaitList * 2357c478bd9Sstevel@tonic-gate evGetWaitList(evContext_p *ctx, const void *tag, int should_create) { 2367c478bd9Sstevel@tonic-gate evWaitList *this; 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate for (this = ctx->waitLists; this != NULL; this = this->next) { 2397c478bd9Sstevel@tonic-gate if (this->first != NULL && this->first->tag == tag) 2407c478bd9Sstevel@tonic-gate break; 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate if (this == NULL && should_create) 2437c478bd9Sstevel@tonic-gate this = evNewWaitList(ctx); 2447c478bd9Sstevel@tonic-gate return (this); 2457c478bd9Sstevel@tonic-gate } 246*9525b14bSRao Shoaib 247*9525b14bSRao Shoaib /*! \file */ 248