Fix MacOS and POSIX semaphores related issues

Recently got a MacBook Pro and decided to check how things build on
MacOS. Discovered that POSIX unnamed semaphores weren't implemented, so
I reimplemented them with conditional variable and mutex.

Additionally, fixed scripts and CMake on MacOS
This commit is contained in:
2025-04-25 22:38:33 +03:00
parent 27ad496ca6
commit 48ddd91dd4
6 changed files with 189 additions and 21 deletions

View File

@@ -22,12 +22,12 @@ else()
endif() endif()
set(CMAKE_C_FLAGS_ASAN set(CMAKE_C_FLAGS_ASAN
"${CMAKE_C_FLAGS_DEBUG} -fsanitize=address,undefined -fno-omit-frame-pointer" CACHE STRING "${CMAKE_C_FLAGS_DEBUG} -fsanitize=address,undefined -fno-omit-frame-pointer -Wno-deprecated-declarations" CACHE STRING
"Flags used by the C compiler for Asan build type or configuration." FORCE "Flags used by the C compiler for Asan build type or configuration." FORCE
) )
set(CMAKE_CXX_FLAGS_ASAN set(CMAKE_CXX_FLAGS_ASAN
"${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address,undefined -fno-omit-frame-pointer" CACHE STRING "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address,undefined -fno-omit-frame-pointer -Wno-deprecated-declarations" CACHE STRING
"Flags used by the C++ compiler for Asan build type or configuration." FORCE "Flags used by the C++ compiler for Asan build type or configuration." FORCE
) )
@@ -60,6 +60,14 @@ if(ENABLE_LTO)
message(STATUS "IPO/LTO enabled") message(STATUS "IPO/LTO enabled")
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
endif() endif()
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
message(NOTICE "WARNING: IPO/LTO might cause issues while debugging")
endif()
endif()
if(ENABLE_MT)
message(STATUS "Multithreading enabled")
endif() endif()
# Enable testing # Enable testing
@@ -91,22 +99,22 @@ set(BH_SOURCE
src/Math/Vec4f.c src/Math/Vec4f.c
src/Math/Vec4i.c src/Math/Vec4i.c
src/Queue.c src/Queue.c
src/Util.c
src/String/Int.c
src/String/Float.c src/String/Float.c
src/String/Int.c
src/String/Unicode.c src/String/Unicode.c
src/Util.c
) )
set(BH_HEADER set(BH_HEADER
include/BH/Common.h
include/BH/Algo.h include/BH/Algo.h
include/BH/Args.h include/BH/Args.h
include/BH/Common.h
include/BH/Hashmap.h include/BH/Hashmap.h
include/BH/IO.h include/BH/IO.h
include/BH/Math.h include/BH/Math.h
include/BH/Queue.h include/BH/Queue.h
include/BH/Util.h
include/BH/Thread.h include/BH/Thread.h
include/BH/Util.h
) )
set(BH_SOURCE_DUMMY set(BH_SOURCE_DUMMY
@@ -122,12 +130,12 @@ set(BH_SOURCE_POSIX
) )
set(BH_SOURCE_WIN32_MT set(BH_SOURCE_WIN32_MT
src/Platform/Spinlock.c
src/Platform/Win32/Condition.c src/Platform/Win32/Condition.c
src/Platform/Win32/Mutex.c src/Platform/Win32/Mutex.c
src/Platform/Win32/Semaphore.c src/Platform/Win32/Semaphore.c
src/Platform/Win32/Thread.c src/Platform/Win32/Thread.c
src/Platform/Win32/Tss.c src/Platform/Win32/Tss.c
src/Platform/Spinlock.c
) )
set(BH_HEADER_WIN32_MT set(BH_HEADER_WIN32_MT

View File

@@ -2,6 +2,8 @@
SET(CMAKE_SYSTEM_NAME Windows) SET(CMAKE_SYSTEM_NAME Windows)
SET(CMAKE_SYSTEM_PROCESSOR i686) SET(CMAKE_SYSTEM_PROCESSOR i686)
# Check path
if(EXISTS /usr/bin/i686-w64-mingw32-gcc)
# which compilers to use for C and C++ and ASM-ATT # which compilers to use for C and C++ and ASM-ATT
SET(CMAKE_C_COMPILER /usr/bin/i686-w64-mingw32-gcc) SET(CMAKE_C_COMPILER /usr/bin/i686-w64-mingw32-gcc)
SET(CMAKE_CXX_COMPILER /usr/bin/i686-w64-mingw32-g++) SET(CMAKE_CXX_COMPILER /usr/bin/i686-w64-mingw32-g++)
@@ -9,6 +11,15 @@ SET(CMAKE_ASM-ATT_COMPILER /usr/bin/i686-w64-mingw32-as)
# here is the target environment located # here is the target environment located
SET(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32) SET(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32)
elseif(EXISTS /usr/local/opt/mingw-w64/toolchain-i686/bin/i686-w64-mingw32-gcc)
# which compilers to use for C and C++ and ASM-ATT
SET(CMAKE_C_COMPILER /usr/local/opt/mingw-w64/toolchain-i686/bin/i686-w64-mingw32-gcc)
SET(CMAKE_CXX_COMPILER /usr/local/opt/mingw-w64/toolchain-i686/bin/i686-w64-mingw32-g++)
SET(CMAKE_ASM-ATT_COMPILER /usr/local/opt/mingw-w64/toolchain-i686/bin/i686-w64-mingw32-as)
# here is the target environment located
SET(CMAKE_FIND_ROOT_PATH /usr/local/opt/mingw-w64/toolchain-i686/i686-w64-mingw32)
endif()
# adjust the default behaviour of the FIND_XXX() commands: # adjust the default behaviour of the FIND_XXX() commands:
# search headers and libraries in the target environment, search # search headers and libraries in the target environment, search

View File

@@ -2,6 +2,9 @@
SET(CMAKE_SYSTEM_NAME Windows) SET(CMAKE_SYSTEM_NAME Windows)
SET(CMAKE_SYSTEM_PROCESSOR x86_64) SET(CMAKE_SYSTEM_PROCESSOR x86_64)
# Check path
if(EXISTS /usr/bin/x86_64-w64-mingw32-gcc)
# which compilers to use for C and C++ and ASM-ATT # which compilers to use for C and C++ and ASM-ATT
SET(CMAKE_C_COMPILER /usr/bin/x86_64-w64-mingw32-gcc) SET(CMAKE_C_COMPILER /usr/bin/x86_64-w64-mingw32-gcc)
SET(CMAKE_CXX_COMPILER /usr/bin/x86_64-w64-mingw32-g++) SET(CMAKE_CXX_COMPILER /usr/bin/x86_64-w64-mingw32-g++)
@@ -9,6 +12,15 @@ SET(CMAKE_ASM-ATT_COMPILER /usr/bin/x86_64-w64-mingw32-as)
# here is the target environment located # here is the target environment located
SET(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) SET(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32)
elseif(EXISTS /usr/local/opt/mingw-w64/toolchain-x86_64/bin/x86_64-w64-mingw32-gcc)
# which compilers to use for C and C++ and ASM-ATT
SET(CMAKE_C_COMPILER /usr/local/opt/mingw-w64/toolchain-x86_64/bin/x86_64-w64-mingw32-gcc)
SET(CMAKE_CXX_COMPILER /usr/local/opt/mingw-w64/toolchain-x86_64/bin/x86_64-w64-mingw32-g++)
SET(CMAKE_ASM-ATT_COMPILER /usr/local/opt/mingw-w64/toolchain-x86_64/bin/x86_64-w64-mingw32-as)
# here is the target environment located
SET(CMAKE_FIND_ROOT_PATH /usr/local/opt/mingw-w64/toolchain-x86_64/x86_64-w64-mingw32)
endif()
# adjust the default behaviour of the FIND_XXX() commands: # adjust the default behaviour of the FIND_XXX() commands:
# search headers and libraries in the target environment, search # search headers and libraries in the target environment, search

View File

@@ -5,6 +5,7 @@
#include <time.h> #include <time.h>
#if (_POSIX_SEMAPHORES >= 200112L)
BH_Semaphore *BH_SemaphoreNew(int value) BH_Semaphore *BH_SemaphoreNew(int value)
{ {
BH_Semaphore *semaphore; BH_Semaphore *semaphore;
@@ -70,3 +71,125 @@ int BH_SemaphoreWaitFor(BH_Semaphore *semaphore,
default: return BH_ERROR; default: return BH_ERROR;
} }
} }
#else
BH_Semaphore *BH_SemaphoreNew(int value)
{
BH_Semaphore *semaphore;
/* Allocate space for mutex and initialize it */
semaphore = malloc(sizeof(BH_Semaphore));
if (semaphore)
{
semaphore->count = value;
semaphore->waiters = 0;
if (pthread_mutex_init(&semaphore->mutex, NULL))
{
free(semaphore);
return NULL;
}
if (pthread_cond_init(&semaphore->condition, NULL))
{
pthread_mutex_destroy(&semaphore->mutex);
free(semaphore);
return NULL;
}
}
return semaphore;
}
void BH_SemaphoreFree(BH_Semaphore *semaphore)
{
/* Destroy condition variable and mutex */
pthread_cond_destroy(&semaphore->condition);
pthread_mutex_destroy(&semaphore->mutex);
free(semaphore);
}
int BH_SemaphorePost(BH_Semaphore *semaphore)
{
/* Increase semaphore value */
pthread_mutex_lock(&semaphore->mutex);
semaphore->count++;
if (semaphore->waiters)
pthread_cond_signal(&semaphore->condition);
pthread_mutex_unlock(&semaphore->mutex);
return BH_OK;
}
int BH_SemaphoreWait(BH_Semaphore *semaphore)
{
int result;
/* Wait until semaphore count is not zero */
result = BH_ERROR;
pthread_mutex_lock(&semaphore->mutex);
semaphore->waiters++;
while (!semaphore->count)
pthread_cond_wait(&semaphore->condition, &semaphore->mutex);
semaphore->waiters--;
semaphore->count--;
pthread_mutex_unlock(&semaphore->mutex);
return result;
}
int BH_SemaphoreWaitTry(BH_Semaphore *semaphore)
{
int result;
result = BH_OK;
/* Check if semaphore count is not zero and decrement it */
pthread_mutex_lock(&semaphore->mutex);
if (!semaphore->count)
result = BH_ERROR;
else
semaphore->count--;
pthread_mutex_unlock(&semaphore->mutex);
return result;
}
int BH_SemaphoreWaitFor(BH_Semaphore *semaphore,
uint32_t timeout)
{
int result;
struct timespec ts;
/* Setup timeout */
ts.tv_sec = timeout / 1000;
ts.tv_nsec = (timeout - ts.tv_sec * 1000) * 1000000;
result = BH_OK;
/* Wait until semaphore count is not zero or timeout */
pthread_mutex_lock(&semaphore->mutex);
semaphore->waiters++;
while (!semaphore->count && result == BH_OK)
{
switch (pthread_cond_timedwait(&semaphore->condition, &semaphore->mutex, &ts))
{
case 0: result = BH_OK; break;
case ETIMEDOUT: result = BH_TIMEOUT; break;
default: result = BH_ERROR; break;
}
}
semaphore->waiters--;
/* If everything went fine - decrement semaphore counter */
if (!result)
semaphore->count--;
pthread_mutex_unlock(&semaphore->mutex);
return result;
}
#endif

View File

@@ -3,8 +3,8 @@
#include <BH/Thread.h> #include <BH/Thread.h>
#include <unistd.h>
#include <pthread.h> #include <pthread.h>
#include <semaphore.h>
struct BH_Condition struct BH_Condition
@@ -19,10 +19,22 @@ struct BH_Mutex
}; };
#if (_POSIX_SEMAPHORES >= 200112L)
#include <semaphore.h>
struct BH_Semaphore struct BH_Semaphore
{ {
sem_t handle; sem_t handle;
}; };
#else
struct BH_Semaphore
{
int count;
int waiters;
pthread_mutex_t mutex;
pthread_cond_t condition;
};
#endif
struct BH_Thread struct BH_Thread

View File

@@ -12,6 +12,8 @@ if [ ! -f $1 ]; then
exit 1 exit 1
fi fi
echo "Checking file" $1
# Message about trailing space before EOL # Message about trailing space before EOL
eolerrors=$(grep -n "\s$" "$1" | cut -f1 -d: | while read -r line; do eolerrors=$(grep -n "\s$" "$1" | cut -f1 -d: | while read -r line; do
@@ -22,7 +24,7 @@ done)
# Message about non-empty last-line # Message about non-empty last-line
linecount=$(($(wc -l "$1" | cut -f1 -d " ") + 1)) linecount=$(($(wc -l "$1" | xargs | cut -f1 -d " ") + 1))
lastline=$(tail -n "+$linecount" $1) lastline=$(tail -n "+$linecount" $1)
llerrors=$(if [ "$lastline" ]; then llerrors=$(if [ "$lastline" ]; then