mirror of
https://github.com/Ryujinx/libsoundio.git
synced 2024-12-22 18:45:29 +00:00
ring buffer works on windows
This commit is contained in:
parent
2b0744816f
commit
5048d7aa57
|
@ -85,8 +85,8 @@ endif()
|
|||
set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
|
||||
set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
|
||||
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wno-unused-variable")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wno-unused-variable")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wno-unused-variable -Wno-unused-but-set-variable")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wno-unused-variable -Wno-unused-but-set-variable")
|
||||
|
||||
|
||||
set(LIB_CFLAGS "-std=c++11 -fno-exceptions -fno-rtti -Werror -Wall -Werror=strict-prototypes -Werror=old-style-definition -Werror=missing-prototypes -fdiagnostics-color=auto")
|
||||
|
|
117
src/os.cpp
117
src/os.cpp
|
@ -50,8 +50,14 @@
|
|||
#include <mmsystem.h>
|
||||
|
||||
#else
|
||||
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#ifndef MAP_ANONYMOUS
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__MACH__)
|
||||
|
@ -116,14 +122,14 @@ struct SoundIoOsCond {
|
|||
|
||||
#if defined(SOUNDIO_OS_WINDOWS)
|
||||
INIT_ONCE win32_init_once = INIT_ONCE_STATIC_INIT;
|
||||
static double win32_time_resolution;
|
||||
SYSTEM_INFO win32_system_info;
|
||||
#else
|
||||
atomic_bool initialized = ATOMIC_VAR_INIT(false);
|
||||
pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
|
||||
#if defined(SOUNDIO_OS_WINDOWS)
|
||||
static double win32_time_resolution;
|
||||
#endif
|
||||
static int page_size;
|
||||
|
||||
double soundio_os_get_time(void) {
|
||||
#if defined(SOUNDIO_OS_WINDOWS)
|
||||
|
@ -558,6 +564,10 @@ static void internal_init(void) {
|
|||
} else {
|
||||
win32_panic("unable to initialize high precision timer: %s");
|
||||
}
|
||||
GetSystemInfo(&win32_system_info);
|
||||
page_size = win32_system_info.dwAllocationGranularity;
|
||||
#else
|
||||
page_size = getpagesize();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -589,3 +599,104 @@ void soundio_os_init(void) {
|
|||
assert_no_err(pthread_mutex_unlock(&init_mutex));
|
||||
#endif
|
||||
}
|
||||
|
||||
int soundio_os_page_size(void) {
|
||||
return page_size;
|
||||
}
|
||||
|
||||
int soundio_os_create_mirrored_memory(size_t *capacity, char **out_address) {
|
||||
*out_address = nullptr;
|
||||
size_t requested_capacity = *capacity;
|
||||
|
||||
size_t actual_capacity = (requested_capacity / page_size) * page_size;
|
||||
if (actual_capacity < requested_capacity)
|
||||
actual_capacity += page_size;
|
||||
|
||||
#if defined(SOUNDIO_OS_WINDOWS)
|
||||
BOOL ok;
|
||||
HANDLE hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, actual_capacity * 2, NULL);
|
||||
if (!hMapFile)
|
||||
return SoundIoErrorNoMem;
|
||||
|
||||
for (;;) {
|
||||
// find a free address space with the correct size
|
||||
char *address = (char*)MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, actual_capacity * 2);
|
||||
if (!address) {
|
||||
ok = CloseHandle(hMapFile);
|
||||
assert(ok);
|
||||
return SoundIoErrorNoMem;
|
||||
}
|
||||
|
||||
// found a big enough address space. hopefully it will remain free
|
||||
// while we map to it. if not, we'll try again.
|
||||
ok = UnmapViewOfFile(address);
|
||||
assert(ok);
|
||||
|
||||
char *addr1 = (char*)MapViewOfFileEx(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, actual_capacity, address);
|
||||
if (addr1 != address) {
|
||||
DWORD err = GetLastError();
|
||||
if (err == ERROR_INVALID_ADDRESS) {
|
||||
continue;
|
||||
} else {
|
||||
ok = CloseHandle(hMapFile);
|
||||
assert(ok);
|
||||
return SoundIoErrorNoMem;
|
||||
}
|
||||
}
|
||||
|
||||
char *addr2 = (char*)MapViewOfFileEx(hMapFile, FILE_MAP_WRITE, 0, 0,
|
||||
actual_capacity, address + actual_capacity);
|
||||
if (addr2 != address + actual_capacity) {
|
||||
ok = UnmapViewOfFile(addr1);
|
||||
assert(ok);
|
||||
|
||||
DWORD err = GetLastError();
|
||||
if (err == ERROR_INVALID_ADDRESS) {
|
||||
continue;
|
||||
} else {
|
||||
ok = CloseHandle(hMapFile);
|
||||
assert(ok);
|
||||
return SoundIoErrorNoMem;
|
||||
}
|
||||
}
|
||||
|
||||
*out_address = address;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
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);
|
||||
if (other_address != address) {
|
||||
munmap(address, 2 * actual_capacity);
|
||||
return SoundIoErrorNoMem;
|
||||
}
|
||||
|
||||
other_address = (char*)mmap(address + actual_capacity, actual_capacity,
|
||||
PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_FIXED|MAP_SHARED, -1, 0);
|
||||
if (other_address != address + actual_capacity) {
|
||||
munmap(address, 2 * actual_capacity);
|
||||
return SoundIoErrorNoMem;
|
||||
}
|
||||
|
||||
*out_address = address;
|
||||
|
||||
#endif
|
||||
|
||||
*capacity = actual_capacity;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void soundio_os_destroy_mirrored_memory(char *address, size_t capacity) {
|
||||
if (!address)
|
||||
return;
|
||||
#if defined(SOUNDIO_OS_WINDOWS)
|
||||
#else
|
||||
int err = munmap(address, 2 * capacity);
|
||||
assert(!err);
|
||||
#endif
|
||||
}
|
||||
|
|
11
src/os.hpp
11
src/os.hpp
|
@ -9,6 +9,7 @@
|
|||
#define SOUNDIO_OS_HPP
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
// safe to call from any thread(s) multiple times, but
|
||||
|
@ -47,4 +48,14 @@ void soundio_os_cond_timed_wait(struct SoundIoOsCond *cond,
|
|||
void soundio_os_cond_wait(struct SoundIoOsCond *cond,
|
||||
struct SoundIoOsMutex *locked_mutex);
|
||||
|
||||
|
||||
int soundio_os_page_size(void);
|
||||
|
||||
// capacity is replaced with actual capacity which might be modified to be
|
||||
// a multiple of the system page size
|
||||
int soundio_os_create_mirrored_memory(size_t *capacity, char **out_address);
|
||||
// capacity should be the actual capacity value that was given via
|
||||
// soundio_os_create_mirrored_memory
|
||||
void soundio_os_destroy_mirrored_memory(char *address, size_t capacity);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -8,17 +8,9 @@
|
|||
#include "ring_buffer.hpp"
|
||||
#include "soundio.hpp"
|
||||
#include "util.hpp"
|
||||
#include "os.hpp"
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef MAP_ANONYMOUS
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#endif
|
||||
|
||||
struct SoundIoRingBuffer *soundio_ring_buffer_create(struct SoundIo *soundio, int requested_capacity) {
|
||||
SoundIoRingBuffer *rb = create<SoundIoRingBuffer>();
|
||||
|
@ -83,34 +75,20 @@ void soundio_ring_buffer_clear(struct SoundIoRingBuffer *rb) {
|
|||
}
|
||||
|
||||
int soundio_ring_buffer_init(struct SoundIoRingBuffer *rb, int requested_capacity) {
|
||||
// round size up to the nearest power of two
|
||||
int pow2_size = powf(2, ceilf(log2(requested_capacity)));
|
||||
// at minimum must be page size
|
||||
int page_size = getpagesize();
|
||||
rb->capacity = max(pow2_size, page_size);
|
||||
int err;
|
||||
size_t capacity = requested_capacity;
|
||||
if ((err = soundio_os_create_mirrored_memory(&capacity, &rb->address))) {
|
||||
soundio_ring_buffer_deinit(rb);
|
||||
return err;
|
||||
}
|
||||
|
||||
rb->capacity = capacity;
|
||||
rb->write_offset = 0;
|
||||
rb->read_offset = 0;
|
||||
|
||||
rb->address = (char*)mmap(NULL, rb->capacity * 2, PROT_NONE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
if (rb->address == MAP_FAILED)
|
||||
return SoundIoErrorNoMem;
|
||||
|
||||
char *other_address = (char*)mmap(rb->address, rb->capacity,
|
||||
PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_FIXED|MAP_SHARED, -1, 0);
|
||||
if (other_address != rb->address)
|
||||
return SoundIoErrorNoMem;
|
||||
|
||||
other_address = (char*)mmap(rb->address + rb->capacity, rb->capacity,
|
||||
PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_FIXED|MAP_SHARED, -1, 0);
|
||||
if (other_address != rb->address + rb->capacity)
|
||||
return SoundIoErrorNoMem;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void soundio_ring_buffer_deinit(struct SoundIoRingBuffer *rb) {
|
||||
if (munmap(rb->address, 2 * rb->capacity))
|
||||
soundio_panic("munmap failed: %s", strerror(errno));
|
||||
soundio_os_destroy_mirrored_memory(rb->address, rb->capacity);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
struct SoundIoRingBuffer {
|
||||
char *address;
|
||||
long capacity;
|
||||
int capacity;
|
||||
atomic_long write_offset;
|
||||
atomic_long read_offset;
|
||||
};
|
||||
|
|
|
@ -51,14 +51,16 @@ static void test_ring_buffer_basic(void) {
|
|||
SoundIoRingBuffer *rb = soundio_ring_buffer_create(soundio, 10);
|
||||
assert(rb);
|
||||
|
||||
assert(soundio_ring_buffer_capacity(rb) == 4096);
|
||||
int page_size = soundio_os_page_size();
|
||||
|
||||
assert(soundio_ring_buffer_capacity(rb) == page_size);
|
||||
|
||||
char *write_ptr = soundio_ring_buffer_write_ptr(rb);
|
||||
int amt = sprintf(write_ptr, "hello") + 1;
|
||||
soundio_ring_buffer_advance_write_ptr(rb, amt);
|
||||
|
||||
assert(soundio_ring_buffer_fill_count(rb) == amt);
|
||||
assert(soundio_ring_buffer_free_count(rb) == 4096 - amt);
|
||||
assert(soundio_ring_buffer_free_count(rb) == page_size - amt);
|
||||
|
||||
char *read_ptr = soundio_ring_buffer_read_ptr(rb);
|
||||
|
||||
|
@ -69,8 +71,8 @@ static void test_ring_buffer_basic(void) {
|
|||
assert(soundio_ring_buffer_fill_count(rb) == 0);
|
||||
assert(soundio_ring_buffer_free_count(rb) == soundio_ring_buffer_capacity(rb));
|
||||
|
||||
soundio_ring_buffer_advance_write_ptr(rb, 4094);
|
||||
soundio_ring_buffer_advance_read_ptr(rb, 4094);
|
||||
soundio_ring_buffer_advance_write_ptr(rb, page_size - 2);
|
||||
soundio_ring_buffer_advance_read_ptr(rb, page_size - 2);
|
||||
amt = sprintf(soundio_ring_buffer_write_ptr(rb), "writing past the end") + 1;
|
||||
soundio_ring_buffer_advance_write_ptr(rb, amt);
|
||||
|
||||
|
|
Loading…
Reference in a new issue