X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=libringbuffer%2Fshm.c;h=44a830af20446142f8e21177b5187e8dfd6d4af0;hb=HEAD;hp=8ac321e3931906888f79dd9e2419a7dbca8225de;hpb=429dadf0e28fe24be158ddb76d09f5f2308b6467;p=lttng-ust.git diff --git a/libringbuffer/shm.c b/libringbuffer/shm.c deleted file mode 100644 index 8ac321e3..00000000 --- a/libringbuffer/shm.c +++ /dev/null @@ -1,477 +0,0 @@ -/* - * libringbuffer/shm.c - * - * Copyright (C) 2005-2012 Mathieu Desnoyers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; only - * version 2.1 of the License. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define _LGPL_SOURCE -#include "shm.h" -#include -#include -#include -#include -#include /* For mode constants */ -#include /* For O_* constants */ -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Ensure we have the required amount of space available by writing 0 - * into the entire buffer. Not doing so can trigger SIGBUS when going - * beyond the available shm space. - * - * Also ensure the file metadata is synced with the storage by using - * fsync(2). - */ -static -int zero_file(int fd, size_t len) -{ - ssize_t retlen; - size_t written = 0; - char *zeropage; - long pagelen; - int ret; - - pagelen = sysconf(_SC_PAGESIZE); - if (pagelen < 0) - return (int) pagelen; - zeropage = calloc(pagelen, 1); - if (!zeropage) - return -ENOMEM; - - while (len > written) { - do { - retlen = write(fd, zeropage, - min_t(size_t, pagelen, len - written)); - } while (retlen == -1UL && errno == EINTR); - if (retlen < 0) { - ret = (int) retlen; - goto error; - } - written += retlen; - } - ret = fsync(fd); - if (ret) { - ret = (int) -errno; - goto error; - } - ret = 0; -error: - free(zeropage); - return ret; -} - -struct shm_object_table *shm_object_table_create(size_t max_nb_obj) -{ - struct shm_object_table *table; - - table = zmalloc(sizeof(struct shm_object_table) + - max_nb_obj * sizeof(table->objects[0])); - if (!table) - return NULL; - table->size = max_nb_obj; - return table; -} - -static -struct shm_object *_shm_object_table_alloc_shm(struct shm_object_table *table, - size_t memory_map_size, - int stream_fd) -{ - int shmfd, waitfd[2], ret, i; - struct shm_object *obj; - char *memory_map; - - if (stream_fd < 0) - return NULL; - if (table->allocated_len >= table->size) - return NULL; - obj = &table->objects[table->allocated_len]; - - /* wait_fd: create pipe */ - ret = pipe(waitfd); - if (ret < 0) { - PERROR("pipe"); - goto error_pipe; - } - for (i = 0; i < 2; i++) { - ret = fcntl(waitfd[i], F_SETFD, FD_CLOEXEC); - if (ret < 0) { - PERROR("fcntl"); - goto error_fcntl; - } - } - /* The write end of the pipe needs to be non-blocking */ - ret = fcntl(waitfd[1], F_SETFL, O_NONBLOCK); - if (ret < 0) { - PERROR("fcntl"); - goto error_fcntl; - } - memcpy(obj->wait_fd, waitfd, sizeof(waitfd)); - - /* create shm */ - - shmfd = stream_fd; - ret = zero_file(shmfd, memory_map_size); - if (ret) { - PERROR("zero_file"); - goto error_zero_file; - } - ret = ftruncate(shmfd, memory_map_size); - if (ret) { - PERROR("ftruncate"); - goto error_ftruncate; - } - obj->shm_fd_ownership = 0; - obj->shm_fd = shmfd; - - /* memory_map: mmap */ - memory_map = mmap(NULL, memory_map_size, PROT_READ | PROT_WRITE, - MAP_SHARED, shmfd, 0); - if (memory_map == MAP_FAILED) { - PERROR("mmap"); - goto error_mmap; - } - obj->type = SHM_OBJECT_SHM; - obj->memory_map = memory_map; - obj->memory_map_size = memory_map_size; - obj->allocated_len = 0; - obj->index = table->allocated_len++; - - return obj; - -error_mmap: -error_ftruncate: -error_zero_file: -error_fcntl: - for (i = 0; i < 2; i++) { - ret = close(waitfd[i]); - if (ret) { - PERROR("close"); - assert(0); - } - } -error_pipe: - return NULL; -} - -static -struct shm_object *_shm_object_table_alloc_mem(struct shm_object_table *table, - size_t memory_map_size) -{ - struct shm_object *obj; - void *memory_map; - int waitfd[2], i, ret; - - if (table->allocated_len >= table->size) - return NULL; - obj = &table->objects[table->allocated_len]; - - memory_map = zmalloc(memory_map_size); - if (!memory_map) - goto alloc_error; - - /* wait_fd: create pipe */ - ret = pipe(waitfd); - if (ret < 0) { - PERROR("pipe"); - goto error_pipe; - } - for (i = 0; i < 2; i++) { - ret = fcntl(waitfd[i], F_SETFD, FD_CLOEXEC); - if (ret < 0) { - PERROR("fcntl"); - goto error_fcntl; - } - } - /* The write end of the pipe needs to be non-blocking */ - ret = fcntl(waitfd[1], F_SETFL, O_NONBLOCK); - if (ret < 0) { - PERROR("fcntl"); - goto error_fcntl; - } - memcpy(obj->wait_fd, waitfd, sizeof(waitfd)); - - /* no shm_fd */ - obj->shm_fd = -1; - obj->shm_fd_ownership = 0; - - obj->type = SHM_OBJECT_MEM; - obj->memory_map = memory_map; - obj->memory_map_size = memory_map_size; - obj->allocated_len = 0; - obj->index = table->allocated_len++; - - return obj; - -error_fcntl: - for (i = 0; i < 2; i++) { - ret = close(waitfd[i]); - if (ret) { - PERROR("close"); - assert(0); - } - } -error_pipe: - free(memory_map); -alloc_error: - return NULL; -} - -struct shm_object *shm_object_table_alloc(struct shm_object_table *table, - size_t memory_map_size, - enum shm_object_type type, - int stream_fd) -{ - switch (type) { - case SHM_OBJECT_SHM: - return _shm_object_table_alloc_shm(table, memory_map_size, - stream_fd); - case SHM_OBJECT_MEM: - return _shm_object_table_alloc_mem(table, memory_map_size); - default: - assert(0); - } - return NULL; -} - -struct shm_object *shm_object_table_append_shm(struct shm_object_table *table, - int shm_fd, int wakeup_fd, uint32_t stream_nr, - size_t memory_map_size) -{ - struct shm_object *obj; - char *memory_map; - int ret; - - if (table->allocated_len >= table->size) - return NULL; - /* streams _must_ be received in sequential order, else fail. */ - if (stream_nr + 1 != table->allocated_len) - return NULL; - - obj = &table->objects[table->allocated_len]; - - /* wait_fd: set write end of the pipe. */ - obj->wait_fd[0] = -1; /* read end is unset */ - obj->wait_fd[1] = wakeup_fd; - obj->shm_fd = shm_fd; - obj->shm_fd_ownership = 1; - - ret = fcntl(obj->wait_fd[1], F_SETFD, FD_CLOEXEC); - if (ret < 0) { - PERROR("fcntl"); - goto error_fcntl; - } - /* The write end of the pipe needs to be non-blocking */ - ret = fcntl(obj->wait_fd[1], F_SETFL, O_NONBLOCK); - if (ret < 0) { - PERROR("fcntl"); - goto error_fcntl; - } - - /* memory_map: mmap */ - memory_map = mmap(NULL, memory_map_size, PROT_READ | PROT_WRITE, - MAP_SHARED, shm_fd, 0); - if (memory_map == MAP_FAILED) { - PERROR("mmap"); - goto error_mmap; - } - obj->type = SHM_OBJECT_SHM; - obj->memory_map = memory_map; - obj->memory_map_size = memory_map_size; - obj->allocated_len = memory_map_size; - obj->index = table->allocated_len++; - - return obj; - -error_fcntl: -error_mmap: - return NULL; -} - -/* - * Passing ownership of mem to object. - */ -struct shm_object *shm_object_table_append_mem(struct shm_object_table *table, - void *mem, size_t memory_map_size, int wakeup_fd) -{ - struct shm_object *obj; - int ret; - - if (table->allocated_len >= table->size) - return NULL; - obj = &table->objects[table->allocated_len]; - - obj->wait_fd[0] = -1; /* read end is unset */ - obj->wait_fd[1] = wakeup_fd; - obj->shm_fd = -1; - obj->shm_fd_ownership = 0; - - ret = fcntl(obj->wait_fd[1], F_SETFD, FD_CLOEXEC); - if (ret < 0) { - PERROR("fcntl"); - goto error_fcntl; - } - /* The write end of the pipe needs to be non-blocking */ - ret = fcntl(obj->wait_fd[1], F_SETFL, O_NONBLOCK); - if (ret < 0) { - PERROR("fcntl"); - goto error_fcntl; - } - - obj->type = SHM_OBJECT_MEM; - obj->memory_map = mem; - obj->memory_map_size = memory_map_size; - obj->allocated_len = memory_map_size; - obj->index = table->allocated_len++; - - return obj; - -error_fcntl: - return NULL; -} - -static -void shmp_object_destroy(struct shm_object *obj, int consumer) -{ - switch (obj->type) { - case SHM_OBJECT_SHM: - { - int ret, i; - - ret = munmap(obj->memory_map, obj->memory_map_size); - if (ret) { - PERROR("umnmap"); - assert(0); - } - - if (obj->shm_fd_ownership) { - /* Delete FDs only if called from app (not consumer). */ - if (!consumer) { - lttng_ust_lock_fd_tracker(); - ret = close(obj->shm_fd); - if (!ret) { - lttng_ust_delete_fd_from_tracker(obj->shm_fd); - } else { - PERROR("close"); - assert(0); - } - lttng_ust_unlock_fd_tracker(); - } else { - ret = close(obj->shm_fd); - if (ret) { - PERROR("close"); - assert(0); - } - } - } - for (i = 0; i < 2; i++) { - if (obj->wait_fd[i] < 0) - continue; - if (!consumer) { - lttng_ust_lock_fd_tracker(); - ret = close(obj->wait_fd[i]); - if (!ret) { - lttng_ust_delete_fd_from_tracker(obj->wait_fd[i]); - } else { - PERROR("close"); - assert(0); - } - lttng_ust_unlock_fd_tracker(); - } else { - ret = close(obj->wait_fd[i]); - if (ret) { - PERROR("close"); - assert(0); - } - } - } - break; - } - case SHM_OBJECT_MEM: - { - int ret, i; - - for (i = 0; i < 2; i++) { - if (obj->wait_fd[i] < 0) - continue; - if (!consumer) { - lttng_ust_lock_fd_tracker(); - ret = close(obj->wait_fd[i]); - if (!ret) { - lttng_ust_delete_fd_from_tracker(obj->wait_fd[i]); - } else { - PERROR("close"); - assert(0); - } - lttng_ust_unlock_fd_tracker(); - } else { - ret = close(obj->wait_fd[i]); - if (ret) { - PERROR("close"); - assert(0); - } - } - } - free(obj->memory_map); - break; - } - default: - assert(0); - } -} - -void shm_object_table_destroy(struct shm_object_table *table, int consumer) -{ - int i; - - for (i = 0; i < table->allocated_len; i++) - shmp_object_destroy(&table->objects[i], consumer); - free(table); -} - -/* - * zalloc_shm - allocate memory within a shm object. - * - * Shared memory is already zeroed by shmget. - * *NOT* multithread-safe (should be protected by mutex). - * Returns a -1, -1 tuple on error. - */ -struct shm_ref zalloc_shm(struct shm_object *obj, size_t len) -{ - struct shm_ref ref; - struct shm_ref shm_ref_error = { -1, -1 }; - - if (obj->memory_map_size - obj->allocated_len < len) - return shm_ref_error; - ref.index = obj->index; - ref.offset = obj->allocated_len; - obj->allocated_len += len; - return ref; -} - -void align_shm(struct shm_object *obj, size_t align) -{ - size_t offset_len = offset_align(obj->allocated_len, align); - obj->allocated_len += offset_len; -}