Compare commits

...
2 Commits
Author SHA1 Message Date
Alug f58772a570 z_zone: add asserts if zone memory functions are called from non main thread
also taken from srb2classic thanks!
2026-02-02 18:14:38 +01:00
Alug f7c065b22e refactor i_thread stuff
based on https://codeberg.org/srb2classic/srb2classic/commit/3670a7c1c193185cf4921de8955c96e63fbecc62
and other things from srb2classic
this also now allows to check if a thread failed to spawn and reduces duped stuff and such
2026-02-02 18:14:35 +01:00
25 changed files with 249 additions and 539 deletions

No files matched your search

+1
View File
@@ -191,6 +191,7 @@ set(SRB2_CORE_GAME_SOURCES
k_kart.c k_kart.c
k_stats.c k_stats.c
i_time.c i_time.c
i_threads.c
p_local.h p_local.h
p_maputl.h p_maputl.h
-5
View File
@@ -8,11 +8,6 @@ ifdef MINGW
libs+=-mconsole libs+=-mconsole
endif endif
ifndef NOTHREADS
opts+=-DHAVE_THREADS
sources+=dedicated/i_threads.c
endif
NOOPENMPT=1 NOOPENMPT=1
NOLIBGME=1 NOLIBGME=1
NOHW=1 NOHW=1
+5
View File
@@ -27,6 +27,11 @@ endif
sources+=$(call List,hardware/Sourcefile) sources+=$(call List,hardware/Sourcefile)
endif endif
ifndef NOTHREADS
opts+=-DHAVE_THREADS
sources+=i_threads.c
endif
ifndef NOMD5 ifndef NOMD5
sources+=md5.c sources+=md5.c
endif endif
-5
View File
@@ -40,11 +40,6 @@ sources+=sdl/mixer_sound.c
endif endif
endif endif
ifndef NOTHREADS
opts+=-DHAVE_THREADS
sources+=sdl/i_threads.c
endif
ifdef SDL_PKGCONFIG ifdef SDL_PKGCONFIG
$(eval $(call Use_pkg_config,SDL)) $(eval $(call Use_pkg_config,SDL))
else else
+3 -3
View File
@@ -44,14 +44,14 @@
#define MAXHUDLINES 20 #define MAXHUDLINES 20
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_mutex con_mutex; I_Mutex con_mutex;
// g_in_exiting_signal_handler is an evil hack // g_in_exiting_signal_handler is an evil hack
// to avoid infinite SIGABRT recursion in the signal handler // to avoid infinite SIGABRT recursion in the signal handler
// due to poisoned locks or mach-o kernel not supporting locks in signals // due to poisoned locks or mach-o kernel not supporting locks in signals
// or something like that. idk // or something like that. idk
# define Lock_state() if (!g_in_exiting_signal_handler) { I_lock_mutex(&con_mutex); } # define Lock_state() if (!g_in_exiting_signal_handler) { I_LockMutex(&con_mutex); }
# define Unlock_state() if (!g_in_exiting_signal_handler) { I_unlock_mutex(con_mutex); } # define Unlock_state() if (!g_in_exiting_signal_handler) { I_UnlockMutex(con_mutex); }
#else/*HAVE_THREADS*/ #else/*HAVE_THREADS*/
# define Lock_state() # define Lock_state()
# define Unlock_state() # define Unlock_state()
+1 -1
View File
@@ -22,7 +22,7 @@ void CON_Init(void);
boolean CON_Responder(event_t *ev); boolean CON_Responder(event_t *ev);
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
extern I_mutex con_mutex; extern I_Mutex con_mutex;
#endif #endif
// set true when screen size has changed, to adapt console // set true when screen size has changed, to adapt console
+4 -4
View File
@@ -2830,11 +2830,11 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
F_TitleScreenDrawer(); F_TitleScreenDrawer();
CL_DrawConnectionStatus(); CL_DrawConnectionStatus();
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex); I_LockMutex(&m_menu_mutex);
#endif #endif
M_Drawer(); //Needed for drawing messageboxes on the connection screen M_Drawer(); //Needed for drawing messageboxes on the connection screen
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex); I_UnlockMutex(m_menu_mutex);
#endif #endif
I_UpdateNoVsync(); // page flip or blit buffer I_UpdateNoVsync(); // page flip or blit buffer
if (moviemode) if (moviemode)
@@ -7187,12 +7187,12 @@ void NetUpdate(void)
{ {
resptime = nowtime; resptime = nowtime;
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex); I_LockMutex(&m_menu_mutex);
#endif #endif
M_Ticker(); M_Ticker();
refreshdirmenu = 0; refreshdirmenu = 0;
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex); I_UnlockMutex(m_menu_mutex);
#endif #endif
CON_Ticker(); CON_Ticker();
} }
+6 -6
View File
@@ -223,13 +223,13 @@ void D_ProcessEvents(void)
// Menu input // Menu input
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex); I_LockMutex(&m_menu_mutex);
#endif #endif
{ {
eaten = M_Responder(ev); eaten = M_Responder(ev);
} }
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex); I_UnlockMutex(m_menu_mutex);
#endif #endif
if (eaten) if (eaten)
@@ -244,13 +244,13 @@ void D_ProcessEvents(void)
// console input // console input
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_lock_mutex(&con_mutex); I_LockMutex(&con_mutex);
#endif #endif
{ {
eaten = CON_Responder(ev); eaten = CON_Responder(ev);
} }
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_unlock_mutex(con_mutex); I_UnlockMutex(con_mutex);
#endif #endif
if (eaten) if (eaten)
@@ -577,11 +577,11 @@ static boolean D_Display(void)
vid.recalc = false; vid.recalc = false;
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex); I_LockMutex(&m_menu_mutex);
#endif #endif
M_Drawer(); // menu is drawn even on top of everything... M_Drawer(); // menu is drawn even on top of everything...
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex); I_UnlockMutex(m_menu_mutex);
#endif #endif
// focus lost moved to M_Drawer // focus lost moved to M_Drawer
+6 -6
View File
@@ -112,7 +112,7 @@ static fileused_t transferFiles[UINT8_MAX + 1];
INT32 fileneedednum = 0; // Number of files needed to join the server INT32 fileneedednum = 0; // Number of files needed to join the server
fileneeded_t fileneeded[MAX_WADFILES] = {}; // List of needed files fileneeded_t fileneeded[MAX_WADFILES] = {}; // List of needed files
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
static I_mutex downloadmutex; static I_Mutex downloadmutex;
#endif #endif
char downloaddir[512] = "DOWNLOAD"; char downloaddir[512] = "DOWNLOAD";
@@ -1427,7 +1427,7 @@ void CURLPrepareFile(const char* url, int dfilenum)
filedownload.http_running = true; filedownload.http_running = true;
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_spawn_thread("http-download", (I_thread_fn)CURLGetFile, NULL); (void)!I_SpawnThread("http-download", (I_ThreadFn)CURLGetFile, NULL);
#endif #endif
} }
else else
@@ -1440,15 +1440,15 @@ void CURLAbortFile(void)
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
// lock and unlock to wait for the download thread to exit // lock and unlock to wait for the download thread to exit
I_lock_mutex(&downloadmutex); I_LockMutex(&downloadmutex);
I_unlock_mutex(downloadmutex); I_UnlockMutex(downloadmutex);
#endif #endif
} }
static void CURLGetFile(void) static void CURLGetFile(void)
{ {
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_lock_mutex(&downloadmutex); I_LockMutex(&downloadmutex);
#endif #endif
CURLMcode mc; /* return code used by curl_multi_wait() */ CURLMcode mc; /* return code used by curl_multi_wait() */
CURLcode easyres; /* Return from easy interface */ CURLcode easyres; /* Return from easy interface */
@@ -1549,7 +1549,7 @@ static void CURLGetFile(void)
filedownload.http_running = false; filedownload.http_running = false;
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_unlock_mutex(downloadmutex); I_UnlockMutex(downloadmutex);
#endif #endif
} }
-1
View File
@@ -2,6 +2,5 @@ i_system.c
i_main.c i_main.c
i_video.c i_video.c
i_sound.c i_sound.c
i_threads.c
dosstr.c dosstr.c
endtxt.c endtxt.c
+2 -2
View File
@@ -1381,8 +1381,8 @@ INT32 I_StartupSystem(void)
I_Fork(); I_Fork();
#endif #endif
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_start_threads(); I_StartThreads();
I_AddExitFunc(I_stop_threads); I_AddExitFunc(I_StopThreads);
#endif #endif
I_RegisterSignals(); I_RegisterSignals();
#ifndef NOMUMBLE #ifndef NOMUMBLE
+5
View File
@@ -223,6 +223,8 @@ typedef int32_t boolean;
#define FUNCNOINLINE __attribute__((noinline)) #define FUNCNOINLINE __attribute__((noinline))
#define FUNCWARNRV __attribute__((warn_unused_result))
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) // >= GCC 4.4 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) // >= GCC 4.4
#ifdef __i386__ // i386 only #ifdef __i386__ // i386 only
#define FUNCTARGET(X) __attribute__ ((__target__ (X))) #define FUNCTARGET(X) __attribute__ ((__target__ (X)))
@@ -268,6 +270,9 @@ typedef int32_t boolean;
#ifndef FUNCTARGET #ifndef FUNCTARGET
#define FUNCTARGET(x) #define FUNCTARGET(x)
#endif #endif
#ifndef FUNCWARNRV
#define FUNCWARNRV
#endif
#ifndef ATTRPACK #ifndef ATTRPACK
#define ATTRPACK #define ATTRPACK
#endif #endif
+2 -2
View File
@@ -388,11 +388,11 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
if (rendermode != render_none && drawMenu) if (rendermode != render_none && drawMenu)
{ {
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex); I_LockMutex(&m_menu_mutex);
#endif #endif
M_Drawer(); // menu is drawn even on top of wipes M_Drawer(); // menu is drawn even on top of wipes
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex); I_UnlockMutex(m_menu_mutex);
#endif #endif
} }
+9 -9
View File
@@ -62,7 +62,7 @@ static int hms_started;
static char *hms_api; static char *hms_api;
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
static I_mutex hms_api_mutex; static I_Mutex hms_api_mutex;
#endif #endif
static char *hms_server_token; static char *hms_server_token;
@@ -90,9 +90,9 @@ Printf_url (const char *url)
boolean startup; boolean startup;
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_lock_mutex(&con_mutex); I_LockMutex(&con_mutex);
startup = con_startup; startup = con_startup;
I_unlock_mutex(con_mutex); I_UnlockMutex(con_mutex);
#else #else
startup = con_startup; startup = con_startup;
#endif #endif
@@ -183,7 +183,7 @@ HMS_connect (const char *format, ...)
} }
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_lock_mutex(&hms_api_mutex); I_LockMutex(&hms_api_mutex);
#endif #endif
seek = strlen(hms_api) + 1;/* + '/' */ seek = strlen(hms_api) + 1;/* + '/' */
@@ -195,7 +195,7 @@ HMS_connect (const char *format, ...)
sprintf(url, "%s/", hms_api); sprintf(url, "%s/", hms_api);
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_unlock_mutex(hms_api_mutex); I_UnlockMutex(hms_api_mutex);
#endif #endif
va_start (ap, format); va_start (ap, format);
@@ -477,12 +477,12 @@ HMS_fetch_servers (msg_server_t *list, int query_id)
if (address && port) if (address && port)
{ {
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_lock_mutex(&ms_QueryId_mutex); I_LockMutex(&ms_QueryId_mutex);
{ {
if (query_id != ms_QueryId) if (query_id != ms_QueryId)
doing_shit = 0; doing_shit = 0;
} }
I_unlock_mutex(ms_QueryId_mutex); I_UnlockMutex(ms_QueryId_mutex);
if (! doing_shit) if (! doing_shit)
break; break;
@@ -611,14 +611,14 @@ void
HMS_set_api (char *api) HMS_set_api (char *api)
{ {
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_lock_mutex(&hms_api_mutex); I_LockMutex(&hms_api_mutex);
#endif #endif
{ {
free(hms_api); free(hms_api);
hms_api = Strip_trailing_slashes(api); hms_api = Strip_trailing_slashes(api);
} }
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_unlock_mutex(hms_api_mutex); I_UnlockMutex(hms_api_mutex);
#endif #endif
} }
+87 -59
View File
@@ -1,4 +1,4 @@
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2 KART
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 2020-2023 by James R. // Copyright (C) 2020-2023 by James R.
// //
@@ -9,12 +9,14 @@
/// \file i_threads.c /// \file i_threads.c
/// \brief Multithreading abstraction /// \brief Multithreading abstraction
#if defined (__unix__) || (!defined(__APPLE__) && defined (UNIXCOMMON)) #ifdef HAVE_THREADS
#if defined (__unix__) || defined(UNIXCOMMON)
#include <pthread.h> #include <pthread.h>
#include "../i_threads.h" #include "i_threads.h"
#include "../doomdef.h" #include "doomdef.h"
#include "doomtype.h"
typedef struct thread_s thread_t; typedef struct thread_s thread_t;
@@ -22,7 +24,7 @@ struct thread_s
{ {
thread_t *next; thread_t *next;
void *userdata; void *userdata;
I_thread_fn func; I_ThreadFn func;
pthread_t thread; pthread_t thread;
}; };
@@ -41,12 +43,8 @@ static void *HandleThread(void *data)
return NULL; return NULL;
} }
void FUNCWARNRV
I_spawn_thread ( int I_SpawnThread(const char *name, I_ThreadFn entry, void *userdata)
const char * name,
I_thread_fn entry,
void * userdata
)
{ {
thread_t *thread; thread_t *thread;
(void)name; (void)name;
@@ -66,17 +64,20 @@ I_spawn_thread (
if (thread == NULL) if (thread == NULL)
{ {
thread = malloc(sizeof(thread_t)); thread = malloc(sizeof(thread_t));
if (thread == NULL)
return false;
thread->next = thread_list; thread->next = thread_list;
thread_list = thread; thread_list = thread;
} }
thread->func = entry; thread->func = entry;
thread->userdata = userdata; thread->userdata = userdata;
pthread_create(&thread->thread, NULL, HandleThread, thread); int err = pthread_create(&thread->thread, NULL, HandleThread, thread);
pthread_mutex_unlock(&thread_lock); pthread_mutex_unlock(&thread_lock);
return err == 0;
} }
int I_thread_is_stopped(void) int I_ThreadIsStopped(void)
{ {
thread_t *thread; thread_t *thread;
pthread_mutex_lock(&thread_lock); pthread_mutex_lock(&thread_lock);
@@ -94,11 +95,11 @@ int I_thread_is_stopped(void)
return true; return true;
} }
void I_start_threads(void) void I_StartThreads(void)
{ {
} }
void I_stop_threads(void) void I_StopThreads(void)
{ {
thread_t *thread = thread_list; thread_t *thread = thread_list;
while (thread != NULL) while (thread != NULL)
@@ -109,7 +110,7 @@ void I_stop_threads(void)
} }
} }
void I_lock_mutex(I_mutex *anchor) void I_LockMutex(I_Mutex *anchor)
{ {
pthread_mutex_lock(&thread_lock); pthread_mutex_lock(&thread_lock);
if (*anchor == NULL) if (*anchor == NULL)
@@ -127,25 +128,25 @@ void I_lock_mutex(I_mutex *anchor)
pthread_mutex_lock(*anchor); pthread_mutex_lock(*anchor);
} }
void I_unlock_mutex(I_mutex id) void I_UnlockMutex(I_Mutex id)
{ {
pthread_mutex_unlock(id); pthread_mutex_unlock(id);
} }
void I_hold_cond(I_cond *cond_anchor, I_mutex mutex_id) void I_HoldCond(I_Cond *condAnchor, I_Mutex mutexId)
{ {
I_Assert(mutex_id != NULL); I_Assert(mutexId != NULL);
pthread_mutex_lock(&thread_lock); pthread_mutex_lock(&thread_lock);
if (*cond_anchor == NULL) if (*condAnchor == NULL)
{ {
*cond_anchor = malloc(sizeof(pthread_cond_t)); *condAnchor = malloc(sizeof(pthread_cond_t));
pthread_cond_init(*cond_anchor, NULL); pthread_cond_init(*condAnchor, NULL);
} }
pthread_mutex_unlock(&thread_lock); pthread_mutex_unlock(&thread_lock);
pthread_cond_wait(*cond_anchor, mutex_id); pthread_cond_wait(*condAnchor, mutexId);
} }
void I_wake_one_cond(I_cond *anchor) void I_WakeOneCond(I_Cond *anchor)
{ {
pthread_mutex_lock(&thread_lock); pthread_mutex_lock(&thread_lock);
if (*anchor == NULL) if (*anchor == NULL)
@@ -157,7 +158,7 @@ void I_wake_one_cond(I_cond *anchor)
pthread_cond_signal(*anchor); pthread_cond_signal(*anchor);
} }
void I_wake_all_cond(I_cond *anchor) void I_WakeAllCond(I_Cond *anchor)
{ {
pthread_mutex_lock(&thread_lock); pthread_mutex_lock(&thread_lock);
if (*anchor == NULL) if (*anchor == NULL)
@@ -168,12 +169,17 @@ void I_wake_all_cond(I_cond *anchor)
pthread_mutex_unlock(&thread_lock); pthread_mutex_unlock(&thread_lock);
pthread_cond_broadcast(*anchor); pthread_cond_broadcast(*anchor);
} }
thread_handle_t I_GetCurrentThread(void)
{
return pthread_self();
}
#elif defined (_WIN32) #elif defined (_WIN32)
#include <windows.h> #include <windows.h>
#include "../i_threads.h" #include "i_threads.h"
#include "../doomdef.h" #include "doomdef.h"
#include "../doomtype.h" #include "doomtype.h"
typedef struct thread_s thread_t; typedef struct thread_s thread_t;
@@ -181,9 +187,9 @@ struct thread_s
{ {
thread_t *next; thread_t *next;
void *userdata; void *userdata;
I_thread_fn func; I_ThreadFn func;
HANDLE thread; HANDLE thread;
DWORD thread_id; DWORD threadId;
}; };
// we use a linked list to avoid moving memory blocks when allocating new threads. // we use a linked list to avoid moving memory blocks when allocating new threads.
@@ -201,7 +207,8 @@ static DWORD __stdcall HandleThread(void *data)
return 0; return 0;
} }
void I_spawn_thread(const char *name, I_thread_fn entry, void *userdata) FUNCWARNRV
int I_SpawnThread(const char *name, I_ThreadFn entry, void *userdata)
{ {
thread_t *thread; thread_t *thread;
(void)name; (void)name;
@@ -219,17 +226,20 @@ void I_spawn_thread(const char *name, I_thread_fn entry, void *userdata)
if (thread == NULL) if (thread == NULL)
{ {
thread = malloc(sizeof(thread_t)); thread = malloc(sizeof(thread_t));
if (thread == NULL)
return false;
thread->next = thread_list; thread->next = thread_list;
thread_list = thread; thread_list = thread;
} }
thread->func = entry; thread->func = entry;
thread->userdata = userdata; thread->userdata = userdata;
thread->thread = CreateThread(NULL, 0, HandleThread, thread, 0, &thread->thread_id); thread->thread = CreateThread(NULL, 0, HandleThread, thread, 0, &thread->threadId);
LeaveCriticalSection(&thread_lock); LeaveCriticalSection(&thread_lock);
return thread->thread != NULL;
} }
int I_thread_is_stopped(void) int I_ThreadIsStopped(void)
{ {
thread_t *thread; thread_t *thread;
EnterCriticalSection(&thread_lock); EnterCriticalSection(&thread_lock);
@@ -247,12 +257,12 @@ int I_thread_is_stopped(void)
return true; return true;
} }
void I_start_threads(void) void I_StartThreads(void)
{ {
InitializeCriticalSection(&thread_lock); InitializeCriticalSection(&thread_lock);
} }
void I_stop_threads(void) void I_StopThreads(void)
{ {
thread_t *thread = thread_list; thread_t *thread = thread_list;
while (thread != NULL) while (thread != NULL)
@@ -264,7 +274,7 @@ void I_stop_threads(void)
DeleteCriticalSection(&thread_lock); DeleteCriticalSection(&thread_lock);
} }
void I_lock_mutex(I_mutex *anchor) void I_LockMutex(I_Mutex *anchor)
{ {
EnterCriticalSection(&thread_lock); EnterCriticalSection(&thread_lock);
if (*anchor == NULL) if (*anchor == NULL)
@@ -276,25 +286,25 @@ void I_lock_mutex(I_mutex *anchor)
EnterCriticalSection(*anchor); EnterCriticalSection(*anchor);
} }
void I_unlock_mutex(I_mutex id) void I_UnlockMutex(I_Mutex id)
{ {
LeaveCriticalSection(id); LeaveCriticalSection(id);
} }
void I_hold_cond(I_cond *cond_anchor, I_mutex mutex_id) void I_HoldCond(I_Cond *condAnchor, I_Mutex mutexId)
{ {
I_Assert(mutex_id != NULL); I_Assert(mutexId != NULL);
EnterCriticalSection(&thread_lock); EnterCriticalSection(&thread_lock);
if (*cond_anchor == NULL) if (*condAnchor == NULL)
{ {
*cond_anchor = malloc(sizeof(CONDITION_VARIABLE)); *condAnchor = malloc(sizeof(CONDITION_VARIABLE));
InitializeConditionVariable(*cond_anchor); InitializeConditionVariable(*condAnchor);
} }
LeaveCriticalSection(&thread_lock); LeaveCriticalSection(&thread_lock);
SleepConditionVariableCS(*cond_anchor, mutex_id, INFINITE); SleepConditionVariableCS(*condAnchor, mutexId, INFINITE);
} }
void I_wake_one_cond(I_cond *anchor) void I_WakeOneCond(I_Cond *anchor)
{ {
EnterCriticalSection(&thread_lock); EnterCriticalSection(&thread_lock);
if (*anchor == NULL) if (*anchor == NULL)
@@ -306,7 +316,7 @@ void I_wake_one_cond(I_cond *anchor)
WakeConditionVariable(*anchor); WakeConditionVariable(*anchor);
} }
void I_wake_all_cond(I_cond *anchor) void I_WakeAllCond(I_Cond *anchor)
{ {
EnterCriticalSection(&thread_lock); EnterCriticalSection(&thread_lock);
if (*anchor == NULL) if (*anchor == NULL)
@@ -317,48 +327,66 @@ void I_wake_all_cond(I_cond *anchor)
LeaveCriticalSection(&thread_lock); LeaveCriticalSection(&thread_lock);
WakeAllConditionVariable(*anchor); WakeAllConditionVariable(*anchor);
} }
void *I_GetCurrentThread(void)
{
return GetCurrentThread();
}
#else #else
void I_spawn_thread(const char *name, I_thread_fn entry, void *userdata) #include "i_threads.h"
FUNCWARNRV
int I_SpawnThread(const char *name, I_ThreadFn entry, void *userdata)
{ {
(void)name; (void)name;
entry(userdata); entry(userdata);
return true;
} }
int I_thread_is_stopped(void) int I_ThreadIsStopped(void)
{
return true;
}
void I_StartThreads(void)
{ {
} }
void I_start_threads(void) void I_StopThreads(void)
{ {
} }
void I_stop_threads(void) void I_LockMutex(I_Mutex *anchor)
{
}
void I_lock_mutex(I_mutex *anchor)
{ {
(void)anchor; (void)anchor;
} }
void I_unlock_mutex(I_mutex id) void I_UnlockMutex(I_Mutex id)
{ {
(void)id; (void)id;
} }
void I_hold_cond(I_cond *cond_anchor, I_mutex mutex_id) void I_HoldCond(I_Cond *condAnchor, I_Mutex mutexId)
{ {
(void)cond_anchor; (void)condAnchor;
(void)mutex_id; (void)mutexId;
} }
void I_wake_one_cond(I_cond *anchor) void I_WakeOneCond(I_Cond *anchor)
{ {
(void)anchor; (void)anchor;
} }
void I_wake_all_cond(I_cond *anchor) void I_WakeAllCond(I_Cond *anchor)
{ {
(void)anchor; (void)anchor;
} }
void *I_GetCurrentThread(void)
{
return NULL;
}
#endif #endif
#endif // HAVE_THREADS
+25 -13
View File
@@ -1,6 +1,6 @@
// SONIC ROBO BLAST 2 KART // SONIC ROBO BLAST 2 KART
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 2020 by James R. // Copyright (C) 2020-2023 by James R.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
@@ -14,34 +14,46 @@
#ifndef I_THREADS_H #ifndef I_THREADS_H
#define I_THREADS_H #define I_THREADS_H
#include "doomtype.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
typedef void (*I_thread_fn)(void *userdata); typedef void (*I_ThreadFn)(void *userdata);
typedef void * I_mutex; typedef void * I_Mutex;
typedef void * I_cond; typedef void * I_Cond;
void I_start_threads (void); #ifdef __linux__
void I_stop_threads (void); typedef long unsigned int thread_handle_t;
#else
typedef void *thread_handle_t;
#endif
void I_spawn_thread (const char *name, I_thread_fn, void *userdata); void I_StartThreads (void);
void I_StopThreads (void);
FUNCWARNRV
int I_SpawnThread (const char *name, I_ThreadFn, void *userdata);
/* check in your thread whether to return early */ /* check in your thread whether to return early */
int I_thread_is_stopped (void); int I_ThreadIsStopped (void);
void I_lock_mutex (I_mutex *); void I_LockMutex (I_Mutex *);
void I_unlock_mutex (I_mutex); void I_UnlockMutex (I_Mutex);
void I_hold_cond (I_cond *, I_mutex); void I_HoldCond (I_Cond *, I_Mutex);
void I_wake_one_cond (I_cond *); void I_WakeOneCond (I_Cond *);
void I_wake_all_cond (I_cond *); void I_WakeAllCond (I_Cond *);
thread_handle_t I_GetCurrentThread(void);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif
#endif/*I_THREADS_H*/ #endif/*I_THREADS_H*/
#endif/*HAVE_THREADS*/ #endif/*HAVE_THREADS*/
+32 -26
View File
@@ -142,7 +142,7 @@ typedef enum
} text_enum; } text_enum;
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_mutex m_menu_mutex; I_Mutex m_menu_mutex;
#endif #endif
M_waiting_mode_t m_waiting_mode = M_NOT_WAITING; M_waiting_mode_t m_waiting_mode = M_NOT_WAITING;
@@ -1967,7 +1967,7 @@ void M_Ticker(void)
} }
#if defined (MASTERSERVER) && defined (HAVE_THREADS) #if defined (MASTERSERVER) && defined (HAVE_THREADS)
I_lock_mutex(&ms_ServerList_mutex); I_LockMutex(&ms_ServerList_mutex);
{ {
if (ms_ServerList) if (ms_ServerList)
{ {
@@ -1976,7 +1976,7 @@ void M_Ticker(void)
ms_ServerList = NULL; ms_ServerList = NULL;
} }
} }
I_unlock_mutex(ms_ServerList_mutex); I_UnlockMutex(ms_ServerList_mutex);
#endif #endif
} }
@@ -4014,14 +4014,14 @@ size_t demolist_all_size = 0;
boolean replaynamesloaded = false; boolean replaynamesloaded = false;
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_mutex replayquerymutex; I_Mutex replayquerymutex;
// g_in_exiting_signal_handler is an evil hack // g_in_exiting_signal_handler is an evil hack
// to avoid infinite SIGABRT recursion in the signal handler // to avoid infinite SIGABRT recursion in the signal handler
// due to poisoned locks or mach-o kernel not supporting locks in signals // due to poisoned locks or mach-o kernel not supporting locks in signals
// or something like that. idk // or something like that. idk
# define Lock_search_state() if (!g_in_exiting_signal_handler) { I_lock_mutex(&replayquerymutex); } # define Lock_search_state() if (!g_in_exiting_signal_handler) { I_LockMutex(&replayquerymutex); }
# define Unlock_search_state() if (!g_in_exiting_signal_handler) { I_unlock_mutex(replayquerymutex); } # define Unlock_search_state() if (!g_in_exiting_signal_handler) { I_UnlockMutex(replayquerymutex); }
#else/*HAVE_THREADS*/ #else/*HAVE_THREADS*/
# define Lock_search_state() # define Lock_search_state()
# define Unlock_search_state() # define Unlock_search_state()
@@ -4088,7 +4088,10 @@ static void LoadReplayNames(void)
Unlock_search_state(); Unlock_search_state();
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_spawn_thread("replay-names-load", ReplayNamesLoadThread, replaydirpath); if (!I_SpawnThread("replay-names-load", ReplayNamesLoadThread, replaydirpath))
{
free(replaydirpath);
}
#else #else
ReplayNamesLoadThread(replaydirpath); ReplayNamesLoadThread(replaydirpath);
#endif #endif
@@ -6684,11 +6687,11 @@ static void M_EndGame(INT32 choice)
void M_SetWaitingMode(int mode) void M_SetWaitingMode(int mode)
{ {
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex); I_LockMutex(&m_menu_mutex);
#endif #endif
m_waiting_mode = mode; m_waiting_mode = mode;
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex); I_UnlockMutex(m_menu_mutex);
#endif #endif
} }
@@ -6697,11 +6700,11 @@ int M_GetWaitingMode(void)
int mode; int mode;
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex); I_LockMutex(&m_menu_mutex);
#endif #endif
mode = m_waiting_mode; mode = m_waiting_mode;
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex); I_UnlockMutex(m_menu_mutex);
#endif #endif
return mode; return mode;
@@ -6713,20 +6716,23 @@ static void Spawn_masterserver_thread(const char *name, void (*thread)(int*))
{ {
int *id = malloc(sizeof *id); int *id = malloc(sizeof *id);
I_lock_mutex(&ms_QueryId_mutex); I_LockMutex(&ms_QueryId_mutex);
*id = ms_QueryId; *id = ms_QueryId;
I_unlock_mutex(ms_QueryId_mutex); I_UnlockMutex(ms_QueryId_mutex);
I_spawn_thread(name, (I_thread_fn)thread, id); if (!I_SpawnThread(name, (I_ThreadFn)thread, id))
{
free(id);
}
} }
static int Same_instance(int id) static int Same_instance(int id)
{ {
int okay; int okay;
I_lock_mutex(&ms_QueryId_mutex); I_LockMutex(&ms_QueryId_mutex);
okay = ( id == ms_QueryId ); okay = ( id == ms_QueryId );
I_unlock_mutex(ms_QueryId_mutex); I_UnlockMutex(ms_QueryId_mutex);
return okay; return okay;
} }
@@ -6755,9 +6761,9 @@ static void Fetch_servers_thread(int *id)
M_SetWaitingMode(M_NOT_WAITING); M_SetWaitingMode(M_NOT_WAITING);
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_lock_mutex(&ms_ServerList_mutex); I_LockMutex(&ms_ServerList_mutex);
ms_ServerList = server_list; ms_ServerList = server_list;
I_unlock_mutex(ms_ServerList_mutex); I_UnlockMutex(ms_ServerList_mutex);
#else #else
CL_QueryServerList(server_list); CL_QueryServerList(server_list);
free(server_list); free(server_list);
@@ -6790,7 +6796,7 @@ static void M_SearchServerList(void)
serverlistsearchedcount = 0; serverlistsearchedcount = 0;
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_lock_mutex(&ms_ServerList_mutex); I_LockMutex(&ms_ServerList_mutex);
#endif #endif
for (UINT32 i = 0; i < serverlistcount; ++i) for (UINT32 i = 0; i < serverlistcount; ++i)
@@ -6801,7 +6807,7 @@ static void M_SearchServerList(void)
} }
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_unlock_mutex(ms_ServerList_mutex); I_UnlockMutex(ms_ServerList_mutex);
#endif #endif
if (menuinput.length > 0) if (menuinput.length > 0)
@@ -7167,11 +7173,11 @@ static void M_CheckMODVersion(int id)
{ {
sprintf(updatestring, UPDATE_ALERT_STRING, VERSIONSTRING, updatecheck); sprintf(updatestring, UPDATE_ALERT_STRING, VERSIONSTRING, updatecheck);
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex); I_LockMutex(&m_menu_mutex);
#endif #endif
M_StartMessage(updatestring, NULL, MM_NOTHING); M_StartMessage(updatestring, NULL, MM_NOTHING);
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex); I_UnlockMutex(m_menu_mutex);
#endif #endif
} }
} }
@@ -7217,13 +7223,13 @@ static void M_ConnectMenu(INT32 choice)
itemOn = 0; itemOn = 0;
#if defined (MASTERSERVER) && defined (HAVE_THREADS) #if defined (MASTERSERVER) && defined (HAVE_THREADS)
I_lock_mutex(&ms_QueryId_mutex); I_LockMutex(&ms_QueryId_mutex);
{ {
ms_QueryId++; ms_QueryId++;
} }
I_unlock_mutex(ms_QueryId_mutex); I_UnlockMutex(ms_QueryId_mutex);
I_lock_mutex(&ms_ServerList_mutex); I_LockMutex(&ms_ServerList_mutex);
{ {
if (ms_ServerList) if (ms_ServerList)
{ {
@@ -7231,7 +7237,7 @@ static void M_ConnectMenu(INT32 choice)
ms_ServerList = NULL; ms_ServerList = NULL;
} }
} }
I_unlock_mutex(ms_ServerList_mutex); I_UnlockMutex(ms_ServerList_mutex);
#ifdef UPDATE_ALERT #ifdef UPDATE_ALERT
Spawn_masterserver_thread("check-new-version", Check_new_version_thread); Spawn_masterserver_thread("check-new-version", Check_new_version_thread);
+1 -1
View File
@@ -215,7 +215,7 @@ void M_SetupNextMenu(menu_t *menudef);
void M_ClearMenus(boolean callexitmenufunc); void M_ClearMenus(boolean callexitmenufunc);
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
extern I_mutex m_menu_mutex; extern I_Mutex m_menu_mutex;
#endif #endif
extern menu_t *currentMenu; extern menu_t *currentMenu;
+33 -29
View File
@@ -41,11 +41,11 @@ static time_t MSLastPing;
static char *MSRules; static char *MSRules;
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
static I_mutex MSMutex; static I_Mutex MSMutex;
static I_cond MSCond; static I_Cond MSCond;
# define Lock_state() I_lock_mutex (&MSMutex) # define Lock_state() I_LockMutex (&MSMutex)
# define Unlock_state() I_unlock_mutex (MSMutex) # define Unlock_state() I_UnlockMutex (MSMutex)
#else/*HAVE_THREADS*/ #else/*HAVE_THREADS*/
# define Lock_state() # define Lock_state()
# define Unlock_state() # define Unlock_state()
@@ -90,10 +90,10 @@ consvar_t cv_masterserver_nagattempts = {"masterserver_nagattempts", "5", CV_SAV
#if defined (MASTERSERVER) && defined (HAVE_THREADS) #if defined (MASTERSERVER) && defined (HAVE_THREADS)
int ms_QueryId = 0; int ms_QueryId = 0;
I_mutex ms_QueryId_mutex; I_Mutex ms_QueryId_mutex;
msg_server_t *ms_ServerList = NULL; msg_server_t *ms_ServerList = NULL;
I_mutex ms_ServerList_mutex; I_Mutex ms_ServerList_mutex;
#endif #endif
UINT16 current_port = 0; UINT16 current_port = 0;
@@ -129,11 +129,11 @@ void AddMServCommands(void)
static void WarnGUI (void) static void WarnGUI (void)
{ {
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex); I_LockMutex(&m_menu_mutex);
#endif #endif
M_PopupMasterServerConnectError(); M_PopupMasterServerConnectError();
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex); I_UnlockMutex(m_menu_mutex);
#endif #endif
} }
@@ -168,12 +168,12 @@ char *GetMODVersion(int id)
c = HMS_compare_mod_version(buffer, 16); c = HMS_compare_mod_version(buffer, 16);
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_lock_mutex(&ms_QueryId_mutex); I_LockMutex(&ms_QueryId_mutex);
{ {
if (id != ms_QueryId) if (id != ms_QueryId)
c = -1; c = -1;
} }
I_unlock_mutex(ms_QueryId_mutex); I_UnlockMutex(ms_QueryId_mutex);
#endif #endif
if (c > 0) if (c > 0)
@@ -341,7 +341,7 @@ Finish_unlist (void)
Unlock_state(); Unlock_state();
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_wake_all_cond(&MSCond); I_WakeAllCond(&MSCond);
#endif #endif
} }
} }
@@ -377,7 +377,7 @@ New_server_id (void)
Lock_state(); Lock_state();
{ {
*id = ++MSId; *id = ++MSId;
I_wake_all_cond(&MSCond); I_WakeAllCond(&MSCond);
} }
Unlock_state(); Unlock_state();
return id; return id;
@@ -392,7 +392,7 @@ Register_server_thread (int *id)
{ {
/* wait for previous unlist to finish */ /* wait for previous unlist to finish */
while (*id == MSId && MSRegistered) while (*id == MSId && MSRegistered)
I_hold_cond(&MSCond, MSMutex); I_HoldCond(&MSCond, MSMutex);
same = ( *id == MSId );/* it could have been a while */ same = ( *id == MSId );/* it could have been a while */
} }
@@ -444,7 +444,7 @@ Change_masterserver_thread (char *api)
Lock_state(); Lock_state();
{ {
while (MSRegistered) while (MSRegistered)
I_hold_cond(&MSCond, MSMutex); I_HoldCond(&MSCond, MSMutex);
} }
Unlock_state(); Unlock_state();
@@ -464,9 +464,9 @@ void RegisterServer(void)
{ {
#ifdef MASTERSERVER #ifdef MASTERSERVER
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_spawn_thread( (void)!I_SpawnThread(
"register-server", "register-server",
(I_thread_fn)Register_server_thread, (I_ThreadFn)Register_server_thread,
New_server_id() New_server_id()
); );
#else #else
@@ -478,9 +478,9 @@ void RegisterServer(void)
static void UpdateServer(void) static void UpdateServer(void)
{ {
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_spawn_thread( (void)!I_SpawnThread(
"update-server", "update-server",
(I_thread_fn)Update_server_thread, (I_ThreadFn)Update_server_thread,
Server_id() Server_id()
); );
#else #else
@@ -492,9 +492,9 @@ void UnregisterServer(void)
{ {
#ifdef MASTERSERVER #ifdef MASTERSERVER
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_spawn_thread( (void)!I_SpawnThread(
"unlist-server", "unlist-server",
(I_thread_fn)Unlist_server_thread, (I_ThreadFn)Unlist_server_thread,
Server_id() Server_id()
); );
#else #else
@@ -557,14 +557,18 @@ void MasterClient_Ticker(void)
static void static void
Set_api (const char *api) Set_api (const char *api)
{ {
char *dapi = strdup(api);
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_spawn_thread( if (!I_SpawnThread(
"change-masterserver", "change-masterserver",
(I_thread_fn)Change_masterserver_thread, (I_ThreadFn)Change_masterserver_thread,
strdup(api) dapi
); ))
{
free(dapi);
}
#else #else
Finish_masterserver_change(strdup(api)); Finish_masterserver_change(dapi);
#endif #endif
} }
@@ -572,9 +576,9 @@ void
Get_rules (void) Get_rules (void)
{ {
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_spawn_thread( (void)!I_SpawnThread(
"get-masterserver-rules", "get-masterserver-rules",
(I_thread_fn)Get_masterserver_rules_thread, (I_ThreadFn)Get_masterserver_rules_thread,
NULL NULL
); );
#else #else
+2 -2
View File
@@ -69,10 +69,10 @@ extern consvar_t cv_rendezvousserver;
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
extern int ms_QueryId; extern int ms_QueryId;
extern I_mutex ms_QueryId_mutex; extern I_Mutex ms_QueryId_mutex;
extern msg_server_t *ms_ServerList; extern msg_server_t *ms_ServerList;
extern I_mutex ms_ServerList_mutex; extern I_Mutex ms_ServerList_mutex;
#endif #endif
#ifdef MASTERSERVER #ifdef MASTERSERVER
void RegisterServer(void); void RegisterServer(void);
+8 -2
View File
@@ -289,8 +289,14 @@ void R_GenerateBlendTables(void)
state->LocalPalette = static_cast<RGBA_t *>(memcpy(malloc(palsize), pLocalPalette, palsize)); state->LocalPalette = static_cast<RGBA_t *>(memcpy(malloc(palsize), pLocalPalette, palsize));
state->gammaCorrectedPalette = static_cast<RGBA_t *>(memcpy(malloc(palsize), pGammaCorrectedPalette, palsize)); state->gammaCorrectedPalette = static_cast<RGBA_t *>(memcpy(malloc(palsize), pGammaCorrectedPalette, palsize));
I_spawn_thread("blend-tables", if (!I_SpawnThread("blend-tables",
R_GenerateBlendTables_Thread, state); R_GenerateBlendTables_Thread, state))
{
free(state->gammaCorrectedPalette);
free(state->LocalPalette);
free(state);
I_Error("R_GenerateBlendTables: Failed to generate BlendTables\n"); // should we just retry on main thread instead?
}
#else #else
struct GenerateBlendTables_State state = {pLocalPalette, pGammaCorrectedPalette}; struct GenerateBlendTables_State state = {pLocalPalette, pGammaCorrectedPalette};
R_GenerateBlendTables_Core(&state); R_GenerateBlendTables_Core(&state);
-1
View File
@@ -35,7 +35,6 @@ set(SRB2_SDL2_SOURCES
i_system.cpp i_system.cpp
i_ttf.c i_ttf.c
i_video.c i_video.c
i_threads.c
#IMG_xpm.c #IMG_xpm.c
ogl_sdl.c ogl_sdl.c
+2 -2
View File
@@ -1896,8 +1896,8 @@ INT32 I_StartupSystem(void)
I_Fork(); I_Fork();
#endif #endif
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_start_threads(); I_StartThreads();
I_AddExitFunc(I_stop_threads); I_AddExitFunc(I_StopThreads);
I_ThreadPoolInit(); I_ThreadPoolInit();
I_AddExitFunc(I_ThreadPoolShutdown); I_AddExitFunc(I_ThreadPoolShutdown);
#endif #endif
-360
View File
@@ -1,360 +0,0 @@
// SONIC ROBO BLAST 2 KART
//-----------------------------------------------------------------------------
// Copyright (C) 2020 by James R.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file i_threads.c
/// \brief Multithreading abstraction
#ifdef HAVE_THREADS
#include "../doomdef.h"
#include "../i_threads.h"
#include <SDL.h>
typedef void * (*Create_fn)(void);
struct Link;
struct Thread;
typedef struct Link * Link;
typedef struct Thread * Thread;
struct Link
{
void * data;
Link next;
Link prev;
};
struct Thread
{
I_thread_fn entry;
void * userdata;
SDL_Thread * thread;
};
static Link i_thread_pool;
static Link i_mutex_pool;
static Link i_cond_pool;
static I_mutex i_thread_pool_mutex;
static I_mutex i_mutex_pool_mutex;
static I_mutex i_cond_pool_mutex;
static SDL_atomic_t i_threads_running = {1};
static Link
Insert_link (
Link * head,
Link link
){
link->prev = NULL;
link->next = (*head);
if ((*head))
(*head)->prev = link;
(*head) = link;
return link;
}
static void
Free_link (
Link * head,
Link link
){
if (link->prev)
link->prev->next = link->next;
else
(*head) = link->next;
if (link->next)
link->next->prev = link->prev;
free(link->data);
free(link);
}
static Link
New_link (void *data)
{
Link link;
link = malloc(sizeof *link);
if (! link)
abort();
link->data = data;
return link;
}
static void *
Identity (
Link * pool_anchor,
I_mutex pool_mutex,
void ** anchor,
Create_fn create_fn
){
void * id;
id = SDL_AtomicGetPtr(anchor);
if (! id)
{
I_lock_mutex(&pool_mutex);
{
id = SDL_AtomicGetPtr(anchor);
if (! id)
{
id = (*create_fn)();
if (! id)
abort();
Insert_link(pool_anchor, New_link(id));
SDL_AtomicSetPtr(anchor, id);
}
}
I_unlock_mutex(pool_mutex);
}
return id;
}
static int
Worker (
Link link
){
Thread th;
th = link->data;
(*th->entry)(th->userdata);
if (SDL_AtomicGet(&i_threads_running))
{
I_lock_mutex(&i_thread_pool_mutex);
{
if (SDL_AtomicGet(&i_threads_running))
{
SDL_DetachThread(th->thread);
Free_link(&i_thread_pool, link);
}
}
I_unlock_mutex(i_thread_pool_mutex);
}
return 0;
}
void
I_spawn_thread (
const char * name,
I_thread_fn entry,
void * userdata
){
Link link;
Thread th;
th = malloc(sizeof *th);
if (! th)
abort();/* this is pretty GNU of me */
th->entry = entry;
th->userdata = userdata;
I_lock_mutex(&i_thread_pool_mutex);
{
link = Insert_link(&i_thread_pool, New_link(th));
if (SDL_AtomicGet(&i_threads_running))
{
th->thread = SDL_CreateThread(
(SDL_ThreadFunction)Worker,
name,
link
);
if (! th->thread)
abort();
}
}
I_unlock_mutex(i_thread_pool_mutex);
}
int
I_thread_is_stopped (void)
{
return ( ! SDL_AtomicGet(&i_threads_running) );
}
void
I_start_threads (void)
{
i_thread_pool_mutex = SDL_CreateMutex();
i_mutex_pool_mutex = SDL_CreateMutex();
i_cond_pool_mutex = SDL_CreateMutex();
if (!(
i_thread_pool_mutex &&
i_mutex_pool_mutex &&
i_cond_pool_mutex
)){
abort();
}
}
void
I_stop_threads (void)
{
Link link;
Link next;
Thread th;
SDL_mutex * mutex;
SDL_cond * cond;
if (i_threads_running.value)
{
/* rely on the good will of thread-san */
SDL_AtomicSet(&i_threads_running, 0);
I_lock_mutex(&i_thread_pool_mutex);
{
for (
link = i_thread_pool;
link;
link = next
){
next = link->next;
th = link->data;
SDL_WaitThread(th->thread, NULL);
free(th);
free(link);
}
}
I_unlock_mutex(i_thread_pool_mutex);
for (
link = i_mutex_pool;
link;
link = next
){
next = link->next;
mutex = link->data;
SDL_DestroyMutex(mutex);
free(link);
}
for (
link = i_cond_pool;
link;
link = next
){
next = link->next;
cond = link->data;
SDL_DestroyCond(cond);
free(link);
}
SDL_DestroyMutex(i_thread_pool_mutex);
SDL_DestroyMutex(i_mutex_pool_mutex);
SDL_DestroyMutex(i_cond_pool_mutex);
}
}
void
I_lock_mutex (
I_mutex * anchor
){
SDL_mutex * mutex;
mutex = Identity(
&i_mutex_pool,
i_mutex_pool_mutex,
anchor,
(Create_fn)SDL_CreateMutex
);
if (SDL_LockMutex(mutex) == -1)
abort();
}
void
I_unlock_mutex (
I_mutex id
){
if (SDL_UnlockMutex(id) == -1)
abort();
}
void
I_hold_cond (
I_cond * cond_anchor,
I_mutex mutex_id
){
SDL_cond * cond;
cond = Identity(
&i_cond_pool,
i_cond_pool_mutex,
cond_anchor,
(Create_fn)SDL_CreateCond
);
if (SDL_CondWait(cond, mutex_id) == -1)
abort();
}
void
I_wake_one_cond (
I_cond * anchor
){
SDL_cond * cond;
cond = Identity(
&i_cond_pool,
i_cond_pool_mutex,
anchor,
(Create_fn)SDL_CreateCond
);
if (SDL_CondSignal(cond) == -1)
abort();
}
void
I_wake_all_cond (
I_cond * anchor
){
SDL_cond * cond;
cond = Identity(
&i_cond_pool,
i_cond_pool_mutex,
anchor,
(Create_fn)SDL_CreateCond
);
if (SDL_CondBroadcast(cond) == -1)
abort();
}
#endif // HAVE_THREADS
+15
View File
@@ -75,6 +75,8 @@ typedef struct memblock_s
#define MEMORY(x) (void *)((uintptr_t)(x) + sizeof(memblock_t) + ALIGNPAD) #define MEMORY(x) (void *)((uintptr_t)(x) + sizeof(memblock_t) + ALIGNPAD)
#define MEMBLOCK(x) (memblock_t *)((uintptr_t)(x) - ALIGNPAD - sizeof(memblock_t)) #define MEMBLOCK(x) (memblock_t *)((uintptr_t)(x) - ALIGNPAD - sizeof(memblock_t))
static thread_handle_t main_thread;
// both the head and tail of the zone memory block list // both the head and tail of the zone memory block list
static memblock_t head; static memblock_t head;
@@ -108,6 +110,7 @@ static void Command_Memdump_f(void);
void Z_Init(void) void Z_Init(void)
{ {
size_t total, memfree; size_t total, memfree;
main_thread = I_GetCurrentThread();
memset(&head, 0x00, sizeof(head)); memset(&head, 0x00, sizeof(head));
@@ -143,6 +146,8 @@ void Z_Free(void *ptr)
{ {
memblock_t *block; memblock_t *block;
I_Assert(I_GetCurrentThread() == main_thread);
if (ptr == NULL) if (ptr == NULL)
return; return;
@@ -237,6 +242,8 @@ void *Z_Malloc(size_t size, INT32 tag, void *user)
memblock_t *block; memblock_t *block;
void *ptr; void *ptr;
I_Assert(I_GetCurrentThread() == main_thread);
#ifdef ZDEBUG2 #ifdef ZDEBUG2
CONS_Debug(DBG_MEMORY, "Z_Malloc %s:%d\n", file, line); CONS_Debug(DBG_MEMORY, "Z_Malloc %s:%d\n", file, line);
#endif #endif
@@ -300,6 +307,8 @@ void *Z_Calloc2(size_t size, INT32 tag, void *user, const char *file, INT32 line
void *Z_Calloc(size_t size, INT32 tag, void *user) void *Z_Calloc(size_t size, INT32 tag, void *user)
#endif #endif
{ {
I_Assert(I_GetCurrentThread() == main_thread);
#ifdef VALGRIND_MEMPOOL_ALLOC #ifdef VALGRIND_MEMPOOL_ALLOC
Z_calloc = true; Z_calloc = true;
#endif #endif
@@ -335,6 +344,8 @@ void *Z_Realloc(void *ptr, size_t size, INT32 tag, void *user)
memblock_t *block; memblock_t *block;
size_t copysize; size_t copysize;
I_Assert(I_GetCurrentThread() == main_thread);
#ifdef ZDEBUG2 #ifdef ZDEBUG2
CONS_Debug(DBG_MEMORY, "Z_Realloc %s:%d\n", file, line); CONS_Debug(DBG_MEMORY, "Z_Realloc %s:%d\n", file, line);
#endif #endif
@@ -414,6 +425,8 @@ void Z_FreeTags(INT32 lowtag, INT32 hightag)
{ {
memblock_t *block, *next; memblock_t *block, *next;
I_Assert(I_GetCurrentThread() == main_thread);
#ifdef ZDEBUG #ifdef ZDEBUG
Z_CheckHeap2(file, line); Z_CheckHeap2(file, line);
#else #else
@@ -447,6 +460,8 @@ void Z_IterateTags(INT32 lowtag, INT32 hightag, boolean (*iterfunc)(void *))
{ {
memblock_t *block, *next; memblock_t *block, *next;
I_Assert(I_GetCurrentThread() == main_thread);
if (!iterfunc) if (!iterfunc)
I_Error("Z_IterateTags: no iterator function was given"); I_Error("Z_IterateTags: no iterator function was given");