Initial commit, yay

This commit is contained in:
VegOwOtenks 2024-06-13 15:28:21 +02:00
commit 25e26756cd
85 changed files with 7077 additions and 0 deletions

View file

@ -0,0 +1,4 @@
add_library(threading STATIC os_mutex.c
os_rwlock.c
os_semaphore.c
os_thread.c)

61
src/threading/os_mutex.c Normal file
View file

@ -0,0 +1,61 @@
#include "os_mutex.h"
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) // Fuck you, apple
int OSMutex_Create(os_mutex_t* target)
{
return pthread_mutex_init(target, NULL);
}
int OSMutex_Acquire(os_mutex_t* mutex)
{
return pthread_mutex_lock(mutex);
}
int OSMutex_Release(os_mutex_t* mutex)
{
return pthread_mutex_unlock(mutex);
}
int OSMutex_Destroy(os_mutex_t* mutex)
{
return pthread_mutex_destroy(mutex);
}
#elif defined(_WIN32)
int OSMutex_Create(os_mutex_t* target)
{
target[0] = CreateMutex(
NULL, // default security attributes
FALSE, // initially not owned
NULL); // unnamed mutex
if (target[0] == NULL) {
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int OSMutex_Acquire(os_mutex_t* mutex)
{
WaitForSingleObject(
*mutex, // handle to mutex
INFINITE); // no time-out interval
return EXIT_SUCCESS;
}
int OSMutex_Release(os_mutex_t* mutex)
{
return ReleaseMutex(mutex);
}
int OSMutex_Destroy(os_mutex_t* mutex)
{
CloseHandle(mutex[0]);
return EXIT_SUCCESS;
}
#endif

23
src/threading/os_mutex.h Normal file
View file

@ -0,0 +1,23 @@
#ifndef OS_MUTEX_H
#define OS_MUTEX_H
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) // Fuck you, apple
#include <pthread.h>
typedef pthread_mutex_t os_mutex_t;
#elif defined(_WIN32)
#include <windows.h>
typedef HANDLE os_mutex_t;
#else
#error "Unknown Threading Standard, feel free to add support via a fork/PR"
#endif
int OSMutex_Create(os_mutex_t* target);
int OSMutex_Acquire(os_mutex_t* mutex);
int OSMutex_Release(os_mutex_t* mutex);
int OSMutex_Destroy(os_mutex_t* mutex);
#endif

90
src/threading/os_rwlock.c Normal file
View file

@ -0,0 +1,90 @@
#include "os_rwlock.h"
#include <pthread.h>
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) // Fuck you, apple
int OSRWLock_Create(OSRWLock* target)
{
return pthread_rwlock_init(target, NULL);
}
void OSRWLock_Destroy(OSRWLock* rwlock)
{
pthread_rwlock_destroy(rwlock);
}
int OSRWLock_Read(OSRWLock* rwlock)
{
return pthread_rwlock_rdlock(rwlock);
}
int OSRWLock_Write(OSRWLock* rwlock)
{
return pthread_rwlock_wrlock(rwlock);
}
int OSRWLock_ReleaseRead(OSRWLock* rwlock)
{
return pthread_rwlock_unlock(rwlock);
}
int OSRWLock_ReleaseWrite(OSRWLock* rwlock)
{
return pthread_rwlock_unlock(rwlock);
}
#elif defined(_WIN32)
int OSRWLock_Create(OSRWLock* target)
{
InitializeSRWLock(*target);
return EXIT_SUCCESS;
}
void OSRWLock_Destroy(OSRWLock* rwlock)
{
// Win32 Locks can be forgotten if there are no more threads waiting on it
OSRWLock_Write(*rwlock);
// Now, nobody else can be holding the lock
OSRWLock_ReleaseWrite(*rwlock);
// Forget about it
return;
}
int OSRWLock_Read(OSRWLock* rwlock)
{
AcquireSRWLockShared(*rwlock);
return EXIT_SUCCESS;
}
int OSRWLock_Write(OSRWLock* rwlock)
{
AcquireSRWLockExclusive(*rwlock);
return EXIT_SUCCESS;
}
int OSRWLock_ReleaseRead(OSRWLock* rwlock)
{
ReleaseSRWLockShared(*rwlock);
return EXIT_SUCCESS;
}
int OSRWLock_ReleaseWrite(OSRWLock* rwlock)
{
ReleaseSRWLockExclusive(*rwlock);
return EXIT_SUCCESS;
}
#else
#error "Threading standard not supported"
#endif

29
src/threading/os_rwlock.h Normal file
View file

@ -0,0 +1,29 @@
#ifndef UTILITIEC_RWLOCK_H
#define UTILITIEC_RWLOCK_H
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) // Fuck you, apple
#include <pthread.h>
typedef pthread_rwlock_t OSRWLock;
#elif defined(_WIN32)
#include <syncapi.h>
typedef PSRWLOCK OSRWLock;
#else
#error "Threading standard not supported"
#endif
int OSRWLock_Create(OSRWLock* target);
void OSRWLock_Destroy(OSRWLock* rwlock);
int OSRWLock_Read(OSRWLock* rwlock);
int OSRWLock_Write(OSRWLock* rwlock);
int OSRWLock_ReleaseRead(OSRWLock* rwlock);
int OSRWLock_ReleaseWrite(OSRWLock* rwlock);
#endif

View file

@ -0,0 +1,92 @@
#include "os_semaphore.h"
#include <semaphore.h>
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) // Fuck you, apple
int OSSemaphore_Create(os_semaphore_t* target, unsigned int value)
{
return sem_init(
target,
0, // multi-threaded, not multiprocess
value
);
}
int OSSemaphore_GetValue(os_semaphore_t* semaphore)
{
int count;
sem_getvalue(semaphore, &count);
return count;
}
int OSSemaphore_Wait(os_semaphore_t* semaphore)
{
return sem_wait(semaphore);
}
int OSSemaphore_Release(os_semaphore_t* semaphore)
{
return sem_post(semaphore);
}
void OSSemaphore_Destroy(os_semaphore_t* semaphore)
{
sem_close(semaphore);
return;
}
#elif defined(_WIN32)
int OSSemaphore_Create(os_semaphore_t* target, unsigned int value)
{
target->sem_handle = CreateSemaphoreA(
SEMAPHORE_ALL_ACCESS, // Access attributes
value, // InitialCount
32 767, // POSIX_SEM_VALUE_MAX
NULL // Named semaphore
);
if (target->sem_handle != NULL) {
return ENOMEM;
}
target->count = value;
return EXIT_SUCCESS;
}
int OSSemaphore_GetValue(os_semaphore_t* semaphore)
{
return semaphore->count;
}
int OSSempahore_Wait(os_semaphore_t* semaphore)
{
DWORD r = WaitForSingleObject(
semaphore->sem_handle,
INIFINITE
);
semaphore->count -= 1;
return r != WAIT_FAILED;
}
int OSSempahore_Release(os_semaphore_t* semaphore)
{
if (ReleaseSemaphore(
semaphore->sem_handle,
1,
NULL
)) {
semaphore->count++;
return EXIT_SUCCESS;
} else {
return EXIT_FAILURE;
}
}
void OSSemaphore_Destroy(os_semaphore_t* semaphore)
{
CloseHandle(semaphore->sem_handle);
}
#endif

View file

@ -0,0 +1,59 @@
#ifndef OS_SEMAPHORE_H
#define OS_SEMAPHORE_H
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) // Fuck you, apple
#include <semaphore.h>
typedef sem_t os_semaphore_t;
#elif defined(_WIN32)
#include <windows.h>
typedef struct Struct_OSSemaphore {
atomic int count;
HANDLE sem_handle;
} os_semaphore_t;
#else
#error "Unknown Threading Standard, feel free to add support via a fork/PR"
#endif
/*!
@brief Create a Operating-System-Backed Semaphore
@param target Memory area for the semaphore
@param initialValue Value the semaphore will initially hold
@pre target must be a valid pointer
@return EXIT_SUCCESS, ENOMEM
*/
int OSSemaphore_Create(os_semaphore_t* target, unsigned int initialValue);
/*!
@brief Rertieve the value of the semaphore
@param semaphore this
@pre Must be a valid semaphore
@return the value of the semaphore, negative if there are threads waiting
*/
int OSSemaphore_GetValue(os_semaphore_t* semaphore);
/*!
@brief Wait for a resource to be available on the semaphore
@param semaphore this
@return EXIT_SUCCESS, EINVAL, EINTR
*/
int OSSemaphore_Wait(os_semaphore_t* semaphore);
/*!
@brief Signal the release of a resource on the semaphore
@param semaphore this
@return EINVAL, EOVERFLOW
*/
int OSSemaphore_Release(os_semaphore_t* semaphore);
/*!
@brief Destroy the referenced semaphore resource and return it to the OS
@param semaphore this
@return void
*/
void OSSemaphore_Destroy(os_semaphore_t* semaphore);
#endif

89
src/threading/os_thread.c Normal file
View file

@ -0,0 +1,89 @@
#include "os_thread.h"
#include <stdlib.h>
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <pthread.h>
#include <signal.h>
int OSThread_Create(os_thread_t* destination, ThreadFunction subroutine, void* arg)
{
return pthread_create(destination, NULL, subroutine, arg);
}
int OSThread_Kill(os_thread_t* thread)
{
return pthread_cancel(*thread);
}
int OSThread_Join(os_thread_t* thread, void** thread_return)
{
return pthread_join(*thread, thread_return);
}
int OSThread_Destroy(os_thread_t* thread)
{
(void) thread;
return EXIT_SUCCESS;
}
#elif defined _WIN32
struct CaptureReturnArgument {
ThreadFunction subroutine;
void* arg;
void** return_value_storage;
};
static void capture_return(struct CaptureReturnArgument* a)
{
a.return_value_storage[0] = a->subroutine(a->arg);
return;
}
int OSThread_Create(os_thread_t* destination, ThreadFunction subroutine, void* arg)
{
destination->return_value_storage = malloc(sizeof(void*));
if (destination->return_value_storage == NULL) {
return ENOMEM;
}
destination->return_value_storage[0] = NULL;
destination->handle = CreateThread(
THREAD_ALL_ACCESS, // Security
0, // default stack size
capture_return, // start address
arg, // argument
0, // start immediately
NULL // thread id receeiver
);
if (destination->handle == NULL) {
return GetLastError();
}
return EXIT_SUCCESS;
}
int OSThread_Kill(os_thread_t* thread)
{
return 1 == TerminateThread(
thread->thread_handle,
0 // exit code
);
}
int OSThread_Join(os_thread_t* thread, void** thread_return)
{
WaitForSingleObject(thread->thread_handle, INFINITE);
thread_return[0] = thread->return_value_storage[0];
return EXIT_SUCCESS;
}
int OSThread_Destroy(os_thread_t* thread)
{
free(thread->return_value_storage);
CloseHandle(thread->thread_handle);
}
#endif

28
src/threading/os_thread.h Normal file
View file

@ -0,0 +1,28 @@
#ifndef OS_THREAD_H
#define OS_THREAD_H
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) // Fuck you, apple
#include <pthread.h>
typedef pthread_t os_thread_t;
#elif defined(_WIN32)
#include <windows.h>
typedef struct Struct_OSThread {
HANDLE thread_handle;
void** return_value_storage;
} os_thread_t;
#else
#error "Unknown Threading Standard, feel free to add support via a fork/PR"
#endif
typedef void* (*ThreadFunction) (void* arg);
int OSThread_Create(os_thread_t* destination, ThreadFunction subroutine, void* arg);
int OSThread_Kill(os_thread_t* thread);
int OSThread_Join(os_thread_t* thread, void** thread_return);
int OSThread_Destroy(os_thread_t* thread);
#endif