diff --git a/src/os.cpp b/src/os.cpp index 742e747..c23fd65 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -668,26 +668,56 @@ int soundio_os_init_mirrored_memory(struct SoundIoOsMirroredMemory *mem, size_t break; } #else + char shm_path[] = "/dev/shm/soundio-XXXXXX"; + char tmp_path[] = "/tmp/soundio-XXXXXX"; + char *chosen_path; + + int fd = mkstemp(shm_path); + if (fd < 0) { + fd = mkstemp(tmp_path); + if (fd < 0) { + return SoundIoErrorSystemResources; + } else { + chosen_path = tmp_path; + } + } else { + chosen_path = shm_path; + } + + if (unlink(chosen_path)) { + close(fd); + return SoundIoErrorSystemResources; + } + + if (ftruncate(fd, actual_capacity)) { + close(fd); + return SoundIoErrorSystemResources; + } + char *address = (char*)mmap(NULL, actual_capacity * 2, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); if (address == MAP_FAILED) return SoundIoErrorNoMem; char *other_address = (char*)mmap(address, actual_capacity, PROT_READ|PROT_WRITE, - MAP_ANONYMOUS|MAP_FIXED|MAP_SHARED, -1, 0); + MAP_FIXED|MAP_SHARED, fd, 0); if (other_address != address) { munmap(address, 2 * actual_capacity); + close(fd); return SoundIoErrorNoMem; } other_address = (char*)mmap(address + actual_capacity, actual_capacity, - PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_FIXED|MAP_SHARED, -1, 0); + PROT_READ|PROT_WRITE, MAP_FIXED|MAP_SHARED, fd, 0); if (other_address != address + actual_capacity) { munmap(address, 2 * actual_capacity); + close(fd); return SoundIoErrorNoMem; } mem->address = address; + if (close(fd)) + return SoundIoErrorSystemResources; #endif mem->capacity = actual_capacity; diff --git a/test/unit_tests.cpp b/test/unit_tests.cpp index d8a72c4..742df29 100644 --- a/test/unit_tests.cpp +++ b/test/unit_tests.cpp @@ -15,7 +15,7 @@ static inline void ok_or_panic(int err) { } static void test_os_get_time(void) { - soundio_os_init(); + ok_or_panic(soundio_os_init()); double prev_time = soundio_os_get_time(); for (int i = 0; i < 1000; i += 1) { double time = soundio_os_get_time(); @@ -165,6 +165,24 @@ static void test_ring_buffer_threaded(void) { soundio_destroy(soundio); } +static void test_mirrored_memory(void) { + struct SoundIoOsMirroredMemory mem; + ok_or_panic(soundio_os_init()); + + static const int requested_bytes = 1024; + ok_or_panic(soundio_os_init_mirrored_memory(&mem, requested_bytes)); + const int size_bytes = mem.capacity; + + for (int i = 0; i < size_bytes; i += 1) { + mem.address[i] = rand() % CHAR_MAX; + } + for (int i = 0; i < size_bytes; i += 1) { + assert(mem.address[i] == mem.address[size_bytes+i]); + } + + soundio_os_deinit_mirrored_memory(&mem); +} + struct Test { const char *name; void (*fn)(void); @@ -175,6 +193,7 @@ static struct Test tests[] = { {"create output stream", test_create_outstream}, {"ring buffer basic", test_ring_buffer_basic}, {"ring buffer threaded", test_ring_buffer_threaded}, + {"mirrored memory", test_mirrored_memory}, {NULL, NULL}, };