2020-12-13 12:04:16 +00:00
|
|
|
#define _POSIX_C_SOURCE 200809L
|
|
|
|
|
2020-12-13 11:08:52 +00:00
|
|
|
#include <shmemq.h>
|
|
|
|
|
2020-12-13 11:32:17 +00:00
|
|
|
#include <fcntl.h>
|
2020-12-13 11:08:52 +00:00
|
|
|
#include <stdlib.h>
|
2020-12-13 11:25:53 +00:00
|
|
|
#include <string.h>
|
2020-12-13 11:32:17 +00:00
|
|
|
#include <sys/mman.h>
|
|
|
|
#include <sys/stat.h>
|
2020-12-13 12:04:16 +00:00
|
|
|
#include <unistd.h>
|
2020-12-13 11:08:52 +00:00
|
|
|
|
2020-12-13 13:41:44 +00:00
|
|
|
enum Shmemq_Error shmemq_delete(struct Shmemq *shmemq)
|
|
|
|
{
|
|
|
|
const enum Shmemq_Error error = shmemq_finish(shmemq);
|
|
|
|
free(shmemq);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum Shmemq_Error shmemq_finish(struct Shmemq *shmemq)
|
|
|
|
{
|
|
|
|
const size_t size =
|
|
|
|
sizeof(struct Shmemq_BufferHeader) +
|
|
|
|
SHMEMQ_FRAME_SIZE * shmemq->buffer->header.frames_count;
|
|
|
|
|
|
|
|
if (munmap(shmemq->buffer, size) != 0) return SHMEMQ_ERROR_FAILED_MUNMAP;
|
|
|
|
shmemq->buffer = NULL;
|
|
|
|
|
|
|
|
if (close(shmemq->shm_id) != 0) return SHMEMQ_ERROR_FAILED_CLOSE;
|
|
|
|
shmemq->shm_id = -1;
|
|
|
|
|
|
|
|
if (shmemq->is_consumer && shm_unlink(shmemq->name) != 0) {
|
|
|
|
return SHMEMQ_ERROR_FAILED_SHM_UNLINK;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SHMEMQ_ERROR_NONE;
|
|
|
|
}
|
|
|
|
|
2020-12-13 11:08:52 +00:00
|
|
|
struct Shmemq *shmemq_new(
|
|
|
|
const char *const name,
|
2020-12-13 12:52:10 +00:00
|
|
|
const bool is_consumer,
|
2020-12-13 11:08:52 +00:00
|
|
|
enum Shmemq_Error *const error_ptr
|
|
|
|
) {
|
|
|
|
struct Shmemq *const shmemq = malloc(sizeof(*shmemq));
|
|
|
|
|
|
|
|
if (!shmemq) {
|
2020-12-13 12:17:47 +00:00
|
|
|
if (error_ptr) *error_ptr = SHMEMQ_ERROR_FAILED_MALLOC;
|
2020-12-13 11:08:52 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-12-13 13:02:01 +00:00
|
|
|
const enum Shmemq_Error error = shmemq_init(shmemq, name, is_consumer);
|
2020-12-13 11:08:52 +00:00
|
|
|
|
|
|
|
if (error_ptr) *error_ptr = error;
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
free(shmemq);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return shmemq;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum Shmemq_Error shmemq_init(
|
|
|
|
struct Shmemq *const shmemq,
|
|
|
|
const char *const name,
|
2020-12-13 13:02:01 +00:00
|
|
|
const bool is_consumer
|
2020-12-13 11:08:52 +00:00
|
|
|
) {
|
2020-12-13 11:25:53 +00:00
|
|
|
if (strlen(name) > SHMEMQ_NAME_SLEN_MAX || name[0] != '/') {
|
2020-12-13 12:17:47 +00:00
|
|
|
return SHMEMQ_ERROR_INVALID_NAME;
|
2020-12-13 11:25:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (const char *chr = &name[1]; *chr; ++chr) {
|
2020-12-13 12:17:47 +00:00
|
|
|
if (*chr == '/') return SHMEMQ_ERROR_INVALID_NAME;
|
2020-12-13 11:25:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
strcpy(shmemq->name, name);
|
|
|
|
|
2020-12-13 14:38:14 +00:00
|
|
|
shmemq->is_consumer = !!is_consumer;
|
2020-12-13 11:25:53 +00:00
|
|
|
|
2020-12-13 11:32:17 +00:00
|
|
|
shmemq->shm_id = shm_open(
|
|
|
|
shmemq->name,
|
2020-12-13 14:15:46 +00:00
|
|
|
O_RDWR | (shmemq->is_consumer ? O_CREAT | O_EXCL : 0),
|
2020-12-13 11:32:17 +00:00
|
|
|
S_IRUSR | S_IWUSR
|
|
|
|
);
|
|
|
|
|
2020-12-13 12:27:23 +00:00
|
|
|
if (shmemq->shm_id == -1) return SHMEMQ_ERROR_FAILED_SHM_OPEN;
|
2020-12-13 11:32:17 +00:00
|
|
|
|
2020-12-13 14:41:07 +00:00
|
|
|
if (ftruncate(shmemq->shm_id, SHMEMQ_BUFFER_SIZE_MIN) != 0) {
|
|
|
|
shm_unlink(shmemq->name);
|
|
|
|
return SHMEMQ_ERROR_FAILED_FTRUNCATE;
|
2020-12-13 12:04:16 +00:00
|
|
|
}
|
|
|
|
|
2020-12-13 12:26:31 +00:00
|
|
|
shmemq->buffer = mmap(
|
|
|
|
NULL,
|
2020-12-13 13:02:01 +00:00
|
|
|
SHMEMQ_BUFFER_SIZE_MIN,
|
2020-12-13 12:26:31 +00:00
|
|
|
PROT_READ | PROT_WRITE,
|
|
|
|
MAP_SHARED,
|
|
|
|
shmemq->shm_id,
|
|
|
|
0
|
|
|
|
);
|
|
|
|
|
|
|
|
if (shmemq->buffer == MAP_FAILED) {
|
|
|
|
shm_unlink(shmemq->name);
|
|
|
|
return SHMEMQ_ERROR_FAILED_MMAP;
|
|
|
|
}
|
2020-12-13 11:25:53 +00:00
|
|
|
|
2020-12-13 14:41:07 +00:00
|
|
|
shmemq->buffer->header.frames_count = 0;
|
|
|
|
shmemq->buffer->header.read_frame_index = 0;
|
|
|
|
shmemq->buffer->header.write_frame_index = 0;
|
2020-12-13 12:36:49 +00:00
|
|
|
|
2020-12-13 11:08:52 +00:00
|
|
|
return SHMEMQ_ERROR_NONE;
|
|
|
|
}
|