static int idesc_pipe_close(struct idesc_pipe *cur, struct idesc_pipe *other) { cur->idesc.idesc_amode = 0; if (other->idesc.idesc_amode) { idesc_notify(&other->idesc, POLLERR); } else { return 1; } return 0; }
static ssize_t pipe_write(struct idesc *idesc, const void *buf, size_t nbyte) { struct pipe *pipe; const void *cbuf; int len; ssize_t res; assert(buf); assert(idesc); assert(idesc->idesc_ops == &idesc_pipe_ops); assert(idesc->idesc_amode == FS_MAY_WRITE); cbuf = buf; /* nbyte == 0 is ok to passthrough */ pipe = idesc_to_pipe(idesc); mutex_lock(&pipe->mutex); do { /* No data can be readed at all */ if (idesc_pipe_isclosed(&pipe->read_desc)) { res = -EPIPE; break; } /* Try to write some data */ len = ring_buff_enqueue(pipe->buff, (void *) cbuf, nbyte); if (len > 0) { /* Notzero was written, adjust pointers and notify * (read end can't be closed) */ cbuf += len; nbyte -= len; idesc_notify(&pipe->read_desc.idesc, POLLIN); } /* Have nothing to write, exit*/ if (!nbyte) { res = cbuf - buf; break; } res = pipe_wait(idesc, pipe, POLLOUT | POLLERR); } while (res == 0); mutex_unlock(&pipe->mutex); return res; }
static ssize_t pipe_read(struct idesc *idesc, void *buf, size_t nbyte) { struct pipe *pipe; ssize_t res; assert(buf); assert(idesc); assert(idesc->idesc_ops == &idesc_pipe_ops); assert(idesc->idesc_amode == FS_MAY_READ); if (!nbyte) { return 0; } pipe = idesc_to_pipe(idesc); mutex_lock(&pipe->mutex); do { res = ring_buff_dequeue(pipe->buff, buf, nbyte); if (idesc_pipe_isclosed(&pipe->write_desc)) { /* Nothing to do, what's read, that's read */ break; } if (res > 0) { /* Smth read, notify write end (can't be closed, * checked already) */ idesc_notify(&pipe->write_desc.idesc, POLLOUT); break; } res = pipe_wait(idesc, pipe, POLLIN | POLLERR); } while (res == 0); mutex_unlock(&pipe->mutex); return res; }
static inline void tty_notify(struct tty *t, int mask) { assert(t); if (t->idesc) idesc_notify(t->idesc, mask); }