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; }
struct inode *get_pipe_inode(void) { register struct inode *inode; extern struct inode_operations pipe_inode_operations; if ((inode = get_empty_inode())) { if (!(PIPE_BASE(*inode) = get_pipe_mem())) { iput(inode); return NULL; } inode->i_op = &pipe_inode_operations; inode->i_count = 2; /* sum of readers/writers */ PIPE_START(*inode) = PIPE_LEN(*inode) = 0; PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0; PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1; PIPE_LOCK(*inode) = 0; inode->i_pipe = 1; inode->i_mode |= S_IFIFO | S_IRUSR | S_IWUSR; inode->i_uid = current->euid; inode->i_gid = (__u8) current->egid; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; #if 0 inode->i_blksize = PAGE_SIZE; #endif } return inode; }
/* * If called with *pipep = NULL, pipe_new will call pipe_alloc to allocate a * pipe control structure and set *pipep to its address. * pipe is locked, when pipe_new returns with no error. */ static int pipe_new( pipe_control_t **pipep ) { pipe_control_t *pipe; int err = 0; if (rtems_semaphore_obtain(rtems_pipe_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT) != RTEMS_SUCCESSFUL) return -EINTR; pipe = *pipep; if (pipe == NULL) { err = pipe_alloc(&pipe); if (err) goto out; } if (! PIPE_LOCK(pipe)) err = -EINTR; if (*pipep == NULL) { if (err) pipe_free(pipe); else *pipep = pipe; } out: rtems_semaphore_release(rtems_pipe_semaphore); return err; }
/* * If called with *pipep = NULL, pipe_new will call pipe_alloc to allocate a * pipe control structure and set *pipep to its address. * pipe is locked, when pipe_new returns with no error. */ static int pipe_new( pipe_control_t **pipep ) { pipe_control_t *pipe; int err = 0; err = pipe_lock(); if (err) return err; pipe = *pipep; if (pipe == NULL) { err = pipe_alloc(&pipe); if (err) goto out; } if (! PIPE_LOCK(pipe)) err = -EINTR; if (*pipep == NULL) { if (err) pipe_free(pipe); else *pipep = pipe; } out: pipe_unlock(); return err; }
static struct inode * get_pipe_inode(void) { extern struct inode_operations pipe_inode_operations; struct inode *inode = get_empty_inode(); if (inode) { unsigned long page = __get_free_page(GFP_USER); if (!page) { iput(inode); inode = NULL; } else { PIPE_BASE(*inode) = (char *) page; inode->i_op = &pipe_inode_operations; PIPE_WAIT(*inode) = NULL; PIPE_START(*inode) = PIPE_LEN(*inode) = 0; PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0; PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1; PIPE_LOCK(*inode) = 0; /* * Mark the inode dirty from the very beginning, * that way it will never be moved to the dirty * list because "mark_inode_dirty()" will think * that it already _is_ on the dirty list. */ inode->i_state = I_DIRTY; inode->i_mode = S_IFIFO | S_IRUSR | S_IWUSR; inode->i_uid = current->fsuid; inode->i_gid = current->fsgid; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_blksize = PAGE_SIZE; } } return inode; }
/* * Interface to file system close. * * *pipep points to pipe control structure. When the last user releases pipe, * it will be set to NULL. */ void pipe_release( pipe_control_t **pipep, rtems_libio_t *iop ) { pipe_control_t *pipe = *pipep; uint32_t mode; #if defined(RTEMS_DEBUG) /* WARN pipe not freed and pipep not set to NULL! */ if (pipe_lock()) rtems_fatal_error_occurred(0xdeadbeef); /* WARN pipe not released! */ if (!PIPE_LOCK(pipe)) rtems_fatal_error_occurred(0xdeadbeef); #endif mode = LIBIO_ACCMODE(iop); if (mode & LIBIO_FLAGS_READ) pipe->Readers --; if (mode & LIBIO_FLAGS_WRITE) pipe->Writers --; PIPE_UNLOCK(pipe); if (pipe->Readers == 0 && pipe->Writers == 0) { #if 0 /* To delete an anonymous pipe file when all users closed it */ if (pipe->Anonymous) delfile = TRUE; #endif pipe_free(pipe); *pipep = NULL; } else if (pipe->Readers == 0 && mode != LIBIO_FLAGS_WRITE) /* Notify waiting Writers that all their partners left */ PIPE_WAKEUPWRITERS(pipe); else if (pipe->Writers == 0 && mode != LIBIO_FLAGS_READ) PIPE_WAKEUPREADERS(pipe); pipe_unlock(); #if 0 if (! delfile) return; if (iop->pathinfo.ops->unlink_h == NULL) return; /* This is safe for IMFS, but how about other FSes? */ iop->flags &= ~LIBIO_FLAGS_OPEN; if(iop->pathinfo.ops->unlink_h(&iop->pathinfo)) return; #endif }
void init_fifo(struct inode * inode) { inode->i_op = &fifo_inode_operations; inode->i_pipe = 1; PIPE_LOCK(*inode) = 0; PIPE_BASE(*inode) = NULL; PIPE_START(*inode) = PIPE_LEN(*inode) = 0; PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0; PIPE_WAIT(*inode) = NULL; PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0; }
static int pipe_rdwr_open(register struct inode *inode, register struct file *filp) { debug("PIPE: rdwr called.\n"); if(!PIPE_BASE(*inode)) { if(!(PIPE_BASE(*inode) = get_pipe_mem())) return -ENOMEM; #if 0 /* next fields already set to zero by get_empty_inode() */ PIPE_START(*inode) = PIPE_LEN(*inode) = 0; PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0; PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0; PIPE_LOCK(*inode) = 0; #endif } if (filp->f_mode & FMODE_READ) { (inode->u.pipe_i.readers)++; if(inode->u.pipe_i.writers > 0) { if(inode->u.pipe_i.readers < 2) wake_up_interruptible(&(inode->u.pipe_i.wait)); } else { if(!(filp->f_flags & O_NONBLOCK) && (inode->i_sb)) while(!(inode->u.pipe_i.writers)) interruptible_sleep_on(&(inode->u.pipe_i.wait)); } } if (filp->f_mode & FMODE_WRITE) { (inode->u.pipe_i.writers)++; if(inode->u.pipe_i.readers > 0) { if(inode->u.pipe_i.writers < 2) wake_up_interruptible(&(inode->u.pipe_i.wait)); } else { if(filp->f_flags & O_NONBLOCK) return -ENXIO; while(!(inode->u.pipe_i.readers)) interruptible_sleep_on(&(inode->u.pipe_i.wait)); } } return 0; }
/* * Interface to file system ioctl. */ int pipe_ioctl( pipe_control_t *pipe, uint32_t cmd, void *buffer, rtems_libio_t *iop ) { if (cmd == FIONREAD) { if (buffer == NULL) return -EFAULT; if (! PIPE_LOCK(pipe)) return -EINTR; /* Return length of pipe */ *(unsigned int *)buffer = pipe->Length; PIPE_UNLOCK(pipe); return 0; } return -EINVAL; }
/* * Interface to file system write. */ ssize_t pipe_write( pipe_control_t *pipe, const void *buffer, size_t count, rtems_libio_t *iop ) { int chunk, chunk1, written = 0, ret = 0; /* Write nothing */ if (count == 0) return 0; if (! PIPE_LOCK(pipe)) return -EINTR; if (pipe->Readers == 0) { ret = -EPIPE; goto out_locked; } /* Write of PIPE_BUF bytes or less shall not be interleaved */ chunk = count <= pipe->Size ? count : 1; while (written < count) { while (PIPE_SPACE(pipe) < chunk) { if (LIBIO_NODELAY(iop)) { ret = -EAGAIN; goto out_locked; } /* Wait until there is chunk bytes space or no reader exists */ pipe->waitingWriters ++; PIPE_UNLOCK(pipe); if (! PIPE_WRITEWAIT(pipe)) ret = -EINTR; if (! PIPE_LOCK(pipe)) { /* WARN waitingWriters not restored! */ ret = -EINTR; goto out_nolock; } pipe->waitingWriters --; if (ret != 0) goto out_locked; if (pipe->Readers == 0) { ret = -EPIPE; goto out_locked; } } chunk = MIN(count - written, PIPE_SPACE(pipe)); chunk1 = pipe->Size - PIPE_WSTART(pipe); if (chunk > chunk1) { memcpy(pipe->Buffer + PIPE_WSTART(pipe), buffer + written, chunk1); memcpy(pipe->Buffer, buffer + written + chunk1, chunk - chunk1); } else memcpy(pipe->Buffer + PIPE_WSTART(pipe), buffer + written, chunk); pipe->Length += chunk; if (pipe->waitingReaders > 0) PIPE_WAKEUPREADERS(pipe); written += chunk; /* Write of more than PIPE_BUF bytes can be interleaved */ chunk = 1; } out_locked: PIPE_UNLOCK(pipe); out_nolock: #ifdef RTEMS_POSIX_API /* Signal SIGPIPE */ if (ret == -EPIPE) kill(getpid(), SIGPIPE); #endif if (written > 0) return written; return ret; }
/* * 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; }
/* * Interface to file system open. * * *pipep points to pipe control structure. If called with *pipep = NULL, * fifo_open will try allocating and initializing a control structure. If the * call succeeds, *pipep will be set to address of new control structure. */ int fifo_open( pipe_control_t **pipep, rtems_libio_t *iop ) { pipe_control_t *pipe; unsigned int prevCounter; int err; err = pipe_new(pipep); if (err) return err; pipe = *pipep; switch (LIBIO_ACCMODE(iop)) { case LIBIO_FLAGS_READ: pipe->readerCounter ++; if (pipe->Readers ++ == 0) PIPE_WAKEUPWRITERS(pipe); if (pipe->Writers == 0) { /* Not an error */ if (LIBIO_NODELAY(iop)) break; prevCounter = pipe->writerCounter; err = -EINTR; /* Wait until a writer opens the pipe */ do { PIPE_UNLOCK(pipe); if (! PIPE_READWAIT(pipe)) goto out_error; if (! PIPE_LOCK(pipe)) goto out_error; } while (prevCounter == pipe->writerCounter); } break; case LIBIO_FLAGS_WRITE: pipe->writerCounter ++; if (pipe->Writers ++ == 0) PIPE_WAKEUPREADERS(pipe); if (pipe->Readers == 0 && LIBIO_NODELAY(iop)) { PIPE_UNLOCK(pipe); err = -ENXIO; goto out_error; } if (pipe->Readers == 0) { prevCounter = pipe->readerCounter; err = -EINTR; do { PIPE_UNLOCK(pipe); if (! PIPE_WRITEWAIT(pipe)) goto out_error; if (! PIPE_LOCK(pipe)) goto out_error; } while (prevCounter == pipe->readerCounter); } break; case LIBIO_FLAGS_READ_WRITE: pipe->readerCounter ++; if (pipe->Readers ++ == 0) PIPE_WAKEUPWRITERS(pipe); pipe->writerCounter ++; if (pipe->Writers ++ == 0) PIPE_WAKEUPREADERS(pipe); break; } PIPE_UNLOCK(pipe); return 0; out_error: pipe_release(pipep, iop); return err; }
int pipe_stat(struct pipe *cpipe, void *ub, int isstat64) { #if CONFIG_MACF int error; #endif int pipe_size = 0; int pipe_count; struct stat *sb = (struct stat *)0; /* warning avoidance ; protected by isstat64 */ struct stat64 * sb64 = (struct stat64 *)0; /* warning avoidance ; protected by isstat64 */ if (cpipe == NULL) return (EBADF); PIPE_LOCK(cpipe); #if CONFIG_MACF error = mac_pipe_check_stat(kauth_cred_get(), cpipe); if (error) { PIPE_UNLOCK(cpipe); return (error); } #endif if (cpipe->pipe_buffer.buffer == 0) { /* must be stat'ing the write fd */ if (cpipe->pipe_peer) { /* the peer still exists, use it's info */ pipe_size = MAX_PIPESIZE(cpipe->pipe_peer); pipe_count = cpipe->pipe_peer->pipe_buffer.cnt; } else { pipe_count = 0; } } else { pipe_size = MAX_PIPESIZE(cpipe); pipe_count = cpipe->pipe_buffer.cnt; } /* * since peer's buffer is setup ouside of lock * we might catch it in transient state */ if (pipe_size == 0) pipe_size = MAX(PIPE_SIZE, pipesize_blocks[0]); if (isstat64 != 0) { sb64 = (struct stat64 *)ub; bzero(sb64, sizeof(*sb64)); sb64->st_mode = S_IFIFO | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; sb64->st_blksize = pipe_size; sb64->st_size = pipe_count; sb64->st_blocks = (sb64->st_size + sb64->st_blksize - 1) / sb64->st_blksize; sb64->st_uid = kauth_getuid(); sb64->st_gid = kauth_getgid(); sb64->st_atimespec.tv_sec = cpipe->st_atimespec.tv_sec; sb64->st_atimespec.tv_nsec = cpipe->st_atimespec.tv_nsec; sb64->st_mtimespec.tv_sec = cpipe->st_mtimespec.tv_sec; sb64->st_mtimespec.tv_nsec = cpipe->st_mtimespec.tv_nsec; sb64->st_ctimespec.tv_sec = cpipe->st_ctimespec.tv_sec; sb64->st_ctimespec.tv_nsec = cpipe->st_ctimespec.tv_nsec; /* * Return a relatively unique inode number based on the current * address of this pipe's struct pipe. This number may be recycled * relatively quickly. */ sb64->st_ino = (ino64_t)VM_KERNEL_ADDRPERM((uintptr_t)cpipe); } else { sb = (struct stat *)ub; bzero(sb, sizeof(*sb)); sb->st_mode = S_IFIFO | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; sb->st_blksize = pipe_size; sb->st_size = pipe_count; sb->st_blocks = (sb->st_size + sb->st_blksize - 1) / sb->st_blksize; sb->st_uid = kauth_getuid(); sb->st_gid = kauth_getgid(); sb->st_atimespec.tv_sec = cpipe->st_atimespec.tv_sec; sb->st_atimespec.tv_nsec = cpipe->st_atimespec.tv_nsec; sb->st_mtimespec.tv_sec = cpipe->st_mtimespec.tv_sec; sb->st_mtimespec.tv_nsec = cpipe->st_mtimespec.tv_nsec; sb->st_ctimespec.tv_sec = cpipe->st_ctimespec.tv_sec; sb->st_ctimespec.tv_nsec = cpipe->st_ctimespec.tv_nsec; /* * Return a relatively unique inode number based on the current * address of this pipe's struct pipe. This number may be recycled * relatively quickly. */ sb->st_ino = (ino_t)VM_KERNEL_ADDRPERM((uintptr_t)cpipe); } PIPE_UNLOCK(cpipe); /* * POSIX: Left as 0: st_dev, st_nlink, st_rdev, st_flags, st_gen, * st_uid, st_gid. * * XXX (st_dev) should be unique, but there is no device driver that * XXX is associated with pipes, since they are implemented via a * XXX struct fileops indirection rather than as FS objects. */ return (0); }
int PipeWrite(struct File* file,BYTE* buffer,DWORD size) { DWORD free = 0, chars; int written = 0; int err = 0; /* If we've got no readers on this pipe, let userspace know. */ if (PIPE_READERS(file) == 0) return -EPIPE; if (size <= PIPE_BUFFER_SIZE) free = size; else free = 1; while (size > 0) { while ((PIPE_FREE(file) < free || PIPE_LOCK(file))) { if (!PIPE_READERS(file) == 0) { err = -EPIPE; goto out; } if (file->flags & FILE_NONBLOCK) { goto out; } WAIT_ON(&PIPE_WAIT(file), PIPE_LOCK(file) == 0); } PIPE_LOCK(file)++; while (size > 0 && (free = PIPE_FREE(file))) { char* pipeBuf = PIPE_BUF(file) + PIPE_END(file); chars = PIPE_MAX_WCHUNK(file); if (chars > size) chars = size; if (chars > free) chars = size; /* Update counters. */ written += chars; PIPE_SIZE(file) += chars; size -= chars; memcpy(pipeBuf, buffer, chars); buffer += chars; } PIPE_LOCK(file)--; WakeUp(&PIPE_WAIT(file)); free = 1; } out: return (written > 0) ? (written) : (err); }
static ssize_t pipe_write(struct file * filp, const char * buf, size_t count, loff_t *ppos) { struct inode * inode = filp->f_dentry->d_inode; ssize_t chars = 0, free = 0, written = 0, err=0; char *pipebuf; if (ppos != &filp->f_pos) return -ESPIPE; if (!PIPE_READERS(*inode)) { /* no readers */ send_sig(SIGPIPE,current,0); return -EPIPE; } /* if count <= PIPE_BUF, we have to make it atomic */ if (count <= PIPE_BUF) free = count; else free = 1; /* can't do it atomically, wait for any free space */ up(&inode->i_sem); if (down_interruptible(&inode->i_atomic_write)) { down(&inode->i_sem); return -ERESTARTSYS; } while (count>0) { while ((PIPE_FREE(*inode) < free) || PIPE_LOCK(*inode)) { if (!PIPE_READERS(*inode)) { /* no readers */ send_sig(SIGPIPE,current,0); err = -EPIPE; goto errout; } if (signal_pending(current)) { err = -ERESTARTSYS; goto errout; } if (filp->f_flags & O_NONBLOCK) { err = -EAGAIN; goto errout; } interruptible_sleep_on(&PIPE_WAIT(*inode)); } PIPE_LOCK(*inode)++; while (count>0 && (free = PIPE_FREE(*inode))) { chars = PIPE_MAX_WCHUNK(*inode); if (chars > count) chars = count; if (chars > free) chars = free; pipebuf = PIPE_BASE(*inode)+PIPE_END(*inode); written += chars; PIPE_LEN(*inode) += chars; count -= chars; copy_from_user(pipebuf, buf, chars ); buf += chars; } PIPE_LOCK(*inode)--; wake_up_interruptible(&PIPE_WAIT(*inode)); free = 1; } inode->i_ctime = inode->i_mtime = CURRENT_TIME; mark_inode_dirty(inode); errout: up(&inode->i_atomic_write); down(&inode->i_sem); return written ? written : err; }
static int fifo_open(struct inode * inode,struct file * filp) { int retval = 0; unsigned long page; switch( filp->f_mode ) { case 1: /* * O_RDONLY * POSIX.1 says that O_NONBLOCK means return with the FIFO * opened, even when there is no process writing the FIFO. */ filp->f_op = &connecting_fifo_fops; if (!PIPE_READERS(*inode)++) wake_up_interruptible(&PIPE_WAIT(*inode)); if (!(filp->f_flags & O_NONBLOCK) && !PIPE_WRITERS(*inode)) { PIPE_RD_OPENERS(*inode)++; while (!PIPE_WRITERS(*inode)) { if (current->signal & ~current->blocked) { retval = -ERESTARTSYS; break; } interruptible_sleep_on(&PIPE_WAIT(*inode)); } if (!--PIPE_RD_OPENERS(*inode)) wake_up_interruptible(&PIPE_WAIT(*inode)); } while (PIPE_WR_OPENERS(*inode)) interruptible_sleep_on(&PIPE_WAIT(*inode)); if (PIPE_WRITERS(*inode)) filp->f_op = &read_fifo_fops; if (retval && !--PIPE_READERS(*inode)) wake_up_interruptible(&PIPE_WAIT(*inode)); break; case 2: /* * O_WRONLY * POSIX.1 says that O_NONBLOCK means return -1 with * errno=ENXIO when there is no process reading the FIFO. */ if ((filp->f_flags & O_NONBLOCK) && !PIPE_READERS(*inode)) { retval = -ENXIO; break; } filp->f_op = &write_fifo_fops; if (!PIPE_WRITERS(*inode)++) wake_up_interruptible(&PIPE_WAIT(*inode)); if (!PIPE_READERS(*inode)) { PIPE_WR_OPENERS(*inode)++; while (!PIPE_READERS(*inode)) { if (current->signal & ~current->blocked) { retval = -ERESTARTSYS; break; } interruptible_sleep_on(&PIPE_WAIT(*inode)); } if (!--PIPE_WR_OPENERS(*inode)) wake_up_interruptible(&PIPE_WAIT(*inode)); } while (PIPE_RD_OPENERS(*inode)) interruptible_sleep_on(&PIPE_WAIT(*inode)); if (retval && !--PIPE_WRITERS(*inode)) wake_up_interruptible(&PIPE_WAIT(*inode)); break; case 3: /* * O_RDWR * POSIX.1 leaves this case "undefined" when O_NONBLOCK is set. * This implementation will NEVER block on a O_RDWR open, since * the process can at least talk to itself. */ filp->f_op = &rdwr_fifo_fops; if (!PIPE_READERS(*inode)++) wake_up_interruptible(&PIPE_WAIT(*inode)); while (PIPE_WR_OPENERS(*inode)) interruptible_sleep_on(&PIPE_WAIT(*inode)); if (!PIPE_WRITERS(*inode)++) wake_up_interruptible(&PIPE_WAIT(*inode)); while (PIPE_RD_OPENERS(*inode)) interruptible_sleep_on(&PIPE_WAIT(*inode)); break; default: retval = -EINVAL; } if (retval || PIPE_BASE(*inode)) return retval; page = __get_free_page(GFP_KERNEL); if (PIPE_BASE(*inode)) { free_page(page); return 0; } if (!page) return -ENOMEM; PIPE_LOCK(*inode) = 0; PIPE_START(*inode) = PIPE_LEN(*inode) = 0; PIPE_BASE(*inode) = (char *) page; return 0; }