int PipeRead(struct File* file, BYTE* buffer, DWORD count) { DWORD size = 0, chars = 0; int read = 0; if (!count) return 0; if (file->flags & FILE_NONBLOCK) { if (PIPE_LOCK(file)) return 0; // if (PIPE_EMPTY(file)) // { /* return -EAGAIN? */ // return 0; // } }else{ while (PIPE_EMPTY(file) || PIPE_LOCK(file)) { if (PIPE_EMPTY(file)) return 0; KePrint("WAIT\n"); // WAIT_ON(&PIPE_WAIT(file), (PIPE_LOCK(file) == 0)); } } PIPE_LOCK(file)++; while (count > 0 && (size = PIPE_SIZE(file))) { char* pipeBuf = PIPE_BUF(file) + PIPE_START(file); chars = PIPE_MAX_RCHUNK(file); if (chars > count) chars = count; if (chars > size) chars = size; read += chars; PIPE_START(file) += chars; PIPE_START(file) &= (PIPE_BUFFER_SIZE - 1); PIPE_SIZE(file) -= chars; count -= chars; memcpy(buffer, pipeBuf, chars); buffer+=chars; } PIPE_LOCK(file)--; WakeUp(&PIPE_WAIT(file)); return read; }
static ssize_t pipe_read(struct file * filp, char * buf, size_t count, loff_t *ppos) { struct inode * inode = filp->f_dentry->d_inode; ssize_t chars = 0, size = 0, read = 0; char *pipebuf; if (ppos != &filp->f_pos) return -ESPIPE; if ( !count ) return 0; if (filp->f_flags & O_NONBLOCK) { if (PIPE_LOCK(*inode)) return -EAGAIN; if (PIPE_EMPTY(*inode)) { if (PIPE_WRITERS(*inode)) return -EAGAIN; else return 0; } } else while (PIPE_EMPTY(*inode) || PIPE_LOCK(*inode)) { if (PIPE_EMPTY(*inode)) { if (!PIPE_WRITERS(*inode) || !count) return 0; } if (signal_pending(current)) return -ERESTARTSYS; interruptible_sleep_on(&PIPE_WAIT(*inode)); } PIPE_LOCK(*inode)++; while (count>0 && (size = PIPE_SIZE(*inode))) { chars = PIPE_MAX_RCHUNK(*inode); if (chars > count) chars = count; if (chars > size) chars = size; read += chars; pipebuf = PIPE_BASE(*inode)+PIPE_START(*inode); PIPE_START(*inode) += chars; PIPE_START(*inode) &= (PIPE_BUF-1); PIPE_LEN(*inode) -= chars; count -= chars; copy_to_user(buf, pipebuf, chars ); buf += chars; } PIPE_LOCK(*inode)--; wake_up_interruptible(&PIPE_WAIT(*inode)); if (read) { UPDATE_ATIME(inode); return read; } if (PIPE_WRITERS(*inode)) return -EAGAIN; return 0; }
int read_pipe(struct m_inode * inode, char * buf, int count) { char * b=buf; while (PIPE_EMPTY(*inode)) { wake_up(&inode->i_wait); if (inode->i_count != 2) /* are there any writers left? */ return 0; sleep_on(&inode->i_wait); } while (count>0 && !(PIPE_EMPTY(*inode))) { count --; put_fs_byte(((char *)inode->i_size)[PIPE_TAIL(*inode)],b++); INC_PIPE( PIPE_TAIL(*inode) ); } wake_up(&inode->i_wait); return b-buf; }
/* * The 'connect_xxx()' functions are needed for named pipes when * the open() code hasn't guaranteed a connection (O_NONBLOCK), * and we need to act differently until we do get a writer.. */ static ssize_t connect_read(struct file * filp, char * buf, size_t count, loff_t *ppos) { struct inode * inode = filp->f_dentry->d_inode; if (PIPE_EMPTY(*inode) && !PIPE_WRITERS(*inode)) return 0; filp->f_op = &read_fifo_fops; return pipe_read(filp,buf,count,ppos); }
static ssize_t pipe_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) { struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count }; return pipe_writev(filp, &iov, 1, ppos); } static ssize_t bad_pipe_r(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { return -EBADF; } static ssize_t bad_pipe_w(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) { return -EBADF; } static int pipe_ioctl(struct inode *pino, struct file *filp, unsigned int cmd, unsigned long arg) { switch (cmd) { case FIONREAD: return put_user(PIPE_LEN(*pino), (int __user *)arg); default: return -EINVAL; } } /* No kernel lock held - fine */ static unsigned int pipe_poll(struct file *filp, poll_table *wait) { unsigned int mask; struct inode *inode = filp->f_dentry->d_inode; poll_wait(filp, PIPE_WAIT(*inode), wait); /* Reading only -- no need for acquiring the semaphore. */ mask = POLLIN | POLLRDNORM; if (PIPE_EMPTY(*inode)) mask = POLLOUT | POLLWRNORM; if (!PIPE_WRITERS(*inode) && filp->f_version != PIPE_WCOUNTER(*inode)) mask |= POLLHUP; if (!PIPE_READERS(*inode)) mask |= POLLERR; return mask; }
static unsigned int connect_poll(struct file * filp, poll_table * wait) { struct inode * inode = filp->f_dentry->d_inode; poll_wait(filp, &PIPE_WAIT(*inode), wait); if (!PIPE_EMPTY(*inode)) { filp->f_op = &read_fifo_fops; return POLLIN | POLLRDNORM; } if (PIPE_WRITERS(*inode)) filp->f_op = &read_fifo_fops; return POLLOUT | POLLWRNORM; }
/* * Argh! Why does SunOS have to have different select() behaviour * for pipes and FIFOs? Hate, hate, hate! SunOS lacks POLLHUP. */ static unsigned int fifo_poll(struct file * filp, poll_table * wait) { unsigned int mask; struct inode * inode = filp->f_dentry->d_inode; poll_wait(filp, &PIPE_WAIT(*inode), wait); mask = POLLIN | POLLRDNORM; if (PIPE_EMPTY(*inode)) mask = POLLOUT | POLLWRNORM; if (!PIPE_READERS(*inode)) mask |= POLLERR; return mask; }
/* * The check_XX functions check out a file. We know it's either * a pipe, a character device or a fifo (fifo's not implemented) */ static int check_in(select_table * wait, struct m_inode * inode) { struct tty_struct * tty; if (tty = get_tty(inode)) if (!EMPTY(tty->secondary)) return 1; else add_wait(&tty->secondary->proc_list, wait); else if (inode->i_pipe) if (!PIPE_EMPTY(*inode)) return 1; else add_wait(&inode->i_wait, wait); return 0; }
/* No kernel lock held - fine */ static unsigned int pipe_poll(struct file *filp, poll_table *wait) { unsigned int mask; struct inode *inode = filp->f_dentry->d_inode; poll_wait(filp, PIPE_WAIT(*inode), wait); /* Reading only -- no need for acquiring the semaphore. */ mask = POLLIN | POLLRDNORM; if (PIPE_EMPTY(*inode)) mask = POLLOUT | POLLWRNORM; if (!PIPE_WRITERS(*inode) && filp->f_version != PIPE_WCOUNTER(*inode)) mask |= POLLHUP; if (!PIPE_READERS(*inode)) mask |= POLLERR; return mask; }
/* * Interface to file system read. */ ssize_t pipe_read( pipe_control_t *pipe, void *buffer, size_t count, rtems_libio_t *iop ) { int chunk, chunk1, read = 0, ret = 0; if (! PIPE_LOCK(pipe)) return -EINTR; while (read < count) { while (PIPE_EMPTY(pipe)) { /* Not an error */ if (pipe->Writers == 0) goto out_locked; if (LIBIO_NODELAY(iop)) { ret = -EAGAIN; goto out_locked; } /* Wait until pipe is no more empty or no writer exists */ pipe->waitingReaders ++; PIPE_UNLOCK(pipe); if (! PIPE_READWAIT(pipe)) ret = -EINTR; if (! PIPE_LOCK(pipe)) { /* WARN waitingReaders not restored! */ ret = -EINTR; goto out_nolock; } pipe->waitingReaders --; if (ret != 0) goto out_locked; } /* Read chunk bytes */ chunk = MIN(count - read, pipe->Length); chunk1 = pipe->Size - pipe->Start; if (chunk > chunk1) { memcpy(buffer + read, pipe->Buffer + pipe->Start, chunk1); memcpy(buffer + read + chunk1, pipe->Buffer, chunk - chunk1); } else memcpy(buffer + read, pipe->Buffer + pipe->Start, chunk); pipe->Start += chunk; pipe->Start %= pipe->Size; pipe->Length -= chunk; /* For buffering optimization */ if (PIPE_EMPTY(pipe)) pipe->Start = 0; if (pipe->waitingWriters > 0) PIPE_WAKEUPWRITERS(pipe); read += chunk; } out_locked: PIPE_UNLOCK(pipe); out_nolock: if (read > 0) return read; return ret; }
static ssize_t pipe_read(struct file *filp, char *buf, size_t count, loff_t *ppos) { struct inode *inode = filp->f_dentry->d_inode; ssize_t size, read, ret; /* Seeks are not allowed on pipes. */ ret = -ESPIPE; read = 0; if (ppos != &filp->f_pos) goto out_nolock; /* Always return 0 on null read. */ ret = 0; if (count == 0) goto out_nolock; /* Get the pipe semaphore */ ret = -ERESTARTSYS; if (down_interruptible(PIPE_SEM(*inode))) goto out_nolock; if (PIPE_EMPTY(*inode)) { do_more_read: ret = 0; if (!PIPE_WRITERS(*inode)) goto out; ret = -EAGAIN; if (filp->f_flags & O_NONBLOCK) goto out; for (;;) { PIPE_WAITING_READERS(*inode)++; pipe_wait(inode); PIPE_WAITING_READERS(*inode)--; ret = -ERESTARTSYS; if (signal_pending(current)) goto out; ret = 0; if (!PIPE_EMPTY(*inode)) break; if (!PIPE_WRITERS(*inode)) goto out; } } /* Read what data is available. */ ret = -EFAULT; while (count > 0 && (size = PIPE_LEN(*inode))) { char *pipebuf = PIPE_BASE(*inode) + PIPE_START(*inode); ssize_t chars = PIPE_MAX_RCHUNK(*inode); if (chars > count) chars = count; if (chars > size) chars = size; if (copy_to_user(buf, pipebuf, chars)) goto out; read += chars; PIPE_START(*inode) += chars; PIPE_START(*inode) &= (PIPE_SIZE - 1); PIPE_LEN(*inode) -= chars; count -= chars; buf += chars; } /* Cache behaviour optimization */ if (!PIPE_LEN(*inode)) PIPE_START(*inode) = 0; if (count && PIPE_WAITING_WRITERS(*inode) && !(filp->f_flags & O_NONBLOCK)) { /* * We know that we are going to sleep: signal * writers synchronously that there is more * room. */ wake_up_interruptible_sync(PIPE_WAIT(*inode)); if (!PIPE_EMPTY(*inode)) BUG(); goto do_more_read; } /* Signal writers asynchronously that there is more room. */ wake_up_interruptible(PIPE_WAIT(*inode)); ret = read; out: up(PIPE_SEM(*inode)); out_nolock: if (read) ret = read; UPDATE_ATIME(inode); return ret; }