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