pipe.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. #include "types.h"
  2. #include "defs.h"
  3. #include "param.h"
  4. #include "mmu.h"
  5. #include "proc.h"
  6. #include "fs.h"
  7. #include "file.h"
  8. #include "spinlock.h"
  9. #define PIPESIZE 512
  10. struct pipe {
  11. struct spinlock lock;
  12. char data[PIPESIZE];
  13. uint nread; // number of bytes read
  14. uint nwrite; // number of bytes written
  15. int readopen; // read fd is still open
  16. int writeopen; // write fd is still open
  17. };
  18. int
  19. pipealloc(struct file **f0, struct file **f1)
  20. {
  21. struct pipe *p;
  22. p = 0;
  23. *f0 = *f1 = 0;
  24. if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0)
  25. goto bad;
  26. if((p = (struct pipe*)kalloc()) == 0)
  27. goto bad;
  28. memset(p, 0, PGSIZE);
  29. p->readopen = 1;
  30. p->writeopen = 1;
  31. p->nwrite = 0;
  32. p->nread = 0;
  33. initlock(&p->lock, "pipe");
  34. (*f0)->type = FD_PIPE;
  35. (*f0)->readable = 1;
  36. (*f0)->writable = 0;
  37. (*f0)->pipe = p;
  38. (*f1)->type = FD_PIPE;
  39. (*f1)->readable = 0;
  40. (*f1)->writable = 1;
  41. (*f1)->pipe = p;
  42. return 0;
  43. //PAGEBREAK: 20
  44. bad:
  45. if(p)
  46. kfree((char*)p);
  47. if(*f0)
  48. fileclose(*f0);
  49. if(*f1)
  50. fileclose(*f1);
  51. return -1;
  52. }
  53. void
  54. pipeclose(struct pipe *p, int writable)
  55. {
  56. acquire(&p->lock);
  57. if(writable){
  58. p->writeopen = 0;
  59. wakeup(&p->nread);
  60. } else {
  61. p->readopen = 0;
  62. wakeup(&p->nwrite);
  63. }
  64. if(p->readopen == 0 && p->writeopen == 0){
  65. release(&p->lock);
  66. kfree((char*)p);
  67. } else
  68. release(&p->lock);
  69. }
  70. //PAGEBREAK: 40
  71. int
  72. pipewrite(struct pipe *p, char *addr, int n)
  73. {
  74. int i;
  75. acquire(&p->lock);
  76. for(i = 0; i < n; i++){
  77. while(p->nwrite == p->nread + PIPESIZE){ //DOC: pipewrite-full
  78. if(p->readopen == 0 || curr_proc->killed){
  79. release(&p->lock);
  80. return -1;
  81. }
  82. wakeup(&p->nread);
  83. sleep(&p->nwrite, &p->lock); //DOC: pipewrite-sleep
  84. }
  85. p->data[p->nwrite++ % PIPESIZE] = addr[i];
  86. }
  87. wakeup(&p->nread); //DOC: pipewrite-wakeup1
  88. release(&p->lock);
  89. return n;
  90. }
  91. int
  92. piperead(struct pipe *p, char *addr, int n)
  93. {
  94. int i;
  95. acquire(&p->lock);
  96. while(p->nread == p->nwrite && p->writeopen){ //DOC: pipe-empty
  97. if(curr_proc->killed){
  98. release(&p->lock);
  99. return -1;
  100. }
  101. sleep(&p->nread, &p->lock); //DOC: piperead-sleep
  102. }
  103. for(i = 0; i < n; i++){ //DOC: piperead-copy
  104. if(p->nread == p->nwrite)
  105. break;
  106. addr[i] = p->data[p->nread++ % PIPESIZE];
  107. }
  108. wakeup(&p->nwrite); //DOC: piperead-wakeup
  109. release(&p->lock);
  110. return i;
  111. }