|
|
1.1 root 1: /* $Header: /ker/coh.386/RCS/pipe.c,v 2.2 93/07/26 14:28:58 nigel Exp $ */
2: /* (lgl-
3: * The information contained herein is a trade secret of Mark Williams
4: * Company, and is confidential information. It is provided under a
5: * license agreement, and may be copied or disclosed only under the
6: * terms of that agreement. Any reproduction or disclosure of this
7: * material without the express written authorization of Mark Williams
8: * Company or persuant to the license agreement is unlawful.
9: *
10: * COHERENT Version 2.3.37
11: * Copyright (c) 1982, 1983, 1984.
12: * An unpublished work by Mark Williams Company, Chicago.
13: * All rights reserved.
14: -lgl) */
15: /*
16: * Coherent.
17: * Pipes.
18: *
19: * $Log: pipe.c,v $
20: * Revision 2.2 93/07/26 14:28:58 nigel
21: * Nigel's R80
22: *
23: * Revision 1.7 93/04/14 10:06:40 root
24: * r75
25: *
26: * Revision 1.2 92/01/06 11:59:52 hal
27: * Compile with cc.mwc.
28: *
29: * Revision 1.1 88/03/24 16:14:07 src
30: * Initial revision
31: *
32: * 86/11/19 Allan Cornish /usr/src/sys/coh/pipe.c
33: * Added check for non-blocking read and write if (io_flag & IPNDLY) set.
34: * Eliminated use of i_a inode field since now included in inode macros.
35: */
36:
37: #include <kernel/_sleep.h>
38: #include <sys/coherent.h>
39: #include <sys/errno.h>
40: #include <sys/filsys.h>
41: #include <sys/ino.h>
42: #include <sys/inode.h>
43: #include <sys/io.h>
44: #include <sys/proc.h>
45: #include <sys/sched.h>
46: #include <sys/file.h>
47: #include <signal.h>
48:
49: /*
50: * These are nothing more than random different values at this point!
51: * Historically, these were bit's or'ed into ip->i_flag, no more!
52: */
53:
54: #define IFWFR 1 /* Sleeping Waiting for a Reader */
55: #define IFWFW 2 /* Sleeping Waiting for a Writer */
56:
57:
58: /*
59: * pmake(mode) -- called from the upipe() system call in sys3.c
60: *
61: * Creates and returns a locked pipe inode with the given mode on
62: * the pipedev.
63: */
64:
65: INODE *
66: pmake(mode)
67: {
68: register INODE *ip;
69:
70: if ((ip = ialloc (pipedev, IFPIPE | mode)) != NULL)
71: pclear (ip);
72: pdump ("M", ip, mode);
73: return ip;
74: }
75:
76: pclear(ip)
77: register INODE *ip;
78: {
79: ip->i_pnc =
80: ip->i_prx =
81: ip->i_pwx =
82: ip->i_par =
83: ip->i_paw =
84: ip->i_psr =
85: ip->i_psw = 0;
86: ip->i_iev.e_pnext =
87: ip->i_iev.e_dnext =
88: ip->i_iev.e_dlast =
89: ip->i_iev.e_procp =
90: ip->i_oev.e_pnext =
91: ip->i_oev.e_dnext =
92: ip->i_oev.e_dlast =
93: ip->i_oev.e_procp = NULL;
94: }
95:
96: /*
97: * popen(ip, mode) -- Opens a pipe inode, with the given mode.
98: * Note: The inode is locked upon entry.
99: *
100: * This routine follows the requirements concerning opening pipes.
101: * Specifically, if opening readonly without O_NDELAY, then block
102: * until we have a writer. If opening readonly with O_NDELAY, then
103: * return opened, no blocking. If opening writeonly without O_NDELAY,
104: * then block until we have a reader. If opening writeonly with
105: * O_NDELAY, then return an error, and set u.u_errno to ENXIO.
106: * Beware of subtle race conditions! Also notice, I followed hal's
107: * style of no internal returns in a function.
108: *
109: * Note: these pipe routines maintain the pipe counter variables:
110: * ip->i_par: Number of Awake readers
111: * ip->i_paw: Number of Awake writers
112: * ip->i_psr: Number of Sleeping readers
113: * ip->i_psw: Number of Sleeping writers
114: */
115:
116: popen(ip, mode)
117: register INODE *ip;
118: {
119: pdump ("OA", ip, mode);
120: switch (mode & (IPR | IPW)) {
121: case IPR:
122: ++ip->i_par;
123: while (! ip->i_paw && ! ip->i_psw) {
124: if (mode & (IPNDLY | IPNONBLOCK))
125: break;
126: else {
127: if (psleep (ip, IFWFW) < 0) {
128: -- ip->i_par;
129: goto popen_done;
130: }
131: if (ip->i_pnc != 0)
132: break;
133: }
134: }
135: pwake (ip, IFWFR);
136: break;
137:
138: case IPW:
139: ++ ip->i_paw;
140: if (! ip->i_par && ! ip->i_psr) {
141: if (mode & (IPNDLY | IPNONBLOCK)) {
142: u.u_error = ENXIO;
143: -- ip->i_paw;
144: goto popen_done;
145: } else {
146: if (psleep (ip, IFWFR) < 0) {
147: -- ip->i_paw;
148: goto popen_done;
149: }
150: }
151: }
152: pwake (ip, IFWFW);
153: break;
154:
155: case IPR | IPW:
156: ++ ip->i_par;
157: ++ ip->i_paw;
158: pwake (ip, IFWFW);
159: pwake (ip, IFWFR);
160: break;
161: }
162:
163: popen_done:
164: pdump ("OZ", ip, mode);
165: return;
166: }
167:
168:
169: /*
170: * pclose(ip, mode) -- Opens a pipe inode, with the given mode.
171: * Note: The inode is locked upon entry.
172: *
173: * This routine closes the given INODE with the given mode. We
174: * must have the mode correct to maintain counters properly.
175: * Good thing that mode cannot be changed by fcntl()!
176: */
177:
178: pclose(ip, mode)
179: register INODE *ip;
180: {
181: pdump ("CA", ip, mode);
182: pwake (ip, IFWFR);
183: pwake (ip, IFWFW);
184: if (mode & IPR)
185: if (-- ip->i_par < 0)
186: panic ("Out of sync IPR in pclose");
187: if (mode & IPW)
188: if (-- ip->i_paw < 0)
189: panic ("Out of sync IPW in pclose");
190:
191: if (! ip->i_paw && ! ip->i_psw && ! ip->i_par && ! ip->i_psr)
192: pclear (ip);
193: pdump ("CZ", ip, mode);
194: }
195:
196:
197: /*
198: * pread(ip, iop) -- Reads from a pipe inode, accoring to the IO info.
199: * Note: The inode is locked upon entry.
200: *
201: * This routine follows the requirements concerning reading from pipes.
202: * Specifically, if there is no data in the pipe, then the read will
203: * block waiting for data, unless you have IONDLY set in which case
204: * it will simply return zero. Notice, the traditional value returned
205: * from uread() is the number of characters actually read. This is
206: * nothing more that iop->io_ioc on entry minus iop->io_ioc on exit.
207: * This routine also works with the ring buffer in the inode maintained
208: * by the variables ip->i_pnc: Number of Characters in pipe.
209: * ip->i_prx: Offset in pipe to begin reading.
210: * ip->i_pwx: Offset in pipe to begin writing.
211: * Notice: we do not unlock the inode when we call fread(), this is to
212: * guarantee that we read all that is available even if we go to sleep.
213: * Subtle race condition? I don't think so, since if we go to sleep
214: * in fread(), it's wrt a resource unrelated to this particular INODE.
215: */
216:
217: pread(ip, iop)
218: register INODE *ip;
219: register IO *iop;
220: {
221: register unsigned n;
222: register unsigned ioc;
223:
224: pdump ("R", ip, 0);
225: while (ip->i_pnc == 0) {
226: /*
227: * If we are in O_NDELAY mode, just return and uread () will
228: * see nothing read, returning 0 to the user.
229: */
230: if ((iop->io_flag & IONDLY) != 0)
231: goto pread_done;
232: /*
233: * If we are in O_NONBLOCK mode, set u.u_error so that upon
234: * returning to user level the return value of uread () gets
235: * forced to -1. Layering? What layering?
236: */
237: if ((iop->io_flag & IONONBLOCK) != 0) {
238: u.u_error = EAGAIN;
239: goto pread_done;
240: }
241: if (! ip->i_paw && ! ip->i_psw)
242: goto pread_done;
243: if (psleep (ip, IFWFW) < 0)
244: goto pread_done;
245: }
246:
247: ioc = iop->io_ioc;
248: while (! u.u_error && ioc > 0 && ip->i_pnc > 0) {
249: if ((n = (PIPSIZE - ip->i_prx)) > ioc)
250: n = ioc;
251: if (n > ip->i_pnc)
252: n = ip->i_pnc;
253: iop->io_ioc = n;
254: iop->io_seek = ip->i_prx;
255: fread (ip, iop);
256: n -= iop->io_ioc;
257: if ((ip->i_prx += n) == PIPSIZE)
258: ip->i_prx = 0;
259: if ((ip->i_pnc -= n) == 0) {
260: ip->i_prx =
261: ip->i_pwx = 0;
262: }
263: ioc -= n;
264: }
265: iop->io_ioc = ioc;
266:
267: if (ip->i_pnc < PIPSIZE)
268: pwake (ip, IFWFR);
269:
270: pread_done:
271: return;
272: }
273:
274:
275: /*
276: * pwrite(ip, iop) -- Writes to a pipe inode, according to the IO info.
277: * Note: The inode is locked upon entry.
278: *
279: * This routine follows the requirements concerning writing to pipes.
280: * Specifically, if the pipe is full, then the write will block waiting
281: * for data to be consumed, unless you have IONDLY set in which case
282: * it will simply return zero. Notice, the traditional value returned
283: * from uwrite() is the number of characters actually written. This is
284: * nothing more that iop->io_ioc on entry minus iop->io_ioc on exit.
285: * In other words, iop->io_ioc had better be zero on exit. The possibility
286: * does exist if the number of characters to be written is larger than
287: * PIPSIZE, and thus we do not guarantee atomic writes, that while the
288: * process is sleeping waiting for a reader to consume data, that the
289: * process will be woken from sleeping by a SIGNAL, thus causing a partial
290: * write. The return value will be the actual number of character written.
291: * This routine also works with the ring buffer in the inode maintained
292: * by the variables ip->i_pnc: Number of Characters in pipe.
293: * ip->i_prx: Offset in pipe to begin reading.
294: * ip->i_pwx: Offset in pipe to begin writing.
295: * Notice: we do not unlock the inode when we call fwrite(), this is to
296: * guarantee that we have an atomic write for all writes of size less
297: * than PIPSIZE, even if we go to sleep in the fwrite(). Subtle race
298: * condition? I don't think so, since if we go to sleep in fwrite(),
299: * it's wrt a resource unrelated to this particular INODE.
300: */
301:
302: pwrite(ip, iop)
303: register INODE *ip;
304: register IO *iop;
305: {
306: register unsigned n;
307: register unsigned ioc;
308:
309: pdump ("W", ip, 0);
310: ioc = iop->io_ioc;
311: while (! u.u_error && (ioc > 0)) {
312: if (! ip->i_par && ! ip->i_psr) {
313: u.u_error = EPIPE;
314: sendsig (SIGPIPE, SELF);
315: goto pwrite_done;
316: }
317: if ((n = PIPSIZE - ip->i_pwx) > ioc)
318: n = ioc;
319: if (n > PIPSIZE - ip->i_pnc)
320: n = PIPSIZE - ip->i_pnc;
321: if (n == 0 || (ioc <= PIPSIZE && n != ioc)) {
322: /*
323: * If we are in O_NDELAY mode, just return and all
324: * uwrite () will see is 0 bytes written.
325: */
326: if ((iop->io_flag & IONDLY) != 0)
327: goto pwrite_done;
328: /*
329: * If we are in O_NONBLOCK mode, set u.u_error so that
330: * the return from system-call code will force the
331: * return value of uwrite () to -1.
332: */
333: if ((iop->io_flag & IONONBLOCK) != 0) {
334: u.u_error = EAGAIN;
335: goto pwrite_done;
336: }
337: if (psleep (ip, IFWFR) < 0)
338: goto pwrite_done;
339: continue;
340: }
341: iop->io_ioc = n;
342: iop->io_seek = ip->i_pwx;
343: fwrite (ip, iop);
344: n -= iop->io_ioc;
345: if ((ip->i_pwx += n) == PIPSIZE)
346: ip->i_pwx = 0;
347: ip->i_pnc += n;
348: ioc -= n;
349:
350: if (ip->i_pnc > 0)
351: pwake (ip, IFWFW);
352: }
353: pwrite_done:
354: iop->io_ioc = ioc;
355: }
356:
357:
358: /*
359: * psleep(ip, who) -- go to sleep either waiting for a reader if (who==IFWFR)
360: * or waiting for a writer if (who==IFWFW).
361: * Returns: 0 if woke up ok
362: * -1 if woke up by signal (e.g. SIGALRM, SIGKILL, etc.)
363: */
364:
365: psleep(ip, who)
366: register INODE *ip;
367: {
368: __sleep_t sleep;
369:
370: pdump ("SA", ip, 0);
371: iunlock (ip);
372: switch (who) {
373: case IFWFW:
374: -- ip->i_par; ++ ip->i_psr;
375: sleep = x_sleep ((char *) & ip->i_psw, primed, slpriSigCatch,
376: "pipe wx");
377: ++ ip->i_par; -- ip->i_psr;
378: break;
379:
380: case IFWFR:
381: -- ip->i_paw; ++ ip->i_psw;
382: sleep = x_sleep ((char *) & ip->i_psr, primed, slpriSigCatch,
383: "pipe rx");
384: ++ ip->i_paw; -- ip->i_psw;
385: break;
386:
387: default:
388: panic ("psleep() internal error");
389: }
390: ilock (ip);
391: pdump ("SZ", ip, 0);
392:
393: if (sleep == PROCESS_SIGNALLED) {
394: u.u_error = EINTR;
395: return -1;
396: }
397: return 0;
398: }
399:
400:
401: /*
402: * pwake(ip, who) -- wake up processes which are waiting for a reader if
403: * (who==IFWFR) or waiting for a writer if (who==IFWFW).
404: */
405:
406: pwake(ip, who)
407: register INODE *ip;
408: {
409: pdump ("KA", ip, 0);
410: switch (who) {
411: case IFWFW:
412: if (ip->i_psr)
413: wakeup ((char *) & ip->i_psw);
414: if (ip->i_pnc > 0)
415: pollwake (& ip->i_iev);
416: break;
417:
418: case IFWFR:
419: if (ip->i_psw)
420: wakeup ((char *) & ip->i_psr);
421: if (ip->i_pnc < PIPSIZE && (ip->i_par || ip->i_psr) )
422: pollwake (& ip->i_oev);
423: break;
424:
425: default:
426: panic ("pwake() internal error");
427: }
428: pdump ("KZ", ip, 0);
429: }
430:
431:
432: /*
433: * ppoll(ip, ev) -- Poll the given pipe inode.
434: * INODE *ip -- The inode in question.
435: * int ev -- The event bit field.
436: * int msec -- Number of msecs to wait.
437: * Returns or'ed bits according to the following rules:
438: * POLLIN: indicates input is available for reading, notice it is possible
439: * to read even if there are no more writers anywhere!
440: * POLLOUT: indicates room in pipe for new output, notice it is not possible
441: * to write unless there is a reader attached!
442: *
443: * No priority polls are supported.
444: */
445:
446: ppoll(ip, ev, msec)
447: register INODE *ip;
448: int ev, msec;
449: {
450: register int rval = 0;
451:
452: if (ev & POLLIN) {
453: if (ip->i_pnc > 0)
454: rval |= POLLIN;
455: else if (msec != 0)
456: pollopen (& ip->i_iev);
457: }
458: if (ev & POLLOUT) {
459: if (ip->i_pnc < PIPSIZE && (ip->i_par || ip->i_psr))
460: rval |= POLLOUT;
461: else if (msec != 0)
462: pollopen (& ip->i_oev);
463: }
464: return rval;
465: }
466:
467: /*
468: * pdump(loc, ip, mode) -- A kernel debugging output line.
469: * char *loc -- prefix of line (two characters indicating where we are)
470: * INODE *ip -- The inode information to dump
471: * int mode -- The mode of the IO call, i.e. IPW, IPR, IPNDLY, ...
472: */
473:
474: #if 1
475: pdump()
476: {}
477: #else
478: pdump(loc, ip, mode)
479: char *loc;
480: register INODE *ip;
481: int mode;
482: {
483: printf("%s ip=%x mde=%x nlk=%x rf=%x nc=%x rx=%x wx=%x",
484: loc, ip, mode, ip->i_nlink, ip->i_refc,
485: ip->i_pnc, ip->i_prx, ip->i_pwx);
486:
487: printf(" ar=%x aw=%x sr=%x sw=%x f=%x\n",
488: ip->i_par, ip->i_paw, ip->i_psr, ip->i_psw, ip->i_flag);
489: }
490: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.