|
|
1.1 ! root 1: /* $Header: /ker/coh.386/RCS/poll.c,v 2.2 93/07/26 14:29:00 nigel Exp $ */ ! 2: /* ! 3: * The information contained herein is a trade secret of INETCO ! 4: * Systems, and is confidential information. It is provided under ! 5: * a license agreement, and may be copied or disclosed only under ! 6: * the terms of that agreement. Any reproduction or disclosure of ! 7: * this material without the express written authorization of ! 8: * INETCO Systems or persuant to the license agreement is unlawful. ! 9: * ! 10: * Copyright (c) 1986 ! 11: * An unpublished work by INETCO Systems, Ltd. ! 12: * All rights reserved. ! 13: */ ! 14: ! 15: /* ! 16: * [Stream] Polling. ! 17: * ! 18: * void pollinit() -- allocate polling buffers ! 19: * int pollopen(qp) -- enable polling by current process on given queue ! 20: * int pollwake(qp) -- wake all processes waiting for poll on given queue ! 21: * int pollexit() -- terminate all polls enabled by current process ! 22: * event_t * ep; ! 23: * ! 24: * $Log: poll.c,v $ ! 25: * Revision 2.2 93/07/26 14:29:00 nigel ! 26: * Nigel's R80 ! 27: * ! 28: * Revision 1.3 93/04/14 10:06:42 root ! 29: * r75 ! 30: * ! 31: * Revision 1.2 92/01/06 11:59:56 hal ! 32: * Compile with cc.mwc. ! 33: * ! 34: * Revision 1.1 88/03/24 16:14:10 src ! 35: * Initial revision ! 36: * ! 37: * 86/11/19 Allan Cornish /usr/src/sys/coh/poll.c ! 38: * Ported to Coherent from RTX. ! 39: */ ! 40: ! 41: #include <sys/coherent.h> ! 42: #include <sys/proc.h> ! 43: ! 44: /* ! 45: * Patchable data. ! 46: */ ! 47: int NPOLL = 0; ! 48: ! 49: /* ! 50: * Private data. ! 51: */ ! 52: static event_t * efreep; ! 53: ! 54: /** ! 55: * ! 56: * event_t * ! 57: * pollinit() -- allocate event buffers. ! 58: */ ! 59: event_t * ! 60: pollinit() ! 61: { ! 62: register event_t * ep; ! 63: register event_t * ap; ! 64: static int first = 1; ! 65: ! 66: /* ! 67: * If dynamically growing event pool is specified [NPOLL == 0], ! 68: * try to allocate an additional cluster of 32 on each call. ! 69: */ ! 70: if (NPOLL == 0) { ! 71: if (ep = kalloc(32 * sizeof(event_t))) ! 72: ap = ep + 32; ! 73: } ! 74: ! 75: /* ! 76: * If statically sized event pool is specified [NPOLL != 0], ! 77: * try to allocate the pool on the first call. ! 78: */ ! 79: else if (first) { ! 80: first = 0; ! 81: if (ep = kalloc(NPOLL * sizeof(event_t))) ! 82: ap = ep + NPOLL; ! 83: } ! 84: ! 85: /* ! 86: * If event cluster was allocated, insert into free event queue. ! 87: */ ! 88: if (ep) { ! 89: do { ! 90: ep->e_pnext = efreep; ! 91: efreep = ep; ! 92: } while (++ep < ap); ! 93: } ! 94: ! 95: return efreep; ! 96: } ! 97: ! 98: /** ! 99: * ! 100: * int ! 101: * pollopen(qp) -- enable polling by current process on given event queue ! 102: * event_t * qp; ! 103: */ ! 104: void ! 105: pollopen(qp) ! 106: register event_t * qp; ! 107: { ! 108: register event_t * ep; ! 109: ! 110: /* ! 111: * Initialize device queue if required. ! 112: */ ! 113: if (qp->e_dnext == 0) ! 114: qp->e_dnext = qp->e_dlast = qp; ! 115: ! 116: /* ! 117: * Obtain a free event buffer, or return. ! 118: */ ! 119: if (((ep = efreep) == 0) && ((ep = pollinit()) == 0)) { ! 120: printf("out of poll buffers\n"); ! 121: return; ! 122: } ! 123: ! 124: /* ! 125: * Remove event buffer from free queue. ! 126: */ ! 127: efreep = ep->e_pnext; ! 128: ! 129: /* ! 130: * Record process pointer in event buffer. ! 131: */ ! 132: ep->e_procp = cprocp; ! 133: ! 134: /* ! 135: * Insert event at head of process event singularly-linked queue. ! 136: */ ! 137: ep->e_pnext = cprocp->p_polls; ! 138: cprocp->p_polls = ep; ! 139: ! 140: /* ! 141: * Insert event at tail of circularly-linked device queue. ! 142: * This ensures that processes are first-in first-out. ! 143: */ ! 144: ep->e_dnext = qp; ! 145: (ep->e_dlast = qp->e_dlast)->e_dnext = ep; ! 146: qp->e_dlast = ep; ! 147: ! 148: /* ! 149: * Record last process to enable polling on device. ! 150: */ ! 151: qp->e_procp = cprocp; ! 152: } ! 153: ! 154: /** ! 155: * ! 156: * int ! 157: * pollwake(qp) -- wake all processes waiting for poll on given queue ! 158: * event_t * qp; ! 159: * ! 160: * Go through extra step of deferring the pollwake to avoid race condition ! 161: * (in case interrupt handler does a pollwake() during upoll()). ! 162: */ ! 163: void ! 164: pollwake(qp) ! 165: event_t * qp; ! 166: { ! 167: void dpollwake(); ! 168: ! 169: defer(dpollwake, qp); ! 170: } ! 171: ! 172: void ! 173: dpollwake(qp) ! 174: event_t * qp; ! 175: { ! 176: register event_t * ep = qp; ! 177: register PROC * pp; ! 178: ! 179: /* ! 180: * Clear device process pointer, indicating poll completed. ! 181: * NOTE: interrupt handlers may have already cleared it. ! 182: */ ! 183: qp->e_procp = 0; ! 184: ! 185: if (ep = qp->e_dnext) { ! 186: ! 187: /* ! 188: * Service circularly-linked polls on device queue. ! 189: */ ! 190: while (ep != qp) { ! 191: /* ! 192: * Wake process if it is sleeping. ! 193: */ ! 194: if ((pp = ep->e_procp) && ASLEEP(pp)) ! 195: wakeup(&pp->p_polls); ! 196: ! 197: ep = ep->e_dnext; ! 198: } ! 199: } ! 200: } ! 201: ! 202: /** ! 203: * ! 204: * int ! 205: * pollexit() -- terminate all polls opened by current process ! 206: */ ! 207: int ! 208: pollexit() ! 209: { ! 210: register PROC * pp = cprocp; ! 211: register event_t * ep; ! 212: ! 213: /* ! 214: * Service all polling event buffers enabled by current process. ! 215: */ ! 216: while (ep = pp->p_polls) { ! 217: ! 218: /* ! 219: * Remove event buffer from circularly-linked device queue. ! 220: */ ! 221: (ep->e_dnext->e_dlast = ep->e_dlast)->e_dnext = ep->e_dnext; ! 222: ! 223: /* ! 224: * Remove event buffer from singularly-linked process queue. ! 225: */ ! 226: pp->p_polls = ep->e_pnext; ! 227: ! 228: /* ! 229: * Insert event buffer at head of free event buffer queue. ! 230: */ ! 231: ep->e_pnext = efreep; ! 232: efreep = ep; ! 233: } ! 234: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.