clang on windows support

This commit is contained in:
wuggy 2026-09-10 08:32:59 -07:00
commit 1d44f05fba
22 changed files with 208 additions and 65 deletions

View file

@ -85,10 +85,24 @@ COLD int dav1d_num_logical_processors(Dav1dContext *const c) {
#ifdef _WIN32
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
GROUP_AFFINITY affinity;
if (GetThreadGroupAffinity(GetCurrentThread(), &affinity)) {
int num_processors = 1;
while (affinity.Mask &= affinity.Mask - 1)
DWORD_PTR mask = 0, system_mask;
HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
typedef BOOL (WINAPI *get_thread_group_affinity_fn)(HANDLE, PGROUP_AFFINITY);
get_thread_group_affinity_fn get_thread_group_affinity = kernel32 ?
(get_thread_group_affinity_fn)GetProcAddress(kernel32, "GetThreadGroupAffinity") : NULL;
/* Processor groups are only available on Windows 7 and later. */
if (get_thread_group_affinity &&
get_thread_group_affinity(GetCurrentThread(), &affinity))
mask = affinity.Mask;
else if (!GetProcessAffinityMask(GetCurrentProcess(), &mask, &system_mask))
mask = 0;
if (mask) {
int num_processors = 0;
do {
num_processors++;
} while (mask &= mask - 1);
return num_processors;
}
#else

View file

@ -33,8 +33,8 @@
#include <limits.h>
#include <windows.h>
#define PTHREAD_MUTEX_INITIALIZER SRWLOCK_INIT
#define PTHREAD_ONCE_INIT INIT_ONCE_STATIC_INIT
#define PTHREAD_MUTEX_INITIALIZER { 0 }
#define PTHREAD_ONCE_INIT 0
typedef struct {
HANDLE h;
@ -46,9 +46,16 @@ typedef struct {
unsigned stack_size;
} pthread_attr_t;
typedef SRWLOCK pthread_mutex_t;
typedef CONDITION_VARIABLE pthread_cond_t;
typedef INIT_ONCE pthread_once_t;
typedef struct {
volatile LONG state;
CRITICAL_SECTION cs;
} pthread_mutex_t;
struct dav1d_cond_waiter;
typedef struct {
CRITICAL_SECTION cs;
struct dav1d_cond_waiter *head;
} pthread_cond_t;
typedef volatile LONG pthread_once_t;
void dav1d_init_thread(void);
void dav1d_set_thread_name(const wchar_t *name);
@ -84,50 +91,51 @@ static inline int pthread_attr_setstacksize(pthread_attr_t *const attr,
static inline int pthread_mutex_init(pthread_mutex_t *const mutex,
const void *const attr)
{
InitializeSRWLock(mutex);
mutex->state = 0;
return 0;
}
static inline int pthread_mutex_destroy(pthread_mutex_t *const mutex) {
if (mutex->state == 2) DeleteCriticalSection(&mutex->cs);
return 0;
}
static inline int pthread_mutex_lock(pthread_mutex_t *const mutex) {
AcquireSRWLockExclusive(mutex);
if (InterlockedCompareExchange(&mutex->state, 1, 0) == 0) {
InitializeCriticalSection(&mutex->cs);
InterlockedExchange(&mutex->state, 2);
} else {
while (InterlockedCompareExchange(&mutex->state, 2, 2) != 2)
Sleep(1);
}
EnterCriticalSection(&mutex->cs);
return 0;
}
static inline int pthread_mutex_unlock(pthread_mutex_t *const mutex) {
ReleaseSRWLockExclusive(mutex);
LeaveCriticalSection(&mutex->cs);
return 0;
}
static inline int pthread_cond_init(pthread_cond_t *const cond,
const void *const attr)
{
InitializeConditionVariable(cond);
InitializeCriticalSection(&cond->cs);
cond->head = NULL;
return 0;
}
static inline int pthread_cond_destroy(pthread_cond_t *const cond) {
DeleteCriticalSection(&cond->cs);
return 0;
}
static inline int pthread_cond_wait(pthread_cond_t *const cond,
pthread_mutex_t *const mutex)
{
return !SleepConditionVariableSRW(cond, mutex, INFINITE, 0);
}
static inline int pthread_cond_signal(pthread_cond_t *const cond) {
WakeConditionVariable(cond);
return 0;
}
static inline int pthread_cond_broadcast(pthread_cond_t *const cond) {
WakeAllConditionVariable(cond);
return 0;
}
#define pthread_cond_wait dav1d_pthread_cond_wait
#define pthread_cond_signal dav1d_pthread_cond_signal
#define pthread_cond_broadcast dav1d_pthread_cond_broadcast
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
#else

View file

@ -85,15 +85,73 @@ COLD int dav1d_pthread_join(pthread_t *const thread, void **const res) {
COLD int dav1d_pthread_once(pthread_once_t *const once_control,
void (*const init_routine)(void))
{
BOOL pending = FALSE;
if (InitOnceBeginInitialize(once_control, 0, &pending, NULL) != TRUE)
return 1;
if (pending == TRUE)
if (InterlockedCompareExchange(once_control, 1, 0) == 0) {
init_routine();
InterlockedExchange(once_control, 2);
} else {
while (InterlockedCompareExchange(once_control, 2, 2) != 2)
Sleep(1);
}
return 0;
}
return !InitOnceComplete(once_control, 0, NULL);
/* Each waiter owns an event. Queue operations and signalling share a lock,
* so a new waiter cannot consume an earlier waiter's notification. */
struct dav1d_cond_waiter {
HANDLE event;
struct dav1d_cond_waiter *next;
};
int dav1d_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) {
struct dav1d_cond_waiter waiter, **link;
DWORD result;
waiter.event = CreateEventW(NULL, FALSE, FALSE, NULL);
if (!waiter.event) return 1;
EnterCriticalSection(&cond->cs);
waiter.next = NULL;
for (link = &cond->head; *link; link = &(*link)->next) {}
*link = &waiter;
pthread_mutex_unlock(mutex);
LeaveCriticalSection(&cond->cs);
result = WaitForSingleObject(waiter.event, INFINITE);
EnterCriticalSection(&cond->cs);
/* Also unlink on wait failure before the stack record goes away. */
for (link = &cond->head; *link; link = &(*link)->next) {
if (*link == &waiter) {
*link = waiter.next;
break;
}
}
CloseHandle(waiter.event);
LeaveCriticalSection(&cond->cs);
pthread_mutex_lock(mutex);
return result != WAIT_OBJECT_0;
}
int dav1d_pthread_cond_signal(pthread_cond_t *cond) {
int result = 0;
EnterCriticalSection(&cond->cs);
if (cond->head) {
if (SetEvent(cond->head->event)) cond->head = cond->head->next;
else result = 1;
}
LeaveCriticalSection(&cond->cs);
return result;
}
int dav1d_pthread_cond_broadcast(pthread_cond_t *cond) {
int result = 0;
EnterCriticalSection(&cond->cs);
while (cond->head) {
if (!SetEvent(cond->head->event)) {
result = 1;
break;
}
cond->head = cond->head->next;
}
LeaveCriticalSection(&cond->cs);
return result;
}
#endif