diff --git a/userspace/libwr/include/libwr/shmem.h b/userspace/libwr/include/libwr/shmem.h index 0ebca3dca098b668ba38dea69fa53fa95a610408..a7edefa66d56febb8bc02dd15f856cc6372a1029 100644 --- a/userspace/libwr/include/libwr/shmem.h +++ b/userspace/libwr/include/libwr/shmem.h @@ -6,10 +6,11 @@ #define __WRS_SHM_H__ #include <stdint.h> -#define WRS_SHM_FILE "/dev/shm/wrs-shmem" -#define WRS_SHM_SIZE (64*1024) /* each */ +#define WRS_SHM_FILE "/dev/shm/wrs-shmem-%i" +#define WRS_SHM_MIN_SIZE (4*1024) +#define WRS_SHM_MAX_SIZE (256*1024) -/* Every process gets 8 pages (32k) to be safe for the future */ +/* Each process "name" (i.e. id) is added to the filename above */ enum wrs_shm_name { wrs_shm_ptp, wrs_shm_rtu, @@ -25,7 +26,7 @@ struct wrs_shm_head { unsigned long stamp; /* Last modified, w/ CLOCK_MONOTONIC */ unsigned long data_off; /* Where the structure lives */ - int shm_name; /* The enum above, for cross-checking */ + int fd; /* So we can enlarge it using fd */ int pid; /* The current pid owning the area */ unsigned pidsequence; /* Each new pid must increments this */ diff --git a/userspace/libwr/shmem.c b/userspace/libwr/shmem.c index 474ac6e9fc6e4ff09f9e179ee2011e0a4db5265f..58c5c43239f0467229a5a42418cd9bbde707dff2 100644 --- a/userspace/libwr/shmem.c +++ b/userspace/libwr/shmem.c @@ -1,4 +1,5 @@ /* Alessandro Rubini for CERN 2014, LGPL-2.1 or later */ +#include <stdio.h> #include <unistd.h> #include <string.h> #include <errno.h> @@ -18,6 +19,7 @@ void *wrs_shm_get(enum wrs_shm_name name_id, char *name, unsigned long flags) struct wrs_shm_head *head; struct stat stbuf; void *map; + char fname[64]; int write_access = flags & WRS_SHM_WRITE; int fd; @@ -26,20 +28,22 @@ void *wrs_shm_get(enum wrs_shm_name name_id, char *name, unsigned long flags) return NULL; } - fd = open(WRS_SHM_FILE, O_RDWR | O_CREAT | O_SYNC, 0644); + sprintf(fname, WRS_SHM_FILE, name_id); + fd = open(fname, O_RDWR | O_CREAT | O_SYNC, 0644); if (fd < 0) return NULL; /* keep errno */ - /* The file may be too short: enlarge it as needed */ + /* The file may be too short: enlarge it to the minimum size */ + if (fstat(fd, &stbuf) < 0) return NULL; /* keep errno */ - if (stbuf.st_size < WRS_SHM_SIZE * (name_id + 1)) { - lseek(fd, WRS_SHM_SIZE * (name_id + 1) -1, SEEK_SET); + if (stbuf.st_size < WRS_SHM_MIN_SIZE) { + lseek(fd, WRS_SHM_MIN_SIZE - 1, SEEK_SET); write(fd, "", 1); } - map = mmap(0, WRS_SHM_SIZE, + map = mmap(0, WRS_SHM_MAX_SIZE, PROT_READ | (write_access ? PROT_WRITE : 0), - MAP_SHARED, fd, WRS_SHM_SIZE * name_id); + MAP_SHARED, fd, 0); if (map == MAP_FAILED) return NULL; /* keep errno */ if (!write_access) @@ -48,10 +52,11 @@ void *wrs_shm_get(enum wrs_shm_name name_id, char *name, unsigned long flags) /* Init the fields */ head = map; if (head->pid && kill(head->pid, 0) == 0) { - munmap(map, WRS_SHM_SIZE); + munmap(map, WRS_SHM_MAX_SIZE); errno = EBUSY; return NULL; } + head->fd = fd; head->sequence = 1; /* a sort of lock */ head->mapbase = head; strncpy(head->name, name, sizeof(head->name)); @@ -59,7 +64,6 @@ void *wrs_shm_get(enum wrs_shm_name name_id, char *name, unsigned long flags) head->stamp = 0; head->data_off = sizeof(*head); head->data_size = 0; - head->shm_name = name_id; head->pid = getpid(); head->pidsequence++; /* version and size are up to the user (or to allocation) */ @@ -74,9 +78,11 @@ int wrs_shm_put(void *headptr) { struct wrs_shm_head *head = headptr; int err; - if (head->pid == getpid()) + if (head->pid == getpid()) { head->pid = 0; /* mark that we are not writers any more */ - if ((err = munmap(headptr, WRS_SHM_SIZE)) < 0) + close(head->fd); + } + if ((err = munmap(headptr, WRS_SHM_MAX_SIZE)) < 0) return err; return 0; } @@ -89,10 +95,15 @@ void *wrs_shm_alloc(void *headptr, size_t size) if (head->pid != getpid()) return NULL; /* we are not writers */ - if (head->data_off + head->data_size + size > WRS_SHM_SIZE) + if (head->data_off + head->data_size + size > WRS_SHM_MAX_SIZE) return NULL; /* no space left */ nextptr = headptr + head->data_off + head->data_size; head->data_size += (size + 7) & ~7; /* force 8-alignment */ + + /* Before we write to shmem, ensure the backing store exists */ + lseek(head->fd, head->data_off + head->data_size - 1, SEEK_SET); + write(head->fd, "", 1); + memset(nextptr, 0, size); return nextptr; } @@ -102,7 +113,7 @@ void *wrs_shm_follow(void *headptr, void *ptr) { struct wrs_shm_head *head = headptr; - if (ptr < head->mapbase || ptr > head->mapbase + WRS_SHM_SIZE) + if (ptr < head->mapbase || ptr > head->mapbase + WRS_SHM_MAX_SIZE) return NULL; /* not in the area */ return headptr + (ptr - head->mapbase); } diff --git a/userspace/ppsi b/userspace/ppsi index 52fda5e90fd10e42f867b8c21a5fd9e42fb2dbfd..f49685ec07132da80b8aec32a2d50d143d23e13d 160000 --- a/userspace/ppsi +++ b/userspace/ppsi @@ -1 +1 @@ -Subproject commit 52fda5e90fd10e42f867b8c21a5fd9e42fb2dbfd +Subproject commit f49685ec07132da80b8aec32a2d50d143d23e13d