This source file includes following definitions.
- sys_opipe
- pipespace
- pipe_create
- pipelock
- pipeunlock
- pipeselwakeup
- pipe_read
- pipe_write
- pipe_ioctl
- pipe_poll
- pipe_stat
- pipe_close
- pipe_free_kmem
- pipeclose
- pipe_kqfilter
- filt_pipedetach
- filt_piperead
- filt_pipewrite
- pipe_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/proc.h>
32 #include <sys/file.h>
33 #include <sys/filedesc.h>
34 #include <sys/pool.h>
35 #include <sys/ioctl.h>
36 #include <sys/stat.h>
37 #include <sys/signalvar.h>
38 #include <sys/mount.h>
39 #include <sys/syscallargs.h>
40 #include <sys/event.h>
41 #include <sys/lock.h>
42 #include <sys/poll.h>
43
44 #include <uvm/uvm_extern.h>
45
46 #include <sys/pipe.h>
47
48
49
50
51 int pipe_read(struct file *, off_t *, struct uio *, struct ucred *);
52 int pipe_write(struct file *, off_t *, struct uio *, struct ucred *);
53 int pipe_close(struct file *, struct proc *);
54 int pipe_poll(struct file *, int events, struct proc *);
55 int pipe_kqfilter(struct file *fp, struct knote *kn);
56 int pipe_ioctl(struct file *, u_long, caddr_t, struct proc *);
57 int pipe_stat(struct file *fp, struct stat *ub, struct proc *p);
58
59 static struct fileops pipeops = {
60 pipe_read, pipe_write, pipe_ioctl, pipe_poll, pipe_kqfilter,
61 pipe_stat, pipe_close
62 };
63
64 void filt_pipedetach(struct knote *kn);
65 int filt_piperead(struct knote *kn, long hint);
66 int filt_pipewrite(struct knote *kn, long hint);
67
68 struct filterops pipe_rfiltops =
69 { 1, NULL, filt_pipedetach, filt_piperead };
70 struct filterops pipe_wfiltops =
71 { 1, NULL, filt_pipedetach, filt_pipewrite };
72
73
74
75
76
77
78
79 #define MINPIPESIZE (PIPE_SIZE/3)
80
81
82
83
84 #define LIMITBIGPIPES 32
85 int nbigpipe;
86 static int amountpipekva;
87
88 struct pool pipe_pool;
89
90 void pipeclose(struct pipe *);
91 void pipe_free_kmem(struct pipe *);
92 int pipe_create(struct pipe *);
93 static __inline int pipelock(struct pipe *);
94 static __inline void pipeunlock(struct pipe *);
95 static __inline void pipeselwakeup(struct pipe *);
96 int pipespace(struct pipe *, u_int);
97
98
99
100
101
102
103 int
104 sys_opipe(struct proc *p, void *v, register_t *retval)
105 {
106 struct filedesc *fdp = p->p_fd;
107 struct file *rf, *wf;
108 struct pipe *rpipe, *wpipe;
109 int fd, error;
110
111 fdplock(fdp);
112
113 rpipe = pool_get(&pipe_pool, PR_WAITOK);
114 error = pipe_create(rpipe);
115 if (error != 0)
116 goto free1;
117 wpipe = pool_get(&pipe_pool, PR_WAITOK);
118 error = pipe_create(wpipe);
119 if (error != 0)
120 goto free2;
121
122 error = falloc(p, &rf, &fd);
123 if (error != 0)
124 goto free2;
125 rf->f_flag = FREAD | FWRITE;
126 rf->f_type = DTYPE_PIPE;
127 rf->f_data = rpipe;
128 rf->f_ops = &pipeops;
129 retval[0] = fd;
130
131 error = falloc(p, &wf, &fd);
132 if (error != 0)
133 goto free3;
134 wf->f_flag = FREAD | FWRITE;
135 wf->f_type = DTYPE_PIPE;
136 wf->f_data = wpipe;
137 wf->f_ops = &pipeops;
138 retval[1] = fd;
139
140 rpipe->pipe_peer = wpipe;
141 wpipe->pipe_peer = rpipe;
142
143 FILE_SET_MATURE(rf);
144 FILE_SET_MATURE(wf);
145
146 fdpunlock(fdp);
147 return (0);
148
149 free3:
150 fdremove(fdp, retval[0]);
151 closef(rf, p);
152 rpipe = NULL;
153 free2:
154 (void)pipeclose(wpipe);
155 free1:
156 if (rpipe != NULL)
157 (void)pipeclose(rpipe);
158 fdpunlock(fdp);
159 return (error);
160 }
161
162
163
164
165
166
167
168 int
169 pipespace(struct pipe *cpipe, u_int size)
170 {
171 caddr_t buffer;
172
173 buffer = (caddr_t)uvm_km_valloc(kernel_map, size);
174 if (buffer == NULL) {
175 return (ENOMEM);
176 }
177
178
179 pipe_free_kmem(cpipe);
180 cpipe->pipe_buffer.buffer = buffer;
181 cpipe->pipe_buffer.size = size;
182 cpipe->pipe_buffer.in = 0;
183 cpipe->pipe_buffer.out = 0;
184 cpipe->pipe_buffer.cnt = 0;
185
186 amountpipekva += cpipe->pipe_buffer.size;
187
188 return (0);
189 }
190
191
192
193
194 int
195 pipe_create(struct pipe *cpipe)
196 {
197 int error;
198
199
200 cpipe->pipe_buffer.buffer = NULL;
201
202
203
204
205 bzero(&cpipe->pipe_sel, sizeof cpipe->pipe_sel);
206 cpipe->pipe_state = 0;
207 cpipe->pipe_peer = NULL;
208 cpipe->pipe_busy = 0;
209
210 error = pipespace(cpipe, PIPE_SIZE);
211 if (error != 0)
212 return (error);
213
214 nanotime(&cpipe->pipe_ctime);
215 cpipe->pipe_atime = cpipe->pipe_ctime;
216 cpipe->pipe_mtime = cpipe->pipe_ctime;
217 cpipe->pipe_pgid = NO_PID;
218
219 return (0);
220 }
221
222
223
224
225
226 static __inline int
227 pipelock(struct pipe *cpipe)
228 {
229 int error;
230 while (cpipe->pipe_state & PIPE_LOCK) {
231 cpipe->pipe_state |= PIPE_LWANT;
232 if ((error = tsleep(cpipe, PRIBIO|PCATCH, "pipelk", 0)))
233 return error;
234 }
235 cpipe->pipe_state |= PIPE_LOCK;
236 return 0;
237 }
238
239
240
241
242 static __inline void
243 pipeunlock(struct pipe *cpipe)
244 {
245 cpipe->pipe_state &= ~PIPE_LOCK;
246 if (cpipe->pipe_state & PIPE_LWANT) {
247 cpipe->pipe_state &= ~PIPE_LWANT;
248 wakeup(cpipe);
249 }
250 }
251
252 static __inline void
253 pipeselwakeup(struct pipe *cpipe)
254 {
255 if (cpipe->pipe_state & PIPE_SEL) {
256 cpipe->pipe_state &= ~PIPE_SEL;
257 selwakeup(&cpipe->pipe_sel);
258 }
259 if ((cpipe->pipe_state & PIPE_ASYNC) && cpipe->pipe_pgid != NO_PID)
260 gsignal(cpipe->pipe_pgid, SIGIO);
261 KNOTE(&cpipe->pipe_sel.si_note, 0);
262 }
263
264
265 int
266 pipe_read(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred)
267 {
268 struct pipe *rpipe = (struct pipe *) fp->f_data;
269 int error;
270 int nread = 0;
271 int size;
272
273 error = pipelock(rpipe);
274 if (error)
275 return (error);
276
277 ++rpipe->pipe_busy;
278
279 while (uio->uio_resid) {
280
281
282
283 if (rpipe->pipe_buffer.cnt > 0) {
284 size = rpipe->pipe_buffer.size - rpipe->pipe_buffer.out;
285 if (size > rpipe->pipe_buffer.cnt)
286 size = rpipe->pipe_buffer.cnt;
287 if (size > uio->uio_resid)
288 size = uio->uio_resid;
289 error = uiomove(&rpipe->pipe_buffer.buffer[rpipe->pipe_buffer.out],
290 size, uio);
291 if (error) {
292 break;
293 }
294 rpipe->pipe_buffer.out += size;
295 if (rpipe->pipe_buffer.out >= rpipe->pipe_buffer.size)
296 rpipe->pipe_buffer.out = 0;
297
298 rpipe->pipe_buffer.cnt -= size;
299
300
301
302
303
304 if (rpipe->pipe_buffer.cnt == 0) {
305 rpipe->pipe_buffer.in = 0;
306 rpipe->pipe_buffer.out = 0;
307 }
308 nread += size;
309 } else {
310
311
312
313
314 if (rpipe->pipe_state & PIPE_EOF)
315 break;
316
317
318
319
320 if (rpipe->pipe_state & PIPE_WANTW) {
321 rpipe->pipe_state &= ~PIPE_WANTW;
322 wakeup(rpipe);
323 }
324
325
326
327
328 if (nread > 0)
329 break;
330
331
332
333
334
335
336 pipeunlock(rpipe);
337
338
339
340
341
342 if (fp->f_flag & FNONBLOCK) {
343 error = EAGAIN;
344 } else {
345 rpipe->pipe_state |= PIPE_WANTR;
346 if ((error = tsleep(rpipe, PRIBIO|PCATCH, "piperd", 0)) == 0)
347 error = pipelock(rpipe);
348 }
349 if (error)
350 goto unlocked_error;
351 }
352 }
353 pipeunlock(rpipe);
354
355 if (error == 0)
356 nanotime(&rpipe->pipe_atime);
357 unlocked_error:
358 --rpipe->pipe_busy;
359
360
361
362
363 if ((rpipe->pipe_busy == 0) && (rpipe->pipe_state & PIPE_WANT)) {
364 rpipe->pipe_state &= ~(PIPE_WANT|PIPE_WANTW);
365 wakeup(rpipe);
366 } else if (rpipe->pipe_buffer.cnt < MINPIPESIZE) {
367
368
369
370 if (rpipe->pipe_state & PIPE_WANTW) {
371 rpipe->pipe_state &= ~PIPE_WANTW;
372 wakeup(rpipe);
373 }
374 }
375
376 if ((rpipe->pipe_buffer.size - rpipe->pipe_buffer.cnt) >= PIPE_BUF)
377 pipeselwakeup(rpipe);
378
379 return (error);
380 }
381
382 int
383 pipe_write(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred)
384 {
385 int error = 0;
386 int orig_resid;
387
388 struct pipe *wpipe, *rpipe;
389
390 rpipe = (struct pipe *) fp->f_data;
391 wpipe = rpipe->pipe_peer;
392
393
394
395
396 if ((wpipe == NULL) || (wpipe->pipe_state & PIPE_EOF)) {
397 return (EPIPE);
398 }
399 ++wpipe->pipe_busy;
400
401
402
403
404
405 if ((uio->uio_resid > PIPE_SIZE) &&
406 (nbigpipe < LIMITBIGPIPES) &&
407 (wpipe->pipe_buffer.size <= PIPE_SIZE) &&
408 (wpipe->pipe_buffer.cnt == 0)) {
409
410 if ((error = pipelock(wpipe)) == 0) {
411 if (pipespace(wpipe, BIG_PIPE_SIZE) == 0)
412 nbigpipe++;
413 pipeunlock(wpipe);
414 }
415 }
416
417
418
419
420
421 if (error) {
422 --wpipe->pipe_busy;
423 if ((wpipe->pipe_busy == 0) &&
424 (wpipe->pipe_state & PIPE_WANT)) {
425 wpipe->pipe_state &= ~(PIPE_WANT | PIPE_WANTR);
426 wakeup(wpipe);
427 }
428 return (error);
429 }
430
431 orig_resid = uio->uio_resid;
432
433 while (uio->uio_resid) {
434 int space;
435
436 retrywrite:
437 if (wpipe->pipe_state & PIPE_EOF) {
438 error = EPIPE;
439 break;
440 }
441
442 space = wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt;
443
444
445 if ((space < uio->uio_resid) && (orig_resid <= PIPE_BUF))
446 space = 0;
447
448 if (space > 0) {
449 if ((error = pipelock(wpipe)) == 0) {
450 int size;
451 int segsize;
452
453
454
455
456
457
458
459
460 if (space > wpipe->pipe_buffer.size -
461 wpipe->pipe_buffer.cnt) {
462 pipeunlock(wpipe);
463 goto retrywrite;
464 }
465
466
467
468
469
470 if (space > uio->uio_resid)
471 size = uio->uio_resid;
472 else
473 size = space;
474
475
476
477
478
479
480
481 segsize = wpipe->pipe_buffer.size -
482 wpipe->pipe_buffer.in;
483 if (segsize > size)
484 segsize = size;
485
486
487
488 error = uiomove(&wpipe->pipe_buffer.buffer[wpipe->pipe_buffer.in],
489 segsize, uio);
490
491 if (error == 0 && segsize < size) {
492
493
494
495
496
497 #ifdef DIAGNOSTIC
498 if (wpipe->pipe_buffer.in + segsize !=
499 wpipe->pipe_buffer.size)
500 panic("Expected pipe buffer wraparound disappeared");
501 #endif
502
503 error = uiomove(&wpipe->pipe_buffer.buffer[0],
504 size - segsize, uio);
505 }
506 if (error == 0) {
507 wpipe->pipe_buffer.in += size;
508 if (wpipe->pipe_buffer.in >=
509 wpipe->pipe_buffer.size) {
510 #ifdef DIAGNOSTIC
511 if (wpipe->pipe_buffer.in != size - segsize + wpipe->pipe_buffer.size)
512 panic("Expected wraparound bad");
513 #endif
514 wpipe->pipe_buffer.in = size - segsize;
515 }
516
517 wpipe->pipe_buffer.cnt += size;
518 #ifdef DIAGNOSTIC
519 if (wpipe->pipe_buffer.cnt > wpipe->pipe_buffer.size)
520 panic("Pipe buffer overflow");
521 #endif
522 }
523 pipeunlock(wpipe);
524 }
525 if (error)
526 break;
527 } else {
528
529
530
531 if (wpipe->pipe_state & PIPE_WANTR) {
532 wpipe->pipe_state &= ~PIPE_WANTR;
533 wakeup(wpipe);
534 }
535
536
537
538
539 if (fp->f_flag & FNONBLOCK) {
540 error = EAGAIN;
541 break;
542 }
543
544
545
546
547
548 pipeselwakeup(wpipe);
549
550 wpipe->pipe_state |= PIPE_WANTW;
551 error = tsleep(wpipe, (PRIBIO + 1)|PCATCH,
552 "pipewr", 0);
553 if (error)
554 break;
555
556
557
558
559 if (wpipe->pipe_state & PIPE_EOF) {
560 error = EPIPE;
561 break;
562 }
563 }
564 }
565
566 --wpipe->pipe_busy;
567
568 if ((wpipe->pipe_busy == 0) && (wpipe->pipe_state & PIPE_WANT)) {
569 wpipe->pipe_state &= ~(PIPE_WANT | PIPE_WANTR);
570 wakeup(wpipe);
571 } else if (wpipe->pipe_buffer.cnt > 0) {
572
573
574
575
576 if (wpipe->pipe_state & PIPE_WANTR) {
577 wpipe->pipe_state &= ~PIPE_WANTR;
578 wakeup(wpipe);
579 }
580 }
581
582
583
584
585 if ((wpipe->pipe_buffer.cnt == 0) &&
586 (uio->uio_resid == 0) &&
587 (error == EPIPE)) {
588 error = 0;
589 }
590
591 if (error == 0)
592 nanotime(&wpipe->pipe_mtime);
593
594
595
596 if (wpipe->pipe_buffer.cnt)
597 pipeselwakeup(wpipe);
598
599 return (error);
600 }
601
602
603
604
605 int
606 pipe_ioctl(struct file *fp, u_long cmd, caddr_t data, struct proc *p)
607 {
608 struct pipe *mpipe = (struct pipe *)fp->f_data;
609
610 switch (cmd) {
611
612 case FIONBIO:
613 return (0);
614
615 case FIOASYNC:
616 if (*(int *)data) {
617 mpipe->pipe_state |= PIPE_ASYNC;
618 } else {
619 mpipe->pipe_state &= ~PIPE_ASYNC;
620 }
621 return (0);
622
623 case FIONREAD:
624 *(int *)data = mpipe->pipe_buffer.cnt;
625 return (0);
626
627 case SIOCSPGRP:
628 mpipe->pipe_pgid = *(int *)data;
629 return (0);
630
631 case SIOCGPGRP:
632 *(int *)data = mpipe->pipe_pgid;
633 return (0);
634
635 }
636 return (ENOTTY);
637 }
638
639 int
640 pipe_poll(struct file *fp, int events, struct proc *p)
641 {
642 struct pipe *rpipe = (struct pipe *)fp->f_data;
643 struct pipe *wpipe;
644 int revents = 0;
645
646 wpipe = rpipe->pipe_peer;
647 if (events & (POLLIN | POLLRDNORM)) {
648 if ((rpipe->pipe_buffer.cnt > 0) ||
649 (rpipe->pipe_state & PIPE_EOF))
650 revents |= events & (POLLIN | POLLRDNORM);
651 }
652
653
654 if ((rpipe->pipe_state & PIPE_EOF) ||
655 (wpipe == NULL) ||
656 (wpipe->pipe_state & PIPE_EOF))
657 revents |= POLLHUP;
658 else if (events & (POLLOUT | POLLWRNORM)) {
659 if ((wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt) >= PIPE_BUF)
660 revents |= events & (POLLOUT | POLLWRNORM);
661 }
662
663 if (revents == 0) {
664 if (events & (POLLIN | POLLRDNORM)) {
665 selrecord(p, &rpipe->pipe_sel);
666 rpipe->pipe_state |= PIPE_SEL;
667 }
668 if (events & (POLLOUT | POLLWRNORM)) {
669 selrecord(p, &wpipe->pipe_sel);
670 wpipe->pipe_state |= PIPE_SEL;
671 }
672 }
673 return (revents);
674 }
675
676 int
677 pipe_stat(struct file *fp, struct stat *ub, struct proc *p)
678 {
679 struct pipe *pipe = (struct pipe *)fp->f_data;
680
681 bzero(ub, sizeof(*ub));
682 ub->st_mode = S_IFIFO;
683 ub->st_blksize = pipe->pipe_buffer.size;
684 ub->st_size = pipe->pipe_buffer.cnt;
685 ub->st_blocks = (ub->st_size + ub->st_blksize - 1) / ub->st_blksize;
686 ub->st_atimespec = pipe->pipe_atime;
687 ub->st_mtimespec = pipe->pipe_mtime;
688 ub->st_ctimespec = pipe->pipe_ctime;
689 ub->st_uid = fp->f_cred->cr_uid;
690 ub->st_gid = fp->f_cred->cr_gid;
691
692
693
694
695 return (0);
696 }
697
698
699 int
700 pipe_close(struct file *fp, struct proc *p)
701 {
702 struct pipe *cpipe = (struct pipe *)fp->f_data;
703
704 fp->f_ops = NULL;
705 fp->f_data = NULL;
706 pipeclose(cpipe);
707 return (0);
708 }
709
710 void
711 pipe_free_kmem(struct pipe *cpipe)
712 {
713 if (cpipe->pipe_buffer.buffer != NULL) {
714 if (cpipe->pipe_buffer.size > PIPE_SIZE)
715 --nbigpipe;
716 amountpipekva -= cpipe->pipe_buffer.size;
717 uvm_km_free(kernel_map, (vaddr_t)cpipe->pipe_buffer.buffer,
718 cpipe->pipe_buffer.size);
719 cpipe->pipe_buffer.buffer = NULL;
720 }
721 }
722
723
724
725
726 void
727 pipeclose(struct pipe *cpipe)
728 {
729 struct pipe *ppipe;
730 if (cpipe) {
731
732 pipeselwakeup(cpipe);
733
734
735
736
737
738 cpipe->pipe_state |= PIPE_EOF;
739 while (cpipe->pipe_busy) {
740 wakeup(cpipe);
741 cpipe->pipe_state |= PIPE_WANT;
742 tsleep(cpipe, PRIBIO, "pipecl", 0);
743 }
744
745
746
747
748 if ((ppipe = cpipe->pipe_peer) != NULL) {
749 pipeselwakeup(ppipe);
750
751 ppipe->pipe_state |= PIPE_EOF;
752 wakeup(ppipe);
753 KNOTE(&ppipe->pipe_sel.si_note, 0);
754 ppipe->pipe_peer = NULL;
755 }
756
757
758
759
760 pipe_free_kmem(cpipe);
761 pool_put(&pipe_pool, cpipe);
762 }
763 }
764
765 int
766 pipe_kqfilter(struct file *fp, struct knote *kn)
767 {
768 struct pipe *rpipe = (struct pipe *)kn->kn_fp->f_data;
769 struct pipe *wpipe = rpipe->pipe_peer;
770
771 switch (kn->kn_filter) {
772 case EVFILT_READ:
773 kn->kn_fop = &pipe_rfiltops;
774 SLIST_INSERT_HEAD(&rpipe->pipe_sel.si_note, kn, kn_selnext);
775 break;
776 case EVFILT_WRITE:
777 if (wpipe == NULL)
778
779 return (1);
780 kn->kn_fop = &pipe_wfiltops;
781 SLIST_INSERT_HEAD(&wpipe->pipe_sel.si_note, kn, kn_selnext);
782 break;
783 default:
784 return (1);
785 }
786
787 return (0);
788 }
789
790 void
791 filt_pipedetach(struct knote *kn)
792 {
793 struct pipe *rpipe = (struct pipe *)kn->kn_fp->f_data;
794 struct pipe *wpipe = rpipe->pipe_peer;
795
796 switch (kn->kn_filter) {
797 case EVFILT_READ:
798 SLIST_REMOVE(&rpipe->pipe_sel.si_note, kn, knote, kn_selnext);
799 break;
800 case EVFILT_WRITE:
801 if (wpipe == NULL)
802 return;
803 SLIST_REMOVE(&wpipe->pipe_sel.si_note, kn, knote, kn_selnext);
804 break;
805 }
806 }
807
808
809 int
810 filt_piperead(struct knote *kn, long hint)
811 {
812 struct pipe *rpipe = (struct pipe *)kn->kn_fp->f_data;
813 struct pipe *wpipe = rpipe->pipe_peer;
814
815 kn->kn_data = rpipe->pipe_buffer.cnt;
816
817 if ((rpipe->pipe_state & PIPE_EOF) ||
818 (wpipe == NULL) || (wpipe->pipe_state & PIPE_EOF)) {
819 kn->kn_flags |= EV_EOF;
820 return (1);
821 }
822 return (kn->kn_data > 0);
823 }
824
825
826 int
827 filt_pipewrite(struct knote *kn, long hint)
828 {
829 struct pipe *rpipe = (struct pipe *)kn->kn_fp->f_data;
830 struct pipe *wpipe = rpipe->pipe_peer;
831
832 if ((wpipe == NULL) || (wpipe->pipe_state & PIPE_EOF)) {
833 kn->kn_data = 0;
834 kn->kn_flags |= EV_EOF;
835 return (1);
836 }
837 kn->kn_data = wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt;
838
839 return (kn->kn_data >= PIPE_BUF);
840 }
841
842 void
843 pipe_init(void)
844 {
845 pool_init(&pipe_pool, sizeof(struct pipe), 0, 0, 0, "pipepl",
846 &pool_allocator_nointr);
847 }
848