Skip to content

Commit

Permalink
Use better Win32 mutexes for rc_mutex_t (#376)
Browse files Browse the repository at this point in the history
  • Loading branch information
CasualPokePlayer authored Oct 16, 2024
1 parent 3106e6d commit 32917bd
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/rc_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ static void rc_client_log_message_va(const rc_client_t* client, const char* form
if (client->callbacks.log_call) {
char buffer[2048];

#ifdef __STDC_WANT_SECURE_LIB__
#ifdef __STDC_SECURE_LIB__
vsprintf_s(buffer, sizeof(buffer), format, args);
#elif __STDC_VERSION__ >= 199901L /* vsnprintf requires c99 */
vsnprintf(buffer, sizeof(buffer), format, args);
Expand Down
70 changes: 59 additions & 11 deletions src/rc_compat.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "rc_compat.h"

#include <assert.h>
#include <ctype.h>
#include <stdarg.h>

Expand Down Expand Up @@ -58,7 +59,7 @@ int rc_snprintf(char* buffer, size_t size, const char* format, ...)

va_start(args, format);

#ifdef __STDC_WANT_SECURE_LIB__
#ifdef __STDC_SECURE_LIB__
result = vsprintf_s(buffer, size, format, args);
#else
/* assume buffer is large enough and ignore size */
Expand All @@ -73,7 +74,7 @@ int rc_snprintf(char* buffer, size_t size, const char* format, ...)

#endif

#ifndef __STDC_WANT_SECURE_LIB__
#ifndef __STDC_SECURE_LIB__

struct tm* rc_gmtime_s(struct tm* buf, const time_t* timer)
{
Expand All @@ -88,32 +89,79 @@ struct tm* rc_gmtime_s(struct tm* buf, const time_t* timer)

#if defined(_WIN32)

/* https://gist.github.com/roxlu/1c1af99f92bafff9d8d9 */
/* https://learn.microsoft.com/en-us/archive/msdn-magazine/2012/november/windows-with-c-the-evolution-of-synchronization-in-windows-and-c */
/* implementation largely taken from https://github.com/libsdl-org/SDL/blob/0fc3574/src/thread/windows/SDL_sysmutex.c */

#if defined(WINVER) && WINVER >= 0x0600

void rc_mutex_init(rc_mutex_t* mutex)
{
InitializeSRWLock(&mutex->srw_lock);
/* https://learn.microsoft.com/en-us/windows/win32/procthread/thread-handles-and-identifiers */
/* thread ids are never 0 */
mutex->owner = 0;
mutex->count = 0;
}

void rc_mutex_destroy(rc_mutex_t* mutex)
{
/* Nothing to do here */
(void)mutex;
}

void rc_mutex_lock(rc_mutex_t* mutex)
{
DWORD current_thread = GetCurrentThreadId();
if (mutex->owner == current_thread) {
++mutex->count;
assert(mutex->count > 0);
}
else {
AcquireSRWLockExclusive(&mutex->srw_lock);
assert(mutex->owner == 0 && mutex->count == 0);
mutex->owner = current_thread;
mutex->count = 1;
}
}

void rc_mutex_unlock(rc_mutex_t* mutex)
{
if (mutex->owner == GetCurrentThreadId()) {
assert(mutex->count > 0);
if (--mutex->count == 0) {
mutex->owner = 0;
ReleaseSRWLockExclusive(&mutex->srw_lock);
}
}
else {
assert(!"Tried to unlock unowned mutex");
}
}

#else

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

void rc_mutex_init(rc_mutex_t* mutex)
{
/* default security, not owned by calling thread, unnamed */
mutex->handle = CreateMutex(NULL, FALSE, NULL);
InitializeCriticalSection(&mutex->critical_section);
}

void rc_mutex_destroy(rc_mutex_t* mutex)
{
CloseHandle(mutex->handle);
DeleteCriticalSection(&mutex->critical_section);
}

void rc_mutex_lock(rc_mutex_t* mutex)
{
WaitForSingleObject(mutex->handle, 0xFFFFFFFF);
EnterCriticalSection(&mutex->critical_section);
}

void rc_mutex_unlock(rc_mutex_t* mutex)
{
ReleaseMutex(mutex->handle);
LeaveCriticalSection(&mutex->critical_section);
}

#endif

#elif defined(GEKKO)

/* https://github.com/libretro/RetroArch/pull/16116 */
Expand Down
26 changes: 21 additions & 5 deletions src/rc_compat.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
#ifndef RC_COMPAT_H
#define RC_COMPAT_H

#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#endif

#include "rc_export.h"

#include <stdio.h>
Expand Down Expand Up @@ -58,7 +65,7 @@ RC_BEGIN_C_DECLS

#endif /* __STDC_VERSION__ < 199901L */

#ifndef __STDC_WANT_SECURE_LIB__
#ifndef __STDC_SECURE_LIB__
/* _CRT_SECURE_NO_WARNINGS redefinitions */
#define strcpy_s(dest, sz, src) strcpy(dest, src)
#define sscanf_s sscanf
Expand All @@ -77,10 +84,19 @@ RC_BEGIN_C_DECLS
#define rc_mutex_lock(mutex)
#define rc_mutex_unlock(mutex)
#else
#ifdef _WIN32
typedef struct rc_mutex_t {
void* handle; /* HANDLE is defined as "void*" */
} rc_mutex_t;
#if defined(_WIN32)
typedef struct rc_mutex_t {
#if defined(WINVER) && WINVER >= 0x0600
/* Windows Vista and later can use a slim reader/writer (SRW) lock */
SRWLOCK srw_lock;
/* Current thread owner needs to be tracked (for recursive mutex usage) */
DWORD owner;
DWORD count;
#else
/* Pre-Vista must use a critical section */
CRITICAL_SECTION critical_section;
#endif
} rc_mutex_t;
#else
#include <pthread.h>
typedef pthread_mutex_t rc_mutex_t;
Expand Down
6 changes: 3 additions & 3 deletions src/rhash/hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ static void* filereader_open(const char* path)
return NULL;
}

#if defined(__STDC_WANT_SECURE_LIB__)
#if defined(__STDC_SECURE_LIB__)
/* have to use _SH_DENYNO because some cores lock the file while its loaded */
fp = _wfsopen(wpath, L"rb", _SH_DENYNO);
#else
Expand All @@ -91,7 +91,7 @@ static void* filereader_open(const char* path)
#else /* !WINVER >= 0x0500 */
static void* filereader_open(const char* path)
{
#if defined(__STDC_WANT_SECURE_LIB__)
#if defined(__STDC_SECURE_LIB__)
#if defined(WINVER)
/* have to use _SH_DENYNO because some cores lock the file while its loaded */
return _fsopen(path, "rb", _SH_DENYNO);
Expand All @@ -100,7 +100,7 @@ static void* filereader_open(const char* path)
fopen_s(&fp, path, "rb");
return fp;
#endif
#else /* !__STDC_WANT_SECURE_LIB__ */
#else /* !__STDC_SECURE_LIB__ */
return fopen(path, "rb");
#endif
}
Expand Down

0 comments on commit 32917bd

Please sign in to comment.