diff options
Diffstat (limited to 'src/lib/shm_rdrbuff.c')
| -rw-r--r-- | src/lib/shm_rdrbuff.c | 617 |
1 files changed, 0 insertions, 617 deletions
diff --git a/src/lib/shm_rdrbuff.c b/src/lib/shm_rdrbuff.c deleted file mode 100644 index 5cdeba9e..00000000 --- a/src/lib/shm_rdrbuff.c +++ /dev/null @@ -1,617 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2024 - * - * Random Deletion Ring Buffer for Data Units - * - * Dimitri Staessens <dimitri@ouroboros.rocks> - * Sander Vrijders <sander@ouroboros.rocks> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * version 2.1 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., http://www.fsf.org/about/contact/. - */ - -#define _POSIX_C_SOURCE 200809L - -#include "config.h" - -#include <ouroboros/errno.h> -#include <ouroboros/pthread.h> -#include <ouroboros/shm_rdrbuff.h> - -#include <assert.h> -#include <fcntl.h> -#include <signal.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/mman.h> -#include <sys/stat.h> - -#define SHM_BLOCKS_SIZE ((SHM_BUFFER_SIZE) * SHM_RDRB_BLOCK_SIZE) -#define SHM_FILE_SIZE (SHM_BLOCKS_SIZE + 2 * sizeof(size_t) \ - + sizeof(pthread_mutex_t) + 2 * sizeof(pthread_cond_t) \ - + sizeof(pid_t)) -#define DU_BUFF_OVERHEAD (DU_BUFF_HEADSPACE + DU_BUFF_TAILSPACE) - -#define get_head_ptr(rdrb) \ - idx_to_du_buff_ptr(rdrb, *rdrb->head) - -#define get_tail_ptr(rdrb) \ - idx_to_du_buff_ptr(rdrb, *rdrb->tail) - -#define idx_to_du_buff_ptr(rdrb, idx) \ - ((struct shm_du_buff *) (rdrb->shm_base + idx * SHM_RDRB_BLOCK_SIZE)) - -#define shm_rdrb_used(rdrb) \ - (((*rdrb->head + (SHM_BUFFER_SIZE) - *rdrb->tail) + 1) \ - & ((SHM_BUFFER_SIZE) - 1)) - -#define shm_rdrb_free(rdrb, i) \ - (shm_rdrb_used(rdrb) + i < (SHM_BUFFER_SIZE)) - -#define shm_rdrb_empty(rdrb) \ - (*rdrb->tail == *rdrb->head) - -struct shm_du_buff { - size_t size; -#ifdef SHM_RDRB_MULTI_BLOCK - size_t blocks; -#endif - size_t du_head; - size_t du_tail; - size_t refs; - size_t idx; -}; - -struct shm_rdrbuff { - uint8_t * shm_base; /* start of blocks */ - size_t * head; /* start of ringbuffer head */ - size_t * tail; /* start of ringbuffer tail */ - pthread_mutex_t * lock; /* lock all free space in shm */ - pthread_cond_t * healthy; /* flag when packet is read */ - pid_t * pid; /* pid of the irmd owner */ -}; - -static void garbage_collect(struct shm_rdrbuff * rdrb) -{ -#ifdef SHM_RDRB_MULTI_BLOCK - struct shm_du_buff * sdb; - while (!shm_rdrb_empty(rdrb) && - (sdb = get_tail_ptr(rdrb))->refs == 0) - *rdrb->tail = (*rdrb->tail + sdb->blocks) - & ((SHM_BUFFER_SIZE) - 1); -#else - while (!shm_rdrb_empty(rdrb) && get_tail_ptr(rdrb)->refs == 0) - *rdrb->tail = (*rdrb->tail + 1) & ((SHM_BUFFER_SIZE) - 1); -#endif - pthread_cond_broadcast(rdrb->healthy); -} - -#ifdef HAVE_ROBUST_MUTEX -static void sanitize(struct shm_rdrbuff * rdrb) -{ - --get_head_ptr(rdrb)->refs; - garbage_collect(rdrb); - pthread_mutex_consistent(rdrb->lock); -} -#endif - -static char * rdrb_filename(void) -{ - char * str; - - str = malloc(strlen(SHM_RDRB_NAME) + 1); - if (str == NULL) - return NULL; - - sprintf(str, "%s", SHM_RDRB_NAME); - - return str; -} - -void shm_rdrbuff_close(struct shm_rdrbuff * rdrb) -{ - assert(rdrb); - - munmap(rdrb->shm_base, SHM_FILE_SIZE); - free(rdrb); -} - -void shm_rdrbuff_destroy(struct shm_rdrbuff * rdrb) -{ - char * shm_rdrb_fn; - - assert(rdrb); - - if (getpid() != *rdrb->pid && kill(*rdrb->pid, 0) == 0) { - free(rdrb); - return; - } - - shm_rdrbuff_close(rdrb); - - shm_rdrb_fn = rdrb_filename(); - if (shm_rdrb_fn == NULL) - return; - - shm_unlink(shm_rdrb_fn); - free(shm_rdrb_fn); -} - -#define MM_FLAGS (PROT_READ | PROT_WRITE) - -static struct shm_rdrbuff * rdrb_create(int flags) -{ - struct shm_rdrbuff * rdrb; - int fd; - uint8_t * shm_base; - char * shm_rdrb_fn; - - shm_rdrb_fn = rdrb_filename(); - if (shm_rdrb_fn == NULL) - goto fail_fn; - - rdrb = malloc(sizeof *rdrb); - if (rdrb == NULL) - goto fail_rdrb; - - fd = shm_open(shm_rdrb_fn, flags, 0666); - if (fd == -1) - goto fail_open; - - if ((flags & O_CREAT) && ftruncate(fd, SHM_FILE_SIZE) < 0) - goto fail_truncate; - - shm_base = mmap(NULL, SHM_FILE_SIZE, MM_FLAGS, MAP_SHARED, fd, 0); - if (shm_base == MAP_FAILED) - goto fail_truncate; - - close(fd); - - rdrb->shm_base = shm_base; - rdrb->head = (size_t *) ((uint8_t *) rdrb->shm_base + SHM_BLOCKS_SIZE); - rdrb->tail = rdrb->head + 1; - rdrb->lock = (pthread_mutex_t *) (rdrb->tail + 1); - rdrb->healthy = (pthread_cond_t *) (rdrb->lock + 1); - rdrb->pid = (pid_t *) (rdrb->healthy + 1); - - free(shm_rdrb_fn); - - return rdrb; - - fail_truncate: - close(fd); - if (flags & O_CREAT) - shm_unlink(shm_rdrb_fn); - fail_open: - free(rdrb); - fail_rdrb: - free(shm_rdrb_fn); - fail_fn: - return NULL; -} - -struct shm_rdrbuff * shm_rdrbuff_create(void) -{ - struct shm_rdrbuff * rdrb; - mode_t mask; - pthread_mutexattr_t mattr; - pthread_condattr_t cattr; - - mask = umask(0); - - rdrb = rdrb_create(O_CREAT | O_EXCL | O_RDWR); - - umask(mask); - - if (rdrb == NULL) - goto fail_rdrb; - - if (pthread_mutexattr_init(&mattr)) - goto fail_mattr; - - pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED); -#ifdef HAVE_ROBUST_MUTEX - pthread_mutexattr_setrobust(&mattr, PTHREAD_MUTEX_ROBUST); -#endif - if (pthread_mutex_init(rdrb->lock, &mattr)) - goto fail_mutex; - - if (pthread_condattr_init(&cattr)) - goto fail_cattr; - - pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED); -#ifndef __APPLE__ - pthread_condattr_setclock(&cattr, PTHREAD_COND_CLOCK); -#endif - if (pthread_cond_init(rdrb->healthy, &cattr)) - goto fail_healthy; - - *rdrb->head = 0; - *rdrb->tail = 0; - - *rdrb->pid = getpid(); - - pthread_mutexattr_destroy(&mattr); - pthread_condattr_destroy(&cattr); - - return rdrb; - - fail_healthy: - pthread_condattr_destroy(&cattr); - fail_cattr: - pthread_mutex_destroy(rdrb->lock); - fail_mutex: - pthread_mutexattr_destroy(&mattr); - fail_mattr: - shm_rdrbuff_destroy(rdrb); - fail_rdrb: - return NULL; -} - -struct shm_rdrbuff * shm_rdrbuff_open(void) -{ - return rdrb_create(O_RDWR); -} - -void shm_rdrbuff_purge(void) -{ - char * shm_rdrb_fn; - - shm_rdrb_fn = rdrb_filename(); - if (shm_rdrb_fn == NULL) - return; - - shm_unlink(shm_rdrb_fn); - free(shm_rdrb_fn); -} - -int shm_rdrbuff_mlock(struct shm_rdrbuff * rdrb) -{ - assert(rdrb != NULL); - - return mlock(rdrb->shm_base, SHM_FILE_SIZE); -} - -ssize_t shm_rdrbuff_alloc(struct shm_rdrbuff * rdrb, - size_t len, - uint8_t ** ptr, - struct shm_du_buff ** psdb) -{ - struct shm_du_buff * sdb; - size_t size = DU_BUFF_OVERHEAD + len; -#ifdef SHM_RDRB_MULTI_BLOCK - size_t blocks = 0; - size_t padblocks = 0; -#endif - ssize_t sz = size + sizeof(*sdb); - - assert(rdrb); - assert(psdb); - -#ifndef SHM_RDRB_MULTI_BLOCK - if (sz > SHM_RDRB_BLOCK_SIZE) - return -EMSGSIZE; -#else - while (sz > 0) { - sz -= SHM_RDRB_BLOCK_SIZE; - ++blocks; - } -#endif -#ifndef HAVE_ROBUST_MUTEX - pthread_mutex_lock(rdrb->lock); -#else - if (pthread_mutex_lock(rdrb->lock) == EOWNERDEAD) - sanitize(rdrb); -#endif -#ifdef SHM_RDRB_MULTI_BLOCK - if (blocks + *rdrb->head > (SHM_BUFFER_SIZE)) - padblocks = (SHM_BUFFER_SIZE) - *rdrb->head; - - if (!shm_rdrb_free(rdrb, blocks + padblocks)) { -#else - if (!shm_rdrb_free(rdrb, 1)) { -#endif - pthread_mutex_unlock(rdrb->lock); - return -EAGAIN; - } - -#ifdef SHM_RDRB_MULTI_BLOCK - if (padblocks) { - sdb = get_head_ptr(rdrb); - sdb->size = 0; - sdb->blocks = padblocks; - sdb->refs = 0; - sdb->du_head = 0; - sdb->du_tail = 0; - sdb->idx = *rdrb->head; - - *rdrb->head = 0; - } -#endif - sdb = get_head_ptr(rdrb); - sdb->refs = 1; - sdb->idx = *rdrb->head; -#ifdef SHM_RDRB_MULTI_BLOCK - sdb->blocks = blocks; - - *rdrb->head = (*rdrb->head + blocks) & ((SHM_BUFFER_SIZE) - 1); -#else - *rdrb->head = (*rdrb->head + 1) & ((SHM_BUFFER_SIZE) - 1); -#endif - pthread_mutex_unlock(rdrb->lock); - - sdb->size = size; - sdb->du_head = DU_BUFF_HEADSPACE; - sdb->du_tail = sdb->du_head + len; - - *psdb = sdb; - if (ptr != NULL) - *ptr = (uint8_t *) (sdb + 1) + sdb->du_head; - - return sdb->idx; -} - -ssize_t shm_rdrbuff_alloc_b(struct shm_rdrbuff * rdrb, - size_t len, - uint8_t ** ptr, - struct shm_du_buff ** psdb, - const struct timespec * abstime) -{ - struct shm_du_buff * sdb; - size_t size = DU_BUFF_OVERHEAD + len; -#ifdef SHM_RDRB_MULTI_BLOCK - size_t blocks = 0; - size_t padblocks = 0; -#endif - ssize_t sz = size + sizeof(*sdb); - int ret = 0; - - assert(rdrb); - assert(psdb); - -#ifndef SHM_RDRB_MULTI_BLOCK - if (sz > SHM_RDRB_BLOCK_SIZE) - return -EMSGSIZE; -#else - while (sz > 0) { - sz -= SHM_RDRB_BLOCK_SIZE; - ++blocks; - } -#endif -#ifndef HAVE_ROBUST_MUTEX - pthread_mutex_lock(rdrb->lock); -#else - if (pthread_mutex_lock(rdrb->lock) == EOWNERDEAD) - sanitize(rdrb); -#endif - pthread_cleanup_push(__cleanup_mutex_unlock, rdrb->lock); - -#ifdef SHM_RDRB_MULTI_BLOCK - if (blocks + *rdrb->head > (SHM_BUFFER_SIZE)) - padblocks = (SHM_BUFFER_SIZE) - *rdrb->head; - - while (!shm_rdrb_free(rdrb, blocks + padblocks) && ret != ETIMEDOUT) { -#else - while (!shm_rdrb_free(rdrb, 1) && ret != ETIMEDOUT) { -#endif - ret = __timedwait(rdrb->healthy, rdrb->lock, abstime); -#ifdef SHM_RDRB_MULTI_BLOCK - if (blocks + *rdrb->head > (SHM_BUFFER_SIZE)) - padblocks = (SHM_BUFFER_SIZE) - *rdrb->head; -#endif - } - - if (ret != ETIMEDOUT) { -#ifdef SHM_RDRB_MULTI_BLOCK - if (padblocks) { - sdb = get_head_ptr(rdrb); - sdb->size = 0; - sdb->blocks = padblocks; - sdb->refs = 0; - sdb->du_head = 0; - sdb->du_tail = 0; - sdb->idx = *rdrb->head; - - *rdrb->head = 0; - } -#endif - sdb = get_head_ptr(rdrb); - sdb->refs = 1; - sdb->idx = *rdrb->head; -#ifdef SHM_RDRB_MULTI_BLOCK - sdb->blocks = blocks; - - *rdrb->head = (*rdrb->head + blocks) & ((SHM_BUFFER_SIZE) - 1); -#else - *rdrb->head = (*rdrb->head + 1) & ((SHM_BUFFER_SIZE) - 1); -#endif - } - - pthread_cleanup_pop(true); - - if (ret == ETIMEDOUT) - return -ETIMEDOUT; - - sdb->size = size; - sdb->du_head = DU_BUFF_HEADSPACE; - sdb->du_tail = sdb->du_head + len; - - *psdb = sdb; - if (ptr != NULL) - *ptr = (uint8_t *) (sdb + 1) + sdb->du_head; - - return sdb->idx; -} - -ssize_t shm_rdrbuff_read(uint8_t ** dst, - struct shm_rdrbuff * rdrb, - size_t idx) -{ - struct shm_du_buff * sdb; - - assert(dst); - assert(rdrb); - assert(idx < (SHM_BUFFER_SIZE)); - - sdb = idx_to_du_buff_ptr(rdrb, idx); - *dst = ((uint8_t *) (sdb + 1)) + sdb->du_head; - - return (ssize_t) (sdb->du_tail - sdb->du_head); -} - -struct shm_du_buff * shm_rdrbuff_get(struct shm_rdrbuff * rdrb, - size_t idx) -{ - assert(rdrb); - assert(idx < (SHM_BUFFER_SIZE)); - - return idx_to_du_buff_ptr(rdrb, idx); -} - -int shm_rdrbuff_remove(struct shm_rdrbuff * rdrb, - size_t idx) -{ - struct shm_du_buff * sdb; - - assert(rdrb); - assert(idx < (SHM_BUFFER_SIZE)); - -#ifndef HAVE_ROBUST_MUTEX - pthread_mutex_lock(rdrb->lock); -#else - if (pthread_mutex_lock(rdrb->lock) == EOWNERDEAD) - sanitize(rdrb); -#endif - /* assert(!shm_rdrb_empty(rdrb)); */ - - sdb = idx_to_du_buff_ptr(rdrb, idx); - - if (sdb->refs == 1) { /* only stack needs it, can be removed */ - sdb->refs = 0; - if (idx == *rdrb->tail) - garbage_collect(rdrb); - } - - pthread_mutex_unlock(rdrb->lock); - - return 0; -} - -size_t shm_du_buff_get_idx(struct shm_du_buff * sdb) -{ - assert(sdb); - - return sdb->idx; -} - -uint8_t * shm_du_buff_head(struct shm_du_buff * sdb) -{ - assert(sdb); - - return (uint8_t *) (sdb + 1) + sdb->du_head; -} - -uint8_t * shm_du_buff_tail(struct shm_du_buff * sdb) -{ - assert(sdb); - - return (uint8_t *) (sdb + 1) + sdb->du_tail; -} - -size_t shm_du_buff_len(struct shm_du_buff * sdb) -{ - assert(sdb); - - return sdb->du_tail - sdb->du_head; -} - -uint8_t * shm_du_buff_head_alloc(struct shm_du_buff * sdb, - size_t size) -{ - assert(sdb); - - if (sdb->du_head < size) - return NULL; - - sdb->du_head -= size; - - return (uint8_t *) (sdb + 1) + sdb->du_head; -} - -uint8_t * shm_du_buff_tail_alloc(struct shm_du_buff * sdb, - size_t size) -{ - uint8_t * buf; - - assert(sdb); - - if (sdb->du_tail + size >= sdb->size) - return NULL; - - buf = (uint8_t *) (sdb + 1) + sdb->du_tail; - - sdb->du_tail += size; - - return buf; -} - -uint8_t * shm_du_buff_head_release(struct shm_du_buff * sdb, - size_t size) -{ - uint8_t * buf; - - assert(sdb); - assert(!(size > sdb->du_tail - sdb->du_head)); - - buf = (uint8_t *) (sdb + 1) + sdb->du_head; - - sdb->du_head += size; - - return buf; -} - -uint8_t * shm_du_buff_tail_release(struct shm_du_buff * sdb, - size_t size) -{ - assert(sdb); - assert(!(size > sdb->du_tail - sdb->du_head)); - - sdb->du_tail -= size; - - return (uint8_t *) (sdb + 1) + sdb->du_tail; -} - -void shm_du_buff_truncate(struct shm_du_buff * sdb, - size_t len) -{ - assert(sdb); - assert(len <= sdb->size); - - sdb->du_tail = sdb->du_head + len; -} - -int shm_du_buff_wait_ack(struct shm_du_buff * sdb) -{ - __sync_add_and_fetch(&sdb->refs, 1); - - return 0; -} - -int shm_du_buff_ack(struct shm_du_buff * sdb) -{ - __sync_sub_and_fetch(&sdb->refs, 1); - return 0; -} |
