SCP: Added generic primitives to create named shared memory regions which can be used interprocess memory sharing

This is a basic starting point to create the memory regions.  At some point synchronization primitives will probably also be necessary.
This commit is contained in:
Mark Pizzolato 2015-03-17 22:11:07 -07:00
parent 50d1407c97
commit 590895bfe5
2 changed files with 113 additions and 0 deletions

110
sim_fio.c
View file

@ -50,6 +50,9 @@
sim_fsize_name_ex - get file size as a t_offset of named file
sim_buf_copy_swapped - copy data swapping elements along the way
sim_buf_swap_data - swap data elements inplace in buffer
sim_shmem_open create or attach to a shared memory region
sim_shmem_close close a shared memory region
sim_fopen and sim_fseek are OS-dependent. The other routines are not.
sim_fsize is always a 32b routine (it is used only with small capacity random
@ -375,6 +378,50 @@ int sim_set_fifo_nonblock (FILE *fptr)
return -1;
}
struct SHMEM {
HANDLE hMapping;
size_t shm_size;
void *shm_base;
};
t_stat sim_shmem_open (const char *name, size_t size, SHMEM **shmem, void **addr)
{
*shmem = (SHMEM *)calloc (1, sizeof(**shmem));
if (*shmem == NULL)
return SCPE_MEM;
(*shmem)->hMapping = INVALID_HANDLE_VALUE;
(*shmem)->shm_size = size;
(*shmem)->shm_base = NULL;
(*shmem)->hMapping = CreateFileMappingA (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (DWORD)size, name);
if ((*shmem)->hMapping == INVALID_HANDLE_VALUE) {
sim_shmem_close (*shmem);
*shmem = NULL;
return SCPE_OPENERR;
}
(*shmem)->shm_base = MapViewOfFile ((*shmem)->hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if ((*shmem)->shm_base == NULL) {
sim_shmem_close (*shmem);
*shmem = NULL;
return SCPE_OPENERR;
}
*addr = (*shmem)->shm_base;
return SCPE_OK;
}
void sim_shmem_close (SHMEM *shmem)
{
if (shmem == NULL)
return;
if (shmem->shm_base != NULL)
UnmapViewOfFile (shmem->shm_base);
if (shmem->hMapping != INVALID_HANDLE_VALUE)
CloseHandle (shmem->hMapping);
free (shmem);
}
#else /* !defined(_WIN32) */
#include <unistd.h>
int sim_set_fsize (FILE *fptr, t_addr size)
@ -400,4 +447,67 @@ if ((stbuf.st_mode & S_IFIFO)) {
return -1;
}
#include <sys/mman.h>
struct SHMEM {
int shm_fd;
size_t shm_size;
void *shm_base;
};
t_stat sim_shmem_open (const char *name, size_t size, SHMEM **shmem, void **addr)
{
*shmem = (SHMEM *)calloc (1, sizeof(**shmem));
*addr = NULL;
if (*shmem == NULL)
return SCPE_MEM;
(*shmem)->shm_base = MAP_FAILED;
(*shmem)->shm_size = size;
(*shmem)->shm_fd = shm_open (name, O_RDWR, 0);
if ((*shmem)->shm_fd == -1) {
(*shmem)->shm_fd = shm_open (name, O_CREAT | O_RDWR, 0660);
if ((*shmem)->shm_fd == -1) {
sim_shmem_close (*shmem);
*shmem = NULL;
return SCPE_OPENERR;
}
if (ftruncate((*shmem)->shm_fd, size)) {
sim_shmem_close (*shmem);
*shmem = NULL;
return SCPE_OPENERR;
}
}
else {
struct stat statb;
if ((fstat ((*shmem)->shm_fd, &statb)) ||
(statb.st_size != (*shmem)->shm_size)) {
sim_shmem_close (*shmem);
*shmem = NULL;
return SCPE_OPENERR;
}
}
(*shmem)->shm_base = mmap(NULL, (*shmem)->shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, (*shmem)->shm_fd, 0);
if ((*shmem)->shm_base == MAP_FAILED) {
sim_shmem_close (*shmem);
*shmem = NULL;
return SCPE_OPENERR;
}
*addr = (*shmem)->shm_base;
return SCPE_OK;
}
void sim_shmem_close (SHMEM *shmem)
{
if (shmem == NULL)
return;
if (shmem->shm_base != MAP_FAILED)
munmap (shmem->shm_base, shmem->shm_size);
if (shmem->shm_fd != -1)
close (shmem->shm_fd);
free (shmem);
}
#endif

View file

@ -64,6 +64,9 @@ t_offset sim_fsize_ex (FILE *fptr);
t_offset sim_fsize_name_ex (char *fname);
void sim_buf_swap_data (void *bptr, size_t size, size_t count);
void sim_buf_copy_swapped (void *dptr, void *bptr, size_t size, size_t count);
typedef struct SHMEM SHMEM;
t_stat sim_shmem_open (const char *name, size_t size, SHMEM **shmem, void **addr);
void sim_shmem_close (SHMEM *shmem);
extern t_bool sim_taddr_64; /* t_addr is > 32b and Large File Support available */
extern t_bool sim_toffset_64; /* Large File (>2GB) file I/O support */