/* * Interface to file system close. * * *pipep points to pipe control structure. When the last user releases pipe, * it will be set to NULL. */ int pipe_release( pipe_control_t **pipep, rtems_libio_t *iop ) { pipe_control_t *pipe = *pipep; uint32_t mode; rtems_status_code sc; sc = rtems_semaphore_obtain(pipe->Semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT); /* WARN pipe not released! */ if(sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred(sc); mode = LIBIO_ACCMODE(iop); if (mode & LIBIO_FLAGS_READ) pipe->Readers --; if (mode & LIBIO_FLAGS_WRITE) pipe->Writers --; sc = rtems_semaphore_obtain(rtems_pipe_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT); /* WARN pipe not freed and pipep not set to NULL! */ if(sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred(sc); 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); rtems_semaphore_release(rtems_pipe_semaphore); #if 0 if (! delfile) return 0; if (iop->pathinfo.ops->unlink_h == NULL) return 0; /* This is safe for IMFS, but how about other FSes? */ iop->flags &= ~LIBIO_FLAGS_OPEN; if(iop->pathinfo.ops->unlink_h(&iop->pathinfo)) return -errno; #endif return 0; }
/* * 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 }
/* * 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 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; }