x86: sends the EOI later in the IRQ path
[akaros.git] / kern / src / vfs.c
index 7744121..7b4c298 100644 (file)
@@ -1750,6 +1750,13 @@ ssize_t pipe_file_write(struct file *file, const char *buf, size_t count,
                }
                cv_wait(&pii->p_cv);
                cpu_relax();
+               /* Still need to check in the loop, in case the last reader left while
+                * we slept. */
+               if (!pii->p_nr_readers) {
+                       cv_unlock(&pii->p_cv);
+                       set_errno(EPIPE);
+                       return -1;
+               }
        }
        /* We might need to wrap-around with our copy, so we'll do the copy in two
         * passes.  This will copy up to the end of the buffer, then on the next
@@ -1780,9 +1787,9 @@ int pipe_open(struct inode *inode, struct file *file)
        struct pipe_inode_info *pii = inode->i_pipe;
        cv_lock(&pii->p_cv);
        /* Ugliness due to not using flags for O_RDONLY and friends... */
-       if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+       if (file->f_mode == S_IRUSR) {
                pii->p_nr_readers++;
-       } else if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
+       } else if (file->f_mode == S_IWUSR) {
                pii->p_nr_writers++;
        } else {
                warn("Bad pipe file flags 0x%x\n", file->f_flags);
@@ -1796,13 +1803,15 @@ int pipe_release(struct inode *inode, struct file *file)
        struct pipe_inode_info *pii = inode->i_pipe;
        cv_lock(&pii->p_cv);
        /* Ugliness due to not using flags for O_RDONLY and friends... */
-       if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+       if (file->f_mode == S_IRUSR) {
                pii->p_nr_readers--;
-       } else if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
+       } else if (file->f_mode == S_IWUSR) {
                pii->p_nr_writers--;
        } else {
                warn("Bad pipe file flags 0x%x\n", file->f_flags);
        }
+       /* need to wake up any sleeping readers/writers, since we might be done */
+       __cv_broadcast(&pii->p_cv);
        cv_unlock(&pii->p_cv);
        return 0;
 }
@@ -1815,6 +1824,19 @@ struct file_operations pipe_f_op = {
        0
 };
 
+void pipe_debug(struct file *f)
+{
+       struct pipe_inode_info *pii = f->f_dentry->d_inode->i_pipe;
+       assert(pii);
+       printk("PIPE %p\n", pii);
+       printk("\trdoff %p\n", pii->p_rd_off);
+       printk("\twroff %p\n", pii->p_wr_off);
+       printk("\tnr_rds %d\n", pii->p_nr_readers);
+       printk("\tnr_wrs %d\n", pii->p_nr_writers);
+       printk("\tcv waiters %d\n", pii->p_cv.nr_waiters);
+
+}
+
 /* General plan: get a dentry/inode to represent the pipe.  We'll alloc it from
  * the default_ns SB, but won't actually link it anywhere.  It'll only be held
  * alive by the krefs, til all the FDs are closed. */
@@ -1872,6 +1894,8 @@ int do_pipe(struct file **pipe_files, int flags)
        }
        pii->p_rd_off = 0;
        pii->p_wr_off = 0;
+       pii->p_nr_readers = 0;
+       pii->p_nr_writers = 0;
        cv_init(&pii->p_cv);    /* must do this before dentry_open / pipe_open */
        /* Now we have an inode for the pipe.  We need two files for the read and
         * write ends of the pipe. */