Example #1
0
static int
shmfifo_ll_get (const struct shmhandle* const shm, void *data, int sz)
{
  struct shmprefix *p;
  int copysz;


  p = (struct shmprefix *) shm->mem;
  p->counter++;

  if (sz <= 0)
    {
      log_error ("sanity check failed in ll_get. sz is %d", sz);
      (void)shmfifo_unlock (shm);
      abort ();
    }

  if (shmfifo_ll_memused (shm) < sz)
    return -1;

  if (p->write > p->read)
    {
      /* normal */
      copysz = p->write - p->read;
      if (copysz > sz)
	copysz = sz;
    }
  else
    {
      copysz = shm->sz - p->read;
      if (copysz > sz)
	copysz = sz;
    }

  memcpy (data, (char *) shm->mem + p->read, copysz);


  p->read += copysz;

  if (p->read == shm->sz)
    p->read = shm->privsz + sizeof (struct shmprefix);

  if (copysz < sz)
    {
      memcpy (&((char *) data)[copysz], (char *) shm->mem + p->read,
	      sz - copysz);
      p->read += sz - copysz;
    }

  return sz;
}
Example #2
0
/*
 * Logs shared-memory usage statistics at level DEBUG.
 *
 * Precondition:
 *      The FIFO is locked by this process. An error-message is logged if it
 *      isn't.
 * Arguments:
 *      shm             Pointer to the shared-memory FIFO data-structure.
 */
static void
shmfifo_printmemstatus(
    const struct shmhandle* const       shm)
{
    if (log_is_enabled_debug) {
        struct shmprefix* p = (struct shmprefix*)shm->mem;

        (void)checkLocked(shm);
        log_debug
          ("<%d> c: %d sz: %d, r: %d, w: %d, used: %d, free: %d, maxblock: %d",
           getpid (), p->counter, shm->sz, p->read, p->write,
           shmfifo_ll_memused (shm), shmfifo_ll_memfree (shm),
           shmfifo_ll_memfree (shm) - sizeof (struct shmbh));
    }
}
Example #3
0
static void
shmfifo_printmemstatus (const struct shmhandle* const shm)
{
  struct shmprefix *p;

  if (ulogIsDebug ())
    {
      (void)shmfifo_lock (shm);
      p = (struct shmprefix *) shm->mem;

      nplDebug
	("<%d> c: %d sz: %d, r: %d, w: %d, used: %d, free: %d, maxblock: %d",
	 getpid (), p->counter, shm->sz, p->read, p->write,
	 shmfifo_ll_memused (shm), shmfifo_ll_memfree (shm),
	 shmfifo_ll_memfree (shm) - sizeof (struct shmbh));
      (void)shmfifo_unlock (shm);
    }
  return;
}
Example #4
0
/*
 * Reads one record's worth of data from the FIFO and writes it to a
 * client-supplied buffer. Blocks until data is available.
 *
 * Arguments:
 *      shm             Pointer to the shared-memory FIFO data-structure. The
 *                      FIFO must be unlocked.
 *      data            Pointer to the buffer into which to put data from the
 *                      FIFO.
 *      sz              The size of the buffer in bytes.
 *      nbytes          Pointer to the memory location to be set to the number
 *                      of bytes read.
 * Returns:
 *      0               Success. "*nbytes" is set to the number of bytes read.
 *      ECANCELED       Operating-system failure. Error-message logged.
 *      EINVAL          "shm" uninitialized. Error-message logged.
 *      EINVAL          "sz" is non-positive. Error-message logged.
 *      EINVAL          The buffer is too small for the record's data.  No data
 *                      is read.  Error-message logged.
 *      EIO             FIFO is corrupt. Error-message logged.
 * Raises:
 *      SIGSEGV if "shm" is NULL
 *      SIGSEGV if "data" is NULL
 *      SIGSEGV if "nbytes" is NULL
 *      SIGABRT if "shm" is uninitialized
 */
int
shmfifo_get(
    const struct shmhandle* const       shm,
    void* const                         data,
    const int                           sz,
    int* const                          nbytes)
{
    int status;

    if (sz <= 0) {
        log_error("Non-positive number of bytes to read: %d", sz);
        status = EINVAL;
    }
    else {
        int     loggedEmptyFifo = 0;

        if ((status = shmfifo_lock(shm)) == 0) {
            shmfifo_printmemstatus(shm);

            for (status = 0; shmfifo_ll_memused(shm) == 0; ) {
                if (!loggedEmptyFifo) {
                    log_info("shmfifo_get(): FIFO is empty");
                    loggedEmptyFifo = 1;
                }
                if ((status = shmfifo_wait_reader(shm)) != 0) {
                    break;
                }
            }

            if (0 == status) {
                struct shmbh        header;

                if (shmfifo_ll_memused(shm) < (int)sizeof(header)) {
                    log_error("Insufficient data for a record: "
                            "should be at least %d bytes; was %d bytes",
                            sizeof(header), shmfifo_ll_memused(shm));
                    shmfifo_print(shm);

                    status = EINVAL;
                }
                else {
                    shmfifo_ll_get(shm, &header, sizeof(header));

                    if (header.canary != 0xDEADBEEF) {
                        log_error("Invalid header sentinel: 0x%X",
                                header.canary);

                        status = EIO;
                    }
                    else if (shmfifo_ll_memused(shm) < header.sz) {
                        log_error("Inconsistent data-length of record: "
                                "expected %d bytes; encountered %d bytes",
                                header.sz, shmfifo_ll_memused(shm));
                        shmfifo_print(shm);

                        status = EIO;
                    }
                    else if (header.sz > sz) {
                        log_error("Client-supplied buffer too small: "
                                "need %d bytes; %d bytes supplied",
                                header.sz, sz);
                        shmfifo_ll_hrewind(shm);

                        status = EINVAL;
                    }
                    else {
                        shmfifo_ll_get(shm, data, header.sz);

                        if (loggedEmptyFifo) {
                            log_info("shmfifo_get(): "
                                    "Got %d bytes of data from FIFO",
                                    header.sz);
                        }

                        shmfifo_printmemstatus(shm);

                        if ((status = shmfifo_notify_writer(shm)) == 0) {
                            *nbytes = header.sz;
                        }
                    }
                }
            }                           /* FIFO has data */

            int tmpStatus = shmfifo_unlock(shm);

            if (status == 0)
                status = tmpStatus;
        }                               /* shared-memory FIFO locked */
    }

    return status;
}
Example #5
0
/*
 * Writes data to the shared-memory FIFO.
 *
 * Arguments:
 *      shm             Pointer to the shared-memory FIFO data-structure.
 *      data            Pointer to the data to be written.
 *      sz              The amount of data to be written in bytes.
 * Returns:
 *      0               Success.
 *      E2BIG           "sz" is larger than the FIFO can handle.  Error-message
 *                      logged.
 *      ECANCELED       Operating-system failure. Error-message logged.
 *      EIO             I/O error. Error-message logged.
 *      EINVAL          "sz" is negative. Error-message logged.
 *      EINVAL          "shm" uninitialized. Error-message logged.
 */
int
shmfifo_put(
    const struct shmhandle* const       shm,
    void* const                         data,
    const int                           sz)
{
    int status;

    if (0 > sz) {
        log_error("Invalid size argument: %d", sz);
        status = EINVAL;
    }
    else {
        if ((status = shmfifo_lock(shm)) == 0) {
            struct shmbh    header;
            const size_t    totalBytesToWrite = sz + sizeof(header);
            size_t          maxSize;

            shmfifo_printmemstatus(shm);

            maxSize = shmfifo_ll_memused(shm) + shmfifo_ll_memfree(shm);

            if (maxSize < totalBytesToWrite) {
                log_error("Record bigger than entire FIFO: "
                        "record is %lu bytes; FIFO capacity is %lu bytes",
                        totalBytesToWrite, maxSize);
                status = E2BIG;
            }
            else {
                int loggedNoRoom = 0;
                int freeSpace;

                status = 0;

                /*
                 * Wait for the FIFO to have room for the data.
                 */
                while ((freeSpace = shmfifo_ll_memfree(shm)) <=
                        totalBytesToWrite) {
                    if (!loggedNoRoom) {
                        log_error("No room in FIFO: "
                                "need %d bytes; only %d bytes available. "
                                "Waiting...", totalBytesToWrite, freeSpace);
                        loggedNoRoom = 1;
                    }
                    if ((status = shmfifo_wait_writer(shm)) != 0) {
                        break;
                    }
                }

                if (0 == status) {
                    header.sz = sz;
                    header.canary = 0xDEADBEEF;
                    shmfifo_ll_put(shm, &header, sizeof(header));
                    shmfifo_ll_put(shm, data, sz);

                    if (loggedNoRoom) {
                        log_info("shmfifo_put(): Wrote %d bytes to FIFO",
                                totalBytesToWrite);
                    }

                    status = shmfifo_notify_reader(shm);
                }
            }

            int tmpStatus = shmfifo_unlock(shm);

            if (status == 0)
                status = tmpStatus;
        }                               /* shared-memory FIFO locked */
    } // `sz` is valid

    return status;
}