Skip to content

Commit

Permalink
Initial POC CMake MSVC, (not yet done testing)
Browse files Browse the repository at this point in the history
  • Loading branch information
peterino2 committed Jul 10, 2023
1 parent a5e8eae commit a2a63b5
Show file tree
Hide file tree
Showing 16 changed files with 384 additions and 118 deletions.
11 changes: 9 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
cmake_minimum_required(VERSION 2.8.5)
# Copyright (c) 2023 Andrew Kelley
# This file is MIT licensed.
# See http://opensource.org/licenses/MIT

cmake_minimum_required(VERSION 3.0.0)

project(libsoundio C)
set(CMAKE_MODULE_PATH ${libsoundio_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})

Expand All @@ -23,6 +28,7 @@ set(LIBSOUNDIO_VERSION_PATCH 0)
set(LIBSOUNDIO_VERSION "${LIBSOUNDIO_VERSION_MAJOR}.${LIBSOUNDIO_VERSION_MINOR}.${LIBSOUNDIO_VERSION_PATCH}")
message("Configuring libsoundio version ${LIBSOUNDIO_VERSION}")


if(NOT SOUNDIO_STATIC_LIBNAME)
set(SOUNDIO_STATIC_LIBNAME soundio)
endif()
Expand Down Expand Up @@ -203,7 +209,6 @@ if(MSVC)
set(EXAMPLE_CFLAGS "/W4")
set(TEST_CFLAGS "${LIB_CFLAGS}")
set(TEST_LDFLAGS " ")
set(LIBM " ")
else()
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Werror -pedantic")
set(LIB_CFLAGS "-std=c11 -fvisibility=hidden -Wall -Werror=strict-prototypes -Werror=old-style-definition -Werror=missing-prototypes -D_REENTRANT -D_POSIX_C_SOURCE=200809L -Wno-missing-braces")
Expand Down Expand Up @@ -386,3 +391,5 @@ message(
"* CoreAudio (optional) : ${STATUS_COREAUDIO}\n"
"* WASAPI (optional) : ${STATUS_WASAPI}\n"
)


4 changes: 4 additions & 0 deletions example/sio_microphone.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,14 @@ static int prioritized_sample_rates[] = {
};


#ifndef _MSC_VER
__attribute__ ((cold))
__attribute__ ((noreturn))
__attribute__ ((format (printf, 1, 2)))
static void panic(const char *format, ...) {
#else
__declspec(noreturn) static void panic(const char *format, ...) {
#endif
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
Expand Down
6 changes: 6 additions & 0 deletions example/sio_record.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@
#include <string.h>
#include <math.h>
#include <errno.h>

#ifndef _MSC_VER
#include <unistd.h>
#else
#include <Windows.h>
#define sleep(x) Sleep(x * 1000)
#endif

struct RecordContext {
struct SoundIoRingBuffer *ring_buffer;
Expand Down
187 changes: 175 additions & 12 deletions src/atomics.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,23 @@
#ifndef SOUNDIO_ATOMICS_H
#define SOUNDIO_ATOMICS_H

#ifdef __cplusplus
#define SOUNDIO_USE_CPP_ATOMICS
#else // ifdef __cplusplus

#ifdef _MSC_VER
#define SOUNDIO_USE_MSVC_NATIVE_C_ATOMICS
#else
#define SOUNDIO_USE_GNU_ATOMICS
#endif // ifdef _MSC_VER

#endif // ifdef __cplusplus


// Simple wrappers around atomic values so that the compiler will catch it if
// I accidentally use operators such as +, -, += on them.

#ifdef __cplusplus
#ifdef SOUNDIO_USE_CPP_ATOMICS

#include <atomic>

Expand All @@ -35,15 +48,38 @@ struct SoundIoAtomicULong {
std::atomic<unsigned long> x;
};

#define SOUNDIO_ATOMIC_LOAD(a) (a.x.load())
#define SOUNDIO_ATOMIC_FETCH_ADD(a, delta) (a.x.fetch_add(delta))
#define SOUNDIO_ATOMIC_STORE(a, value) (a.x.store(value))
#define SOUNDIO_ATOMIC_EXCHANGE(a, value) (a.x.exchange(value))
#define SOUNDIO_ATOMIC_LOAD_(a) (a.x.load())
#define SOUNDIO_ATOMIC_FETCH_ADD_(a, delta) (a.x.fetch_add(delta))
#define SOUNDIO_ATOMIC_STORE_(a, value) (a.x.store(value))
#define SOUNDIO_ATOMIC_EXCHANGE_(a, value) (a.x.exchange(value))

#define SOUNDIO_ATOMIC_LOAD_BOOL SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_BOOL SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_BOOL SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_BOOL SOUNDIO_ATOMIC_EXCHANGE_

#define SOUNDIO_ATOMIC_LOAD_INT SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_INT SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_INT SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_INT SOUNDIO_ATOMIC_EXCHANGE_

#define SOUNDIO_ATOMIC_LOAD_LONG SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_LONG SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_LONG SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_LONG SOUNDIO_ATOMIC_EXCHANGE_

#define SOUNDIO_ATOMIC_LOAD_ULONG SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_ULONG SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_ULONG SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_ULONG SOUNDIO_ATOMIC_EXCHANGE_

#define SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(a) (a.x.test_and_set())
#define SOUNDIO_ATOMIC_FLAG_CLEAR(a) (a.x.clear())
#define SOUNDIO_ATOMIC_FLAG_INIT ATOMIC_FLAG_INIT

#else
#endif

#ifdef SOUNDIO_USE_GNU_ATOMICS

#include <stdatomic.h>

Expand All @@ -67,14 +103,141 @@ struct SoundIoAtomicULong {
atomic_ulong x;
};

#define SOUNDIO_ATOMIC_LOAD(a) atomic_load(&a.x)
#define SOUNDIO_ATOMIC_FETCH_ADD(a, delta) atomic_fetch_add(&a.x, delta)
#define SOUNDIO_ATOMIC_STORE(a, value) atomic_store(&a.x, value)
#define SOUNDIO_ATOMIC_EXCHANGE(a, value) atomic_exchange(&a.x, value)
#define SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(a) atomic_flag_test_and_set(&a.x)
#define SOUNDIO_ATOMIC_FLAG_CLEAR(a) atomic_flag_clear(&a.x)
#define SOUNDIO_ATOMIC_LOAD_(a) atomic_load(&a.x)
#define SOUNDIO_ATOMIC_FETCH_ADD_(a, delta) atomic_fetch_add(&a.x, delta)
#define SOUNDIO_ATOMIC_STORE_(a, value) atomic_store(&a.x, value)
#define SOUNDIO_ATOMIC_EXCHANGE_(a, value) atomic_exchange(&a.x, value)
#define SOUNDIO_ATOMIC_FLAG_TEST_AND_SET_(a) atomic_flag_test_and_set(&a.x)
#define SOUNDIO_ATOMIC_FLAG_CLEAR_(a) atomic_flag_clear(&a.x)
#define SOUNDIO_ATOMIC_FLAG_INIT ATOMIC_FLAG_INIT

#define SOUNDIO_ATOMIC_LOAD_BOOL SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_BOOL SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_BOOL SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_BOOL SOUNDIO_ATOMIC_EXCHANGE_

#define SOUNDIO_ATOMIC_LOAD_INT SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_INT SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_INT SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_INT SOUNDIO_ATOMIC_EXCHANGE_

#define SOUNDIO_ATOMIC_LOAD_LONG SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_LONG SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_LONG SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_LONG SOUNDIO_ATOMIC_EXCHANGE_

#define SOUNDIO_ATOMIC_LOAD_ULONG SOUNDIO_ATOMIC_LOAD_
#define SOUNDIO_ATOMIC_STORE_ULONG SOUNDIO_ATOMIC_STORE_
#define SOUNDIO_ATOMIC_FETCH_ADD_ULONG SOUNDIO_ATOMIC_FETCH_ADD_
#define SOUNDIO_ATOMIC_EXCHANGE_ULONG SOUNDIO_ATOMIC_EXCHANGE_

#endif

#ifdef SOUNDIO_USE_MSVC_NATIVE_C_ATOMICS
// When building for native msvc, we can leverage builtin atomics.

#ifdef _WIN64
#define SOUNDIO_MSVC_POINTER_SIZE 8
#else
#define SOUNDIO_MSVC_POINTER_SIZE 4
#endif

struct SoundIoAtomicLong {
long x;
};

struct SoundIoAtomicInt {
int x;
};

struct SoundIoAtomicBool {
char x;
};

struct SoundIoAtomicFlag {
long x;
};

struct SoundIoAtomicULong {
unsigned long x;
};

// When sticking to raw C and msvc, we rely on MSVC compiler intrinsics and are unable to
// Automatically deduce types at compile time. Must use the correct macro for the correct function.
//
// No headers needed. We use _Interlocked* family of compiler intrinsics.
// Implementation referenced from the fantastic turf library's `atomic_msvc.h`

// How the living hell is it that to this day and age. msvc does not support typeof which both clang
// and gcc support.
//
// guess this is why c11 in msvc can't implement stdatomic.h right now
#define SOUNDIO_ATOMIC_LOAD_BOOL(a) (char) *((volatile char*) &(a.x))
#define SOUNDIO_ATOMIC_STORE_BOOL(a, value) (*((volatile char*) &(a.x))) = value
#define SOUNDIO_ATOMIC_FETCH_ADD_BOOL(a, delta) _InterlockedExchangeAdd8((volatile char*) (&a.x), delta)
#define SOUNDIO_ATOMIC_EXCHANGE_BOOL(a, value) _InterlockedExchange8((volatile char*) (&a.x), value)

#define SOUNDIO_ATOMIC_LOAD_INT(a) (int) *((volatile int*) &(a.x))
#define SOUNDIO_ATOMIC_STORE_INT(a, value) *((volatile int*) &(a.x)) = value
#define SOUNDIO_ATOMIC_FETCH_ADD_INT(a, delta) _InterlockedExchangeAdd((volatile LONG*) (&a.x), delta)
#define SOUNDIO_ATOMIC_EXCHANGE_INT(a, value) _InterlockedExchange((volatile LONG*) (&a.x), value)

#define SOUNDIO_ATOMIC_LOAD_LONG(a) SoundIoMSVCLoadLong(&a)
#define SOUNDIO_ATOMIC_STORE_LONG(a, value) SoundIoMSVCStoreLong((struct SoundIoAtomicLong*) &a, value)
#define SOUNDIO_ATOMIC_FETCH_ADD_LONG(a, delta) _InterlockedExchangeAdd64((long*) (&a.x), delta)
#define SOUNDIO_ATOMIC_EXCHANGE_LONG(a, value) _InterlockedExchange64((long*) (&a.x), delta)

#define SOUNDIO_ATOMIC_LOAD_ULONG(a) SoundIoMSVCLoadLong(&a)
#define SOUNDIO_ATOMIC_STORE_ULONG(a, value) SoundIoMSVCStoreLong((struct SoundIoAtomicULong*) &a, value)
#define SOUNDIO_ATOMIC_FETCH_ADD_ULONG(a, delta) _InterlockedExchangeAdd64((volatile long*) (&a.x), delta)
#define SOUNDIO_ATOMIC_EXCHANGE_ULONG(a, value) _InterlockedExchange64((volatile long*) (&a.x), delta)

#define SOUNDIO_ATOMIC_FLAG_TEST_AND_SET(a) _interlockedbittestandset(&a.x, 0)
#define SOUNDIO_ATOMIC_FLAG_CLEAR(a) _interlockedbittestandreset(&a.x, 0)
#define SOUNDIO_ATOMIC_FLAG_INIT {1}

#define SOUNDIO_ATOMIC_LOAD(a) error
#define SOUNDIO_ATOMIC_FETCH_ADD(a, delta) error
#define SOUNDIO_ATOMIC_STORE(a, value) error
#define SOUNDIO_ATOMIC_EXCHANGE(a, value) error

static long SoundIoMSVCLoadLong(struct SoundIoAtomicLong* a)
{
#if SOUNDIO_MSVC_POINTER_SIZE == 8
return ((volatile struct SoundIoAtomicLong*) a)->x;
#else

uint64_t result;
__asm {
mov esi, object;
mov ebx, eax;
mov ecx, edx;
lock cmpxchg8b [esi];
mov dword ptr result, eax;
mov dword ptr result[4], edx;
}
return result;

#endif
}

static void SoundIoMSVCStoreLong(struct SoundIoAtomicLong* a, long value)
{
#if SOUNDIO_MSVC_POINTER_SIZE == 8
((volatile struct SoundIoAtomicLong*) a)->x = value;
#else
__asm {
mov esi, object;
mov ebx, dword ptr value;
mov ecx, dword ptr value[4];
retry:
cmpxchg8b [esi];
jne retry;
}
#endif
}

#endif

#endif //SOUNDIO_ATOMICS_H

2 changes: 1 addition & 1 deletion src/channel_layout.c
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ enum SoundIoChannelId soundio_parse_channel_id(const char *str, int str_len) {
const char *alias = channel_names[id][i];
if (!alias)
break;
int alias_len = strlen(alias);
int alias_len = (int) strlen(alias);
if (soundio_streql(alias, alias_len, str, str_len))
return (enum SoundIoChannelId)id;
}
Expand Down
Loading

0 comments on commit a2a63b5

Please sign in to comment.