#include "shared_memory.h" #if !defined(_WIN32) || defined(__CYGWIN__) # include # include # include # include # include # include # include kit_shared_memory_t kit_shared_memory_open(kit_str_t name, i64 size, i32 mode) { kit_shared_memory_t mem; memset(&mem, 0, sizeof mem); assert(size > 0); assert(name.size > 0); assert(name.size + 1 <= NAME_MAX); assert(name.values != NULL); if (size <= 0) { mem.status = KIT_ERROR_INVALID_SIZE; return mem; } if (name.size <= 0) { mem.status = KIT_ERROR_INVALID_NAME; return mem; } if (name.size + 1 > NAME_MAX) { mem.status = KIT_ERROR_NAME_TOO_LONG; return mem; } for (i64 i = 0; i < name.size; i++) if (name.values[i] == '/' || name.values[i] == '\\') { mem.status = KIT_ERROR_INVALID_NAME; return mem; } mem._name[0] = '/'; memcpy(mem._name + 1, name.values, name.size); mem._name[1 + name.size] = '\0'; i32 fd = shm_open(mem._name, mode == KIT_SHARED_MEMORY_CREATE ? O_RDWR | O_CREAT | O_EXCL : O_RDWR, mode == KIT_SHARED_MEMORY_CREATE ? 0660 : 0); if (fd == -1) { mem.status = KIT_ERROR_OPEN_FAILED; return mem; } if (mode == KIT_SHARED_MEMORY_CREATE && ftruncate(fd, size) == -1) { shm_unlink(mem._name); assert(0); mem.status = KIT_ERROR_TRUNCATE_FAILED; return mem; } void *p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); close(fd); if (p == MAP_FAILED) { shm_unlink(mem._name); mem.status = KIT_ERROR_MAP_FAILED; return mem; } mem.status = KIT_OK; mem.size = size; mem.bytes = (u8 *) p; mem._owned = (mode == KIT_SHARED_MEMORY_CREATE); return mem; } s32 kit_shared_memory_close(kit_shared_memory_t *mem) { assert(mem != NULL); if (mem == NULL) return KIT_ERROR_INVALID_ARGUMENT; s32 status = KIT_OK; if (munmap(mem->bytes, mem->size) != 0) status |= KIT_ERROR_UNMAP_FAILED; if (mem->_owned && shm_unlink(mem->_name) != 0) status |= KIT_ERROR_UNLINK_FAILED; return status; } s32 kit_shared_memory_clean(kit_str_t name) { assert(name.size > 0); assert(name.size + 1 <= NAME_MAX); assert(name.values != NULL); if (name.size <= 0) return KIT_ERROR_INVALID_NAME; if (name.size + 1 > NAME_MAX) return KIT_ERROR_NAME_TOO_LONG; for (i64 i = 0; i < name.size; i++) if (name.values[i] == '/' || name.values[i] == '\\') return KIT_ERROR_INVALID_NAME; char buf[NAME_MAX + 1] = "/"; memcpy(buf + 1, name.values, name.size); buf[1 + name.size] = '\0'; if (shm_unlink(buf) != 0) return KIT_ERROR_UNLINK_FAILED; return KIT_OK; } #endif