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