fix some threading crashes

This commit is contained in:
Isaac0-dev 2024-11-26 16:28:27 +10:00
parent 507f578dbb
commit 10ead40b5d
3 changed files with 31 additions and 27 deletions

View file

@ -18,7 +18,7 @@ struct LoadingSegment {
extern struct LoadingSegment gCurrLoadingSegment; extern struct LoadingSegment gCurrLoadingSegment;
#define LOADING_SCREEN_MUTEX(...) \ #define LOADING_SCREEN_MUTEX(...) \
if (!gCLIOpts.hideLoadingScreen && gLoadingThread.state != INVALID) { \ if (!gCLIOpts.hideLoadingScreen && gLoadingThread.state == RUNNING) { \
pthread_mutex_lock(&gLoadingThread.mutex); \ pthread_mutex_lock(&gLoadingThread.mutex); \
__VA_ARGS__; \ __VA_ARGS__; \
pthread_mutex_unlock(&gLoadingThread.mutex); \ pthread_mutex_unlock(&gLoadingThread.mutex); \

View file

@ -6,19 +6,19 @@
int init_thread_handle(struct ThreadHandle *handle, void *(*entry)(void *), void *arg, void *sp, size_t sp_size) { int init_thread_handle(struct ThreadHandle *handle, void *(*entry)(void *), void *arg, void *sp, size_t sp_size) {
int err1 = init_mutex(handle); int err1 = init_mutex(handle);
int err2 = init_thread(handle, entry, arg, sp, sp_size); int err2 = init_thread(handle, entry, arg, sp, sp_size);
return (err1 != 0 || err2 != 0); return (err1 != 0 || err2 != 0);
} }
void free_thread_handle(struct ThreadHandle *handle) { void free_thread_handle(struct ThreadHandle *handle) {
assert(handle != NULL); assert(handle != NULL);
//int err = stop_thread(handle); //int err = stop_thread(handle);
//assert(err == 0); //assert(err == 0);
int err = destroy_mutex(handle); int err = destroy_mutex(handle);
assert(err == 0); assert(err == 0);
// Reset the memory of the thread handle, We no longer need the thread or mutex. // Reset the memory of the thread handle, We no longer need the thread or mutex.
memset((void *)handle, 0, sizeof(struct ThreadHandle)); memset((void *)handle, 0, sizeof(struct ThreadHandle));
} }
@ -26,18 +26,18 @@ void free_thread_handle(struct ThreadHandle *handle) {
// Optimally just call init_thread_handle instead. // Optimally just call init_thread_handle instead.
int init_thread(struct ThreadHandle *handle, void *(*entry)(void *), void *arg, void *sp, size_t sp_size) { int init_thread(struct ThreadHandle *handle, void *(*entry)(void *), void *arg, void *sp, size_t sp_size) {
assert(handle != NULL); assert(handle != NULL);
// Setup our thread and create it. // Setup our thread and create it.
pthread_attr_t thattr = { 0 }; pthread_attr_t thattr = { 0 };
// Initialize default attributes for a new thread. // Initialize default attributes for a new thread.
int err = pthread_attr_init(&thattr); int err = pthread_attr_init(&thattr);
assert(err == 0); assert(err == 0);
// By default, We want the thread to be joinable. // By default, We want the thread to be joinable.
err = pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE); err = pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE);
assert(err == 0); assert(err == 0);
// Set the stack if we have one specified, Otherwise we don't care. // Set the stack if we have one specified, Otherwise we don't care.
// In truth, This honestly shouldn't be used on PC. But if somebody wants // In truth, This honestly shouldn't be used on PC. But if somebody wants
// a really managed stack? This is possible. // a really managed stack? This is possible.
@ -45,29 +45,33 @@ int init_thread(struct ThreadHandle *handle, void *(*entry)(void *), void *arg,
err = pthread_attr_setstack(&thattr, sp, sp_size); err = pthread_attr_setstack(&thattr, sp, sp_size);
assert(err == 0); assert(err == 0);
} }
// Create our thread. // Create our thread.
int ret = pthread_create(&handle->thread, &thattr, entry, arg); int ret = pthread_create(&handle->thread, &thattr, entry, arg);
// Destroy the thread attributes, They are no longer needed // Destroy the thread attributes, They are no longer needed
err = pthread_attr_destroy(&thattr); err = pthread_attr_destroy(&thattr);
assert(err == 0); assert(err == 0);
handle->state = RUNNING; handle->state = RUNNING;
return ret; return ret;
} }
int join_thread(struct ThreadHandle *handle) { int join_thread(struct ThreadHandle *handle) {
assert(handle != NULL); assert(handle != NULL);
handle->state = STOPPED;
// Join the thread and wait for it to finish. // Join the thread and wait for it to finish.
return pthread_join(handle->thread, NULL); return pthread_join(handle->thread, NULL);
} }
int detach_thread(struct ThreadHandle *handle) { int detach_thread(struct ThreadHandle *handle) {
assert(handle != NULL); assert(handle != NULL);
handle->state = STOPPED;
// Detach the thread, it will no longer be joinable afterwards. // Detach the thread, it will no longer be joinable afterwards.
return pthread_detach(handle->thread); return pthread_detach(handle->thread);
} }
@ -90,43 +94,43 @@ int stop_thread(struct ThreadHandle *handle) {
// Optimally just call init_thread_handle instead. // Optimally just call init_thread_handle instead.
int init_mutex(struct ThreadHandle *handle) { int init_mutex(struct ThreadHandle *handle) {
assert(handle != NULL); assert(handle != NULL);
pthread_mutexattr_t mtattr; pthread_mutexattr_t mtattr;
int err = pthread_mutexattr_init(&mtattr); int err = pthread_mutexattr_init(&mtattr);
assert(err == 0); assert(err == 0);
err = pthread_mutexattr_settype(&mtattr, PTHREAD_MUTEX_ERRORCHECK); err = pthread_mutexattr_settype(&mtattr, PTHREAD_MUTEX_ERRORCHECK);
assert(err == 0); assert(err == 0);
int ret = pthread_mutex_init(&handle->mutex, &mtattr); int ret = pthread_mutex_init(&handle->mutex, &mtattr);
err = pthread_mutexattr_destroy(&mtattr); err = pthread_mutexattr_destroy(&mtattr);
assert(err == 0); assert(err == 0);
return ret; return ret;
} }
int destroy_mutex(struct ThreadHandle *handle) { int destroy_mutex(struct ThreadHandle *handle) {
assert(handle != NULL); assert(handle != NULL);
return pthread_mutex_destroy(&handle->mutex); return pthread_mutex_destroy(&handle->mutex);
} }
int lock_mutex(struct ThreadHandle *handle) { int lock_mutex(struct ThreadHandle *handle) {
assert(handle != NULL); assert(handle != NULL);
return pthread_mutex_lock(&handle->mutex); return pthread_mutex_lock(&handle->mutex);
} }
int trylock_mutex(struct ThreadHandle *handle) { int trylock_mutex(struct ThreadHandle *handle) {
assert(handle != NULL); assert(handle != NULL);
return pthread_mutex_trylock(&handle->mutex); return pthread_mutex_trylock(&handle->mutex);
} }
int unlock_mutex(struct ThreadHandle *handle) { int unlock_mutex(struct ThreadHandle *handle) {
assert(handle != NULL); assert(handle != NULL);
return pthread_mutex_unlock(&handle->mutex); return pthread_mutex_unlock(&handle->mutex);
} }

View file

@ -7,8 +7,8 @@
#include "types.h" #include "types.h"
// Macros // Macros
#define MUTEX_LOCK(handle) if (handle.state != INVALID) { lock_mutex(&handle); } #define MUTEX_LOCK(handle) if (handle.state == RUNNING) { lock_mutex(&handle); }
#define MUTEX_UNLOCK(handle) if (handle.state != INVALID) { unlock_mutex(&handle); } #define MUTEX_UNLOCK(handle) if (handle.state == RUNNING) { unlock_mutex(&handle); }
// Types // Types
enum ThreadState { enum ThreadState {