Merge pull request 'Merge master into features/fs' (#5) from master into features/fs

Reviewed-on: PallasDev/DrangPlatform#5
This commit is contained in:
MechSlayer 2025-09-05 22:04:29 +02:00
commit b8e697cfd0
14 changed files with 507 additions and 98 deletions

View file

@ -10,17 +10,18 @@ DRANG_BEGIN_DECLS
*/
DRANG_PLATFORM_API const char *drang_error_str(int err);
#define DRANG_EOK (0) // Success
#define DRANG_EINVAL (-1) // Invalid argument
#define DRANG_ENOMEM (-2) // Out of memory
#define DRANG_EIO (-3) // I/O error
#define DRANG_NOTSUP (-4) // Operation not supported
#define DRANG_EAGAIN (-5) // Resource temporarily unavailable
#define DRANG_ENOENT (-6) // No such file or directory
#define DRANG_EDEADLK (-7) // Resource deadlock would occur
#define DRANG_EPERM (-8) // Operation not permitted
#define DRANG_ETIMEDOUT (-9) // Connection timed out
#define DRANG_EBUSY (-10) // Device or resource busy
#define DRANG_EOK (0) // Success
#define DRANG_EINVAL (-1) // Invalid argument
#define DRANG_ENOMEM (-2) // Out of memory
#define DRANG_EIO (-3) // I/O error
#define DRANG_NOTSUP (-4) // Operation not supported
#define DRANG_EAGAIN (-5) // Resource temporarily unavailable
#define DRANG_ENOENT (-6) // No such file or directory
#define DRANG_EDEADLK (-7) // Resource deadlock would occur
#define DRANG_EPERM (-8) // Operation not permitted
#define DRANG_ETIMEDOUT (-9) // Connection timed out
#define DRANG_EBUSY (-10) // Device or resource busy
#define DRANG_EPLATFORM (-1000) // An unknown platform-specific error occurred
/**
* @brief Begins a try-catch block for error handling.

View file

@ -28,6 +28,17 @@ struct drang_mutex;
*/
DRANG_PLATFORM_API size_t drang_mutex_size(void);
/**
* @brief Returns the alignment in bytes required for a mutex structure.
*
* This function returns the platform-specific alignment needed to allocate
* a mutex structure. Useful for stack allocation or custom memory management.
*
* @return Alignment in bytes required for a drang_mutex structure.
* @remarks The returned alignment is platform-specific and may vary between builds.
*/
DRANG_PLATFORM_API size_t drang_mutex_alignment(void);
/**
* @brief Creates and initializes a new mutex on the heap.
*
@ -144,6 +155,17 @@ struct drang_cond;
*/
DRANG_PLATFORM_API size_t drang_cond_size(void);
/**
* @brief Returns the alignment in bytes required for a condition variable structure.
*
* This function returns the platform-specific alignment needed to allocate
* a condition variable structure. Useful for stack allocation or custom memory management.
*
* @return Alignment in bytes required for a drang_cond structure.
* @remarks The returned alignment is platform-specific and may vary between builds.
*/
DRANG_PLATFORM_API size_t drang_cond_alignment(void);
/**
* @brief Creates and initializes a new condition variable on the heap.
*
@ -300,6 +322,17 @@ struct drang_rwlock;
*/
DRANG_PLATFORM_API size_t drang_rwlock_size(void);
/**
* @brief Returns the alignment in bytes required for a read-write lock structure.
*
* This function returns the platform-specific alignment needed to allocate
* a read-write lock structure. Useful for stack allocation or custom memory management.
*
* @return Alignment in bytes required for a drang_rwlock structure.
* @remarks The returned alignment is platform-specific and may vary between builds.
*/
DRANG_PLATFORM_API size_t drang_rwlock_alignment(void);
/**
* @brief Creates and initializes a new read-write lock on the heap.
*

View file

@ -0,0 +1,56 @@
#include "errno_convert.h"
#include "drang/error.h"
#include <errno.h>
int drang_error_to_errno(int error)
{
switch (error) {
case DRANG_EOK:
return 0;
case DRANG_EAGAIN:
return EAGAIN;
case DRANG_ENOMEM:
return ENOMEM;
case DRANG_EINVAL:
return EINVAL;
case DRANG_ENOENT:
return ENOENT;
case DRANG_EDEADLK:
return EDEADLK;
case DRANG_EPERM:
return EPERM;
case DRANG_ETIMEDOUT:
return ETIMEDOUT;
case DRANG_EBUSY:
return EBUSY;
case DRANG_EPLATFORM:
default:
return EIO; // Generic I/O error for unknown platform errors
}
}
int drang_errno_to_error(const int errnum)
{
switch (errnum) {
case 0:
return DRANG_EOK;
case EAGAIN:
return DRANG_EAGAIN;
case ENOMEM:
return DRANG_ENOMEM;
case EINVAL:
return DRANG_EINVAL;
case ENOENT:
return DRANG_ENOENT;
case EDEADLK:
return DRANG_EDEADLK;
case EPERM:
return DRANG_EPERM;
case ETIMEDOUT:
return DRANG_ETIMEDOUT;
case EBUSY:
return DRANG_EBUSY;
default:
return DRANG_EPLATFORM;
}
}

View file

@ -0,0 +1,9 @@
#pragma once
#include <drang/platform.h>
DRANG_BEGIN_DECLS
int drang_error_to_errno(int error);
int drang_errno_to_error(int errnum);
DRANG_END_DECLS

View file

@ -0,0 +1,111 @@
#include "drang/alloc.h"
#include "errno_convert.h"
#include "internal.h"
#include <drang/error.h>
#include <drang/sync.h>
#include <errno.h>
size_t drang_cond_size(void)
{
return sizeof(struct drang_cond);
}
size_t drang_cond_alignment(void)
{
return alignof(struct drang_cond);
}
int drang_cond_init(struct drang_cond *cond)
{
DRANG_BEGIN_TRY()
DRANG_CHECK(cond != NULL, DRANG_EINVAL);
DRANG_CHECK(!cond->initialized, DRANG_EBUSY);
const int res = pthread_cond_init(&cond->inner, NULL);
if (res != 0) {
DRANG_FAIL(drang_errno_to_error(res));
}
cond->initialized = true;
DRANG_END_TRY_IGNORE();
}
void drang_cond_fini(struct drang_cond *cond)
{
if (cond == NULL) {
return;
}
pthread_cond_destroy(&cond->inner);
cond->initialized = false;
}
int drang_cond_signal(struct drang_cond *cond)
{
DRANG_BEGIN_TRY()
DRANG_CHECK(cond != NULL, DRANG_EINVAL);
DRANG_CHECK(cond->initialized, DRANG_EINVAL);
const int res = pthread_cond_signal(&cond->inner);
if (res != 0) {
DRANG_FAIL(drang_errno_to_error(res));
}
DRANG_END_TRY_IGNORE();
}
int drang_cond_broadcast(struct drang_cond *cond)
{
DRANG_BEGIN_TRY()
DRANG_CHECK(cond != NULL, DRANG_EINVAL);
DRANG_CHECK(cond->initialized, DRANG_EINVAL);
const int res = pthread_cond_broadcast(&cond->inner);
if (res != 0) {
DRANG_FAIL(drang_errno_to_error(res));
}
DRANG_END_TRY_IGNORE();
}
int drang_cond_wait(struct drang_cond *cond, struct drang_mutex *mutex)
{
return drang_cond_timedwait(cond, mutex, 0);
}
int drang_cond_timedwait(struct drang_cond *cond, struct drang_mutex *mutex, uint64_t timeout_ms)
{
DRANG_BEGIN_TRY()
DRANG_CHECK(cond != NULL, DRANG_EINVAL);
DRANG_CHECK(cond->initialized, DRANG_EINVAL);
DRANG_CHECK(mutex != NULL, DRANG_EINVAL);
DRANG_CHECK(mutex->initialized, DRANG_EINVAL);
int res;
if (timeout_ms == 0) {
// Infinite wait
res = pthread_cond_wait(&cond->inner, &mutex->inner);
} else {
// Timed wait - calculate absolute timeout
struct timespec abs_timeout;
if (clock_gettime(CLOCK_REALTIME, &abs_timeout) != 0) {
DRANG_FAIL(drang_errno_to_error(errno));
}
// Add timeout milliseconds to current time
abs_timeout.tv_sec += (time_t) (timeout_ms / 1000);
abs_timeout.tv_nsec += (time_t) ((timeout_ms % 1000) * 1000000);
// Handle nanosecond overflow
if (abs_timeout.tv_nsec >= 1000000000) {
abs_timeout.tv_sec += 1;
abs_timeout.tv_nsec -= 1000000000;
}
res = pthread_cond_timedwait(&cond->inner, &mutex->inner, &abs_timeout);
}
if (res != 0) {
if (res == ETIMEDOUT) {
DRANG_FAIL(DRANG_ETIMEDOUT);
}
DRANG_FAIL(drang_errno_to_error(res));
}
DRANG_END_TRY_IGNORE();
}

View file

@ -0,0 +1,22 @@
#pragma once
#include <drang/sync.h>
#include <pthread.h>
#include <stdbool.h>
struct drang_mutex
{
pthread_mutex_t inner;
bool initialized;
};
struct drang_cond
{
pthread_cond_t inner;
bool initialized;
};
struct drang_rwlock
{
pthread_rwlock_t inner;
bool initialized;
};

View file

@ -0,0 +1,66 @@
#include "drang/alloc.h"
#include "errno_convert.h"
#include "internal.h"
#include <drang/error.h>
#include <drang/sync.h>
size_t drang_mutex_size(void)
{
return sizeof(struct drang_mutex);
}
size_t drang_mutex_alignment(void)
{
return alignof(struct drang_mutex);
}
int drang_mutex_init(struct drang_mutex *mutex)
{
DRANG_BEGIN_TRY();
DRANG_CHECK(mutex != NULL, DRANG_EINVAL);
DRANG_CHECK(!mutex->initialized, DRANG_EBUSY);
const int res = pthread_mutex_init(&mutex->inner, NULL);
if (res != 0) {
DRANG_FAIL(drang_errno_to_error(res));
}
mutex->initialized = true;
DRANG_END_TRY_IGNORE();
}
void drang_mutex_fini(struct drang_mutex *mutex)
{
if (mutex == NULL) {
return;
}
if (mutex->initialized) {
pthread_mutex_destroy(&mutex->inner);
mutex->initialized = false;
}
}
int drang_mutex_lock(struct drang_mutex *mutex)
{
DRANG_BEGIN_TRY()
DRANG_CHECK(mutex != NULL, DRANG_EINVAL);
DRANG_CHECK(mutex->initialized, DRANG_EINVAL);
const int res = pthread_mutex_lock(&mutex->inner);
if (res != 0) {
DRANG_FAIL(drang_errno_to_error(res));
}
DRANG_END_TRY_IGNORE();
}
int drang_mutex_unlock(struct drang_mutex *mutex)
{
DRANG_BEGIN_TRY()
DRANG_CHECK(mutex != NULL, DRANG_EINVAL);
DRANG_CHECK(mutex->initialized, DRANG_EINVAL);
const int res = pthread_mutex_unlock(&mutex->inner);
if (res != 0) {
DRANG_FAIL(drang_errno_to_error(res));
}
DRANG_END_TRY_IGNORE();
}

View file

@ -0,0 +1,87 @@
#include "errno_convert.h"
#include "internal.h"
#include <drang/error.h>
#include <drang/sync.h>
#include <stdalign.h>
size_t drang_rwlock_size(void)
{
return sizeof(struct drang_rwlock);
}
size_t drang_rwlock_alignment(void)
{
return alignof(struct drang_rwlock);
}
int drang_rwlock_init(struct drang_rwlock *rwlock)
{
DRANG_BEGIN_TRY()
DRANG_CHECK(rwlock != NULL, DRANG_EINVAL);
DRANG_CHECK(!rwlock->initialized, DRANG_EBUSY);
const int res = pthread_rwlock_init(&rwlock->inner, NULL);
if (res != 0) {
DRANG_FAIL(drang_errno_to_error(res));
}
rwlock->initialized = true;
DRANG_END_TRY_IGNORE();
}
void drang_rwlock_fini(struct drang_rwlock *rwlock)
{
if (rwlock == NULL) {
return;
}
if (rwlock->initialized) {
pthread_rwlock_destroy(&rwlock->inner);
rwlock->initialized = false;
}
}
int drang_rwlock_rdlock(struct drang_rwlock *rwlock)
{
DRANG_BEGIN_TRY()
DRANG_CHECK(rwlock != NULL, DRANG_EINVAL);
DRANG_CHECK(rwlock->initialized, DRANG_EINVAL);
const int res = pthread_rwlock_rdlock(&rwlock->inner);
if (res != 0) {
DRANG_FAIL(drang_errno_to_error(res));
}
DRANG_END_TRY_IGNORE();
}
int drang_rwlock_wrlock(struct drang_rwlock *rwlock)
{
DRANG_BEGIN_TRY()
DRANG_CHECK(rwlock != NULL, DRANG_EINVAL);
DRANG_CHECK(rwlock->initialized, DRANG_EINVAL);
const int res = pthread_rwlock_wrlock(&rwlock->inner);
if (res != 0) {
DRANG_FAIL(drang_errno_to_error(res));
}
DRANG_END_TRY_IGNORE();
}
int drang_rwlock_rdunlock(struct drang_rwlock *rwlock)
{
DRANG_BEGIN_TRY()
DRANG_CHECK(rwlock != NULL, DRANG_EINVAL);
DRANG_CHECK(rwlock->initialized, DRANG_EINVAL);
const int res = pthread_rwlock_unlock(&rwlock->inner);
if (res != 0) {
DRANG_FAIL(drang_errno_to_error(res));
}
DRANG_END_TRY_IGNORE();
}
int drang_rwlock_wrunlock(struct drang_rwlock *rwlock)
{
DRANG_BEGIN_TRY()
DRANG_CHECK(rwlock != NULL, DRANG_EINVAL);
DRANG_CHECK(rwlock->initialized, DRANG_EINVAL);
const int res = pthread_rwlock_unlock(&rwlock->inner);
if (res != 0) {
DRANG_FAIL(drang_errno_to_error(res));
}
DRANG_END_TRY_IGNORE();
}

View file

@ -0,0 +1,35 @@
#include "drang/alloc.h"
#include "drang/error.h"
#include <drang/sync.h>
int drang_cond_new(struct drang_cond **cond)
{
struct drang_cond *c = NULL;
DRANG_BEGIN_TRY();
DRANG_CHECK(cond != NULL, DRANG_EINVAL);
c = DRANG_TRY_ALLOC_ALIGNED(drang_cond_size(), drang_cond_alignment());
DRANG_TRY(drang_cond_init(c));
DRANG_RETURN_IN(cond, c);
DRANG_CATCH(_)
{
if (c != NULL) {
drang_free(c);
}
}
DRANG_END_TRY();
}
void drang_cond_free(struct drang_cond *cond)
{
if (cond == NULL) {
return;
}
drang_cond_fini(cond);
drang_free(cond);
}

View file

@ -0,0 +1,35 @@
#include "drang/alloc.h"
#include "drang/error.h"
#include <drang/sync.h>
int drang_mutex_new(struct drang_mutex **mutex)
{
struct drang_mutex *m = NULL;
DRANG_BEGIN_TRY();
DRANG_CHECK(mutex != NULL, DRANG_EINVAL);
m = DRANG_TRY_ALLOC_ALIGNED(drang_mutex_size(), drang_mutex_alignment());
DRANG_TRY(drang_mutex_init(m));
DRANG_RETURN_IN(mutex, m);
DRANG_CATCH(_)
{
if (m != NULL) {
drang_free(m);
}
}
DRANG_END_TRY()
}
void drang_mutex_free(struct drang_mutex *mutex)
{
if (mutex == NULL) {
return;
}
drang_mutex_fini(mutex);
drang_free(mutex);
}

View file

@ -0,0 +1,35 @@
#include <drang/alloc.h>
#include <drang/error.h>
#include <drang/sync.h>
int drang_rwlock_new(struct drang_rwlock **rwlock)
{
struct drang_rwlock *rw = NULL;
DRANG_BEGIN_TRY();
DRANG_CHECK(rwlock != NULL, DRANG_EINVAL);
rw = DRANG_TRY_ALLOC_ALIGNED(drang_rwlock_size(), drang_rwlock_alignment());
DRANG_TRY(drang_rwlock_init(rw));
DRANG_RETURN_IN(rwlock, rw);
DRANG_CATCH(_)
{
if (rw != NULL) {
drang_free(rw);
}
}
DRANG_END_TRY();
}
void drang_rwlock_free(struct drang_rwlock *rwlock)
{
if (rwlock == NULL) {
return;
}
drang_rwlock_fini(rwlock);
drang_free(rwlock);
}

View file

@ -8,36 +8,9 @@ size_t drang_cond_size(void)
return sizeof(struct drang_cond);
}
int drang_cond_new(struct drang_cond **cond)
size_t drang_cond_alignment(void)
{
struct drang_cond *c = NULL;
DRANG_BEGIN_TRY();
DRANG_CHECK(cond != NULL, DRANG_EINVAL);
c = DRANG_TRY_ALLOC_T(struct drang_cond);
DRANG_TRY(drang_cond_init(c));
DRANG_RETURN_IN(cond, c);
DRANG_CATCH(_)
{
if (c != NULL) {
drang_free(c);
}
}
DRANG_END_TRY();
}
void drang_cond_free(struct drang_cond *cond)
{
if (cond == NULL) {
return;
}
drang_cond_fini(cond);
drang_free(cond);
return alignof(struct drang_cond);
}
int drang_cond_init(struct drang_cond *cond)

View file

@ -7,36 +7,9 @@ size_t drang_mutex_size(void)
return sizeof(struct drang_mutex);
}
int drang_mutex_new(struct drang_mutex **mutex)
size_t drang_mutex_alignment(void)
{
struct drang_mutex *m = NULL;
DRANG_BEGIN_TRY();
DRANG_CHECK(mutex != NULL, DRANG_EINVAL);
m = DRANG_TRY_ALLOC_T(struct drang_mutex);
DRANG_TRY(drang_mutex_init(m));
DRANG_RETURN_IN(mutex, m);
DRANG_CATCH(_)
{
if (m != NULL) {
drang_free(m);
}
}
DRANG_END_TRY();
}
void drang_mutex_free(struct drang_mutex *mutex)
{
if (mutex == NULL) {
return;
}
drang_mutex_fini(mutex);
drang_free(mutex);
return alignof(struct drang_mutex);
}
int drang_mutex_init(struct drang_mutex *mutex)

View file

@ -7,36 +7,9 @@ size_t drang_rwlock_size(void)
return sizeof(struct drang_rwlock);
}
int drang_rwlock_new(struct drang_rwlock **rwlock)
size_t drang_rwlock_alignment(void)
{
struct drang_rwlock *rw = NULL;
DRANG_BEGIN_TRY();
DRANG_CHECK(rwlock != NULL, DRANG_EINVAL);
rw = DRANG_TRY_ALLOC_T(struct drang_rwlock);
DRANG_TRY(drang_rwlock_init(rw));
DRANG_RETURN_IN(rwlock, rw);
DRANG_CATCH(_)
{
if (rw != NULL) {
drang_free(rw);
}
}
DRANG_END_TRY();
}
void drang_rwlock_free(struct drang_rwlock *rwlock)
{
if (rwlock == NULL) {
return;
}
drang_rwlock_fini(rwlock);
drang_free(rwlock);
return alignof(struct drang_rwlock);
}
int drang_rwlock_init(struct drang_rwlock *rwlock)