Multithread the exec command #115

Closed
alufolie91 wants to merge 3 commits from multithreadshit into Saturn-Next
pull from: multithreadshit
16 changed files with 634 additions and 65 deletions

No files matched your search

+1
View File
@@ -462,6 +462,7 @@ DBGNAME?=$(EXENAME).debug
OBJS:=$(i_main_o) \
$(OBJDIR)/comptime.o \
$(OBJDIR)/string.o \
$(OBJDIR)/d_async.o \
$(OBJDIR)/d_main.o \
$(OBJDIR)/d_protocol.o \
$(OBJDIR)/d_clisrv.o \
+79 -28
View File
@@ -18,6 +18,7 @@
#include "doomdef.h"
#include "doomstat.h"
#include "d_main.h"
#include "command.h"
#include "console.h"
#include "z_zone.h"
@@ -34,6 +35,8 @@
#include "p_setup.h"
#include "lua_script.h"
#include "d_netfil.h" // findfile
#include "d_async.h"
#include "filesrch.h"
//========
// protos.
@@ -121,11 +124,9 @@ void COM_BufAddText(const char *ptext)
l = strlen(ptext);
if (com_text.cursize + l >= com_text.maxsize)
{
CONS_Alert(CONS_WARNING, M_GetText("Command buffer full!\n"));
return;
}
VS_Write(&com_text, ptext, l);
else
VS_Write(&com_text, ptext, l);
}
/** Adds command text and executes it immediately.
@@ -752,12 +753,60 @@ static void COM_CEchoDuration_f(void)
HU_SetCEchoDuration(atoi(COM_Argv(1)));
}
struct COM_Exec_Ctx
{
boolean noerror;
boolean silent;
UINT8 * buf;
};
static void Free_COM_Exec_Ctx (struct COM_Exec_Ctx *ctx)
{
Z_Free(ctx->buf);
Z_Free(ctx);
}
void COM_ExecuteFile (void *p, void *u)
{
filequery_t * q = p;
struct COM_Exec_Ctx * ctx = u;
ctx->buf = NULL;
if (q->status == FS_FOUND)
{
FIL_ReadFile(q->filename, &ctx->buf);
}
if (ctx->buf)
{
if (! ctx->silent)
CONS_Printf(M_GetText("executing %s\n"), q->filename);
// insert text file into the command buffer
COM_BufAddText((char *)ctx->buf);
COM_BufAddText("\n");
}
else
{
if (! ctx->noerror)
CONS_Printf(M_GetText("couldn't execute file %s\n"), q->filename);
}
Free_COM_Exec_Ctx(ctx);
}
/** Executes a script file.
*/
static void COM_Exec_f(void)
{
UINT8 *buf = NULL;
char filename[256];
char filenamebuf[MAX_WADPATH];
struct COM_Exec_Ctx *ctx;
const char * filename;
filequery_t q;
if (COM_Argc() < 2 || COM_Argc() > 3)
{
@@ -765,37 +814,39 @@ static void COM_Exec_f(void)
return;
}
// load file
// Try with Argv passed verbatim first, for back compat
FIL_ReadFile(COM_Argv(1), &buf);
filename = COM_Argv(1);
if (!buf)
ctx = ZZ_Alloc(sizeof *ctx);
ctx->noerror = COM_CheckParm("-noerror");
ctx->silent = COM_CheckParm("-silent");
if (COM_CheckParm("-sync"))
{
// Now try by searching the file path
// filename is modified with the full found path
strcpy(filename, COM_Argv(1));
if (findfile(filename, NULL, true) != FS_NOTFOUND)
FIL_ReadFile(filename, &buf);
q.filename = filenamebuf;
if (!buf)
strcpy(q.filename, filename);
if (FIL_FileOK(filename))
{
if (!COM_CheckParm("-noerror"))
CONS_Printf(M_GetText("couldn't execute file %s\n"), COM_Argv(1));
return;
q.status = FS_FOUND;
}
else
{
q.status = findfile(q.filename, NULL, true);
}
COM_ExecuteFile(&q, ctx);
}
else
{
q.filename = strcpy(ZZ_Alloc(MAX_WADPATH), filename);
Append_async_addfile(ASYNC_EXEC, q.filename, ctx);
}
if (!COM_CheckParm("-silent"))
CONS_Printf(M_GetText("executing %s\n"), COM_Argv(1));
// insert text file into the command buffer
COM_BufAddText((char *)buf);
COM_BufAddText("\n");
// free buffer
Z_Free(buf);
}
/** Delays execution of the rest of the commands until the next frame.
* Allows sequences of commands like "jump; fire; backward".
*/
+3
View File
@@ -59,6 +59,9 @@ void COM_ImmedExecute(const char *ptext);
// Execute commands in buffer, flush them
void COM_BufExecute(void);
// Execute a whole file (internal use only :v)
void COM_ExecuteFile(void *query, void *ctx);
// As above; and progress the wait timer.
void COM_BufTicker(void);
+8
View File
@@ -1414,6 +1414,14 @@ void CONS_Printf(const char *fmt, ...)
startup = con_startup;
Unlock_state();
#ifdef HAVE_THREADS
if (! I_on_main_thread())
{
return;
}
#endif
// if not in display loop, force screen update
if (startup)
+259
View File
@@ -0,0 +1,259 @@
// 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 d_async.c
/// \brief Add wad/exec config asynchronously to the main thread, but in order
#include "doomdef.h"
#include "d_main.h"
#include "d_async.h"
#include "filesrch.h"
#include "i_threads.h"
#include "m_misc.h"
#include "p_setup.h"
#include "z_zone.h"
struct filename_queue;
struct async_addfile;
typedef struct filename_queue filename_queue_t;
typedef struct async_addfile async_addfile_t;
struct filename_queue
{
int type;
char * name;
void * u;/* exec command has some parameters that need know */
filename_queue_t * next;
};
struct async_addfile
{
int done;
int query_size;
int query_position;
filequery_t * query;
int * type;
void ** u;
async_addfile_t * next;
};
static filename_queue_t * queue_head;
static filename_queue_t * queue_tail;
static int queue_size;
static I_mutex async_mutex;
static async_addfile_t * async_head;
static async_addfile_t * async_tail;
static void
Async_addfile_thread (async_addfile_t *file)
{
findmultiplefiles(file->query_size, file->query, false, true, &async_mutex);
I_lock_mutex(&async_mutex);
{
file->done = 1;
}
I_unlock_mutex(async_mutex);
}
static void
Do_addfile (int type, filequery_t *q, void *ctx)
{
switch (type)
{
case ASYNC_EXEC:
COM_ExecuteFile(q, ctx);
break;
}
}
void
Finish_async_addfile (void)
{
async_addfile_t * file = async_head;
async_addfile_t * next;
filequery_t * q;
filestatus_t status;
int type;
int done;
while (file != NULL)
{
while (file->query_position < file->query_size)
{
q = &file->query [file->query_position];
type = file->type [file->query_position];
I_lock_mutex(&async_mutex);
{
status = q->status;
}
I_unlock_mutex(async_mutex);
if (status == FS_NOTCHECKED)
{
break;
}
else
{
Do_addfile(type, q, file->u[file->query_position]);
}
Z_Free(q->filename);
file->query_position++;
}
if (file->query_position < file->query_size)
{
break;
}
I_lock_mutex(&async_mutex);
{
done = file->done;
}
I_unlock_mutex(async_mutex);
if (done)
{
next = file->next;
Z_Free(file->u);
Z_Free(file->type);
Z_Free(file->query);
Z_Free(file);
file = next;
}
else
{
break;
}
}
async_head = file;
if (file == NULL)
{
async_tail = NULL;
}
}
void
Append_async_addfile (int type, const char * filename, void * userdata)
{
char filenamebuf[MAX_WADPATH];
filename_queue_t * q;
filequery_t file;
if (FIL_FileOK(filename))
{
file.status = FS_FOUND;
file.filename = filenamebuf;
strcpy(file.filename, filename);
Do_addfile(type, &file, userdata);
}
else
{
q = ZZ_Alloc(sizeof *q);
if (queue_tail != NULL)
{
queue_tail->next = q;
}
else
{
queue_head = q;
}
queue_tail = q;
queue_size++;
q->type = type;
q->name = strcpy(ZZ_Alloc(MAX_WADPATH), filename);
q->u = userdata;
q->next = NULL;
}
}
void
Detach_async_addfile (void)
{
filename_queue_t * q = queue_head;
filename_queue_t * next;
async_addfile_t * file;
filequery_t * query;
int * type;
void ** udata;
if (q != NULL)
{
file = ZZ_Alloc(sizeof *file);
if (async_tail != NULL)
{
async_tail->next = file;
}
else
{
async_head = file;
}
async_tail = file;
file->done = 0;
file->next = NULL;
file->query_size = queue_size;
file->query_position = 0;
file->query = ZZ_Alloc(queue_size * sizeof (*file->query));
file->type = ZZ_Alloc(queue_size * sizeof (*file->type));
file->u = ZZ_Alloc(queue_size * sizeof (*file->u));
query = file->query;
type = file->type;
udata = file->u;
do
{
*type++ = q->type;
*udata++ = q->u;
query->status = FS_NOTCHECKED;
query->wantedmd5sum = NULL;
query->filename = q->name;
query++;
next = q->next;
Z_Free(q);
}
while (( q = next ) != NULL) ;
I_spawn_thread("async-addfile",
(I_thread_fn)Async_addfile_thread, file);
queue_head = NULL;
queue_tail = NULL;
queue_size = 0;
}
}
+44
View File
@@ -0,0 +1,44 @@
// 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 d_async.h
/// \brief Add wad/exec config asynchronously to the main thread, but in order
#ifndef D_ASYNC_H
#define D_ASYNC_H
enum
{
ASYNC_ADDFILE,
ASYNC_EXEC,
};
/*
Queue a file to be added. Detach_async_addfile will spawn a thread that
searches for any files if necessary.
*/
void Append_async_addfile (int type, const char * filename, void * ctx);
/*
Although the file searching is done on another thread, the actual adding of the
wad or executing the config must be done on the main thread. This function is
called every tic to check if a file was found so it can perform that last step.
It does this in order.
*/
void Finish_async_addfile (void);
/*
Spawns a thread that searches for files that were queued.
Called at the end of each tic.
*/
void Detach_async_addfile (void);
#endif/*D_ASYNC_H*/
+5
View File
@@ -45,6 +45,7 @@
#include "lua_script.h"
#include "lua_hook.h"
#include "k_kart.h"
#include "d_async.h"
#include "s_sound.h" // sfx_syfail
#include "m_perfstats.h"
#include "d_main.h"
@@ -6041,6 +6042,8 @@ boolean TryRunTics(tic_t realtics)
if (singletics)
realtics = 1;
Finish_async_addfile();
if (realtics >= 1)
{
@@ -6118,6 +6121,8 @@ boolean TryRunTics(tic_t realtics)
{
hu_stopped = true;
}
Detach_async_addfile();
return ticking;
}
+10 -4
View File
@@ -1164,13 +1164,13 @@ filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum)
// Rewritten by Monster Iestyn to be less stupid
// Note: if completepath is true, "filename" is modified, but only if FS_FOUND is going to be returned
// (Don't worry about WinCE's version of filesearch, nobody cares about that OS anymore)
filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean completepath)
filestatus_t findmultiplefiles(int n, filequery_t *files, boolean checkmd5, boolean completepath, void *mutex_ptr)
{
filestatus_t homecheck; // store result of last file search
boolean badmd5 = false; // store whether md5 was bad from either of the first two searches (if nothing was found in the third)
// first, check SRB2's "home" directory
homecheck = filesearch(filename, srb2home, wantedmd5sum, completepath, 10);
homecheck = filesearch(n, files, srb2home, checkmd5, completepath, 10, mutex_ptr);
if (homecheck == FS_FOUND) // we found the file, so return that we have :)
return FS_FOUND;
@@ -1179,7 +1179,7 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet
// if not found at all, just move on without doing anything
// next, check SRB2's "path" directory
homecheck = filesearch(filename, srb2path, wantedmd5sum, completepath, 10);
homecheck = filesearch(n, files, srb2path, checkmd5, completepath, 10, mutex_ptr);
if (homecheck == FS_FOUND) // we found the file, so return that we have :)
return FS_FOUND;
@@ -1188,7 +1188,7 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet
// if not found at all, just move on without doing anything
// finally check "." directory
homecheck = filesearch(filename, ".", wantedmd5sum, completepath, 10);
homecheck = filesearch(n, files, ".", checkmd5, completepath, 10, mutex_ptr);
if (homecheck != FS_NOTFOUND) // if not found this time, fall back on the below return statement
return homecheck; // otherwise return the result we got
@@ -1196,6 +1196,12 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet
return (badmd5 ? FS_MD5SUMBAD : FS_NOTFOUND); // md5 sum bad or file not found
}
filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean completepath)
{
filequery_t q = { FS_NOTFOUND, wantedmd5sum, filename };
return findmultiplefiles(1, &q, ( wantedmd5sum != NULL ), completepath, NULL);
}
#ifdef HAVE_CURL
size_t curlwrite_data(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
+90 -22
View File
@@ -29,6 +29,7 @@
#include "m_misc.h"
#include "z_zone.h"
#include "m_menu.h" // Addons_option_Onchange
#include "i_threads.h"
#if defined (_WIN32) && defined (_MSC_VER)
@@ -354,17 +355,44 @@ INT32 pathisdirectory(const char *path)
return 0;
}
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth)
filestatus_t filesearch(int nfiles, filequery_t *files, const char *startpath, boolean checkmd5, boolean completepath, int maxsearchdepth, void *mutex_ptr)
{
filestatus_t retval = FS_NOTFOUND;
const UINT8 *wantedmd5sum = NULL;
DIR **dirhandle;
struct dirent *dent;
struct stat fsstat;
int found = 0;
char *searchname = strdup(filename);
int depthleft = maxsearchdepth;
char searchpath[1024];
size_t *searchpathindex;
int matched;
int files_left = 0;
int i;
#ifdef HAVE_THREADS
#define Lock() I_lock_mutex ((I_mutex *)mutex_ptr)
#define Unlock() I_unlock_mutex (((mutex_ptr) ? *(I_mutex *)mutex_ptr : NULL))
#else
#define Lock() ((void)0)
#define Unlock() ((void)0)
#endif
Lock();
for (i = 0; i < nfiles; ++i)
{
if (files[i].status != FS_FOUND)
{
files_left++;
}
}
Unlock();
if (! files_left)
{
return FS_FOUND;
}
dirhandle = (DIR**) malloc(maxsearchdepth * sizeof (DIR*));
searchpathindex = (size_t *) malloc(maxsearchdepth * sizeof (size_t));
@@ -376,7 +404,6 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
if (dirhandle[depthleft] == NULL)
{
free(searchname);
free(dirhandle);
free(searchpathindex);
return FS_NOTFOUND;
@@ -390,7 +417,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
else
searchpathindex[depthleft]--;
while ((!found) && (depthleft < maxsearchdepth))
while ((files_left) && (depthleft < maxsearchdepth))
{
searchpath[searchpathindex[depthleft]]=0;
dent = readdir(dirhandle[depthleft]);
@@ -448,34 +475,75 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
searchpath[searchpathindex[depthleft]-1]='/';
searchpath[searchpathindex[depthleft]]=0;
}
else if (!strcasecmp(searchname, dent->d_name))
else
{
switch (checkfilemd5(searchpath, wantedmd5sum))
for (i = 0; i < nfiles; ++i)
{
case FS_FOUND:
if (completepath)
strcpy(filename,searchpath);
else
strcpy(filename,dent->d_name);
retval = FS_FOUND;
found = 1;
break;
case FS_MD5SUMBAD:
retval = FS_MD5SUMBAD;
break;
default: // prevent some compiler warnings
break;
Lock();
if (checkmd5)
{
wantedmd5sum = files[i].wantedmd5sum;
}
matched = (
files[i].status != FS_FOUND &&
!strcasecmp(files[i].filename, dent->d_name)
);
Unlock();
if (matched)
{
switch (checkfilemd5(searchpath, wantedmd5sum))
{
case FS_FOUND:
Lock();
if (completepath)
strcpy(files[i].filename,searchpath);
else
strcpy(files[i].filename,dent->d_name);
files[i].status = FS_FOUND;
Unlock();
files_left--;
break;
case FS_MD5SUMBAD:
Lock();
retval = files[i].status = FS_MD5SUMBAD;
Unlock();
break;
default: // prevent some compiler warnings
break;
}
}
}
}
}
for (; depthleft < maxsearchdepth; closedir(dirhandle[depthleft++]));
free(searchname);
free(searchpathindex);
free(dirhandle);
return retval;
Lock();
{
for (i = 0; i < nfiles; ++i)
{
if (files[i].status != FS_FOUND && files[i].status != FS_MD5SUMBAD)
{
files[i].status = FS_NOTFOUND;
}
}
}
Unlock();
return ( (files_left) ? retval : FS_FOUND );
#undef Lock
#undef Unlock
}
char exttable[NUM_EXT_TABLE][7] = { // maximum extension length (currently 4) plus 3 (null terminator, stop, and length including previous two)
+18 -5
View File
@@ -8,25 +8,38 @@
#include "d_netfil.h"
#include "m_menu.h" // MAXSTRINGLENGTH
typedef struct
{
filestatus_t status;
const UINT8 * wantedmd5sum;
char * filename;
}
filequery_t;
extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_showall, cv_addons_search_case, cv_addons_search_type;
/** \brief The filesearch function
This function search files, manly WADs and return back the status of the file
\param filename the file to look for
\param nfiles number of files
\param queries the files to look for
\param startpath where to start look from
\param wantedmd5sum want to check with MD5
\param completepath want to return the complete path of the file?
\param maxsearchdepth the max depth to search for the file
\return filestatus_t
\return FS_FOUND if all files were found, FS_NOTFOUND or FS_MD5SUMBAD
if some files were not found
*/
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
boolean completepath, int maxsearchdepth);
filestatus_t filesearch(int nfiles, filequery_t *queries, const char *startpath,
boolean checkmd5, boolean completepath, int maxsearchdepth, void *mutex_ptr);
/* this is a better place for it tbh (im still too lazy to move the other) */
filestatus_t findmultiplefiles(int nfiles, filequery_t *files,
boolean checkmd5, boolean completepath, void *mutex_ptr);
#define menudepth 20
+2
View File
@@ -27,6 +27,8 @@ void I_spawn_thread (const char *name, I_thread_fn, void *userdata);
/* check in your thread whether to return early */
int I_thread_is_stopped (void);
int I_on_main_thread (void);
void I_lock_mutex (I_mutex *);
void I_unlock_mutex (I_mutex);
+1 -1
View File
@@ -504,7 +504,7 @@ void M_FirstLoadConfig(void)
CV_InitFilterVar();
// load config, make sure those commands doesnt require the screen...
COM_BufInsertText(va("exec \"%s\"\n", configfile));
COM_BufInsertText(va("exec \"%s\" -sync\n", configfile));
// no COM_BufExecute() needed; that does it right away
// don't filter anymore vars and don't let this convsvar be changed
+6 -2
View File
@@ -3871,10 +3871,14 @@ static void pathonly(char *s)
static const char *searchWad(const char *searchDir)
{
static char tempsw[256] = "";
filequery_t fsquery;
filestatus_t fstemp;
fsquery.filename = tempsw;
strcpy(tempsw, WADKEYWORD1);
fstemp = filesearch(tempsw,searchDir,NULL,true,20);
fsquery.status = FS_NOTFOUND;
fstemp = filesearch(1,&fsquery,searchDir,false,true,20,NULL);
if (fstemp == FS_FOUND)
{
pathonly(tempsw);
@@ -3882,7 +3886,7 @@ static const char *searchWad(const char *searchDir)
}
strcpy(tempsw, WADKEYWORD2);
fstemp = filesearch(tempsw, searchDir, NULL, true, 20);
fstemp = filesearch(1, &fsquery, searchDir, false, true, 20, NULL);
if (fstemp == FS_FOUND)
{
pathonly(tempsw);
+40
View File
@@ -47,6 +47,8 @@ static I_mutex i_cond_pool_mutex;
static SDL_atomic_t i_threads_running = {1};
static SDL_threadID i_main_thread_id;
static Link
Insert_link (
Link * head,
@@ -197,6 +199,12 @@ I_thread_is_stopped (void)
return ( ! SDL_AtomicGet(&i_threads_running) );
}
int
I_on_main_thread (void)
{
return ( SDL_ThreadID() == i_main_thread_id );
}
void
I_start_threads (void)
{
@@ -211,6 +219,8 @@ I_start_threads (void)
)){
abort();
}
i_main_thread_id = SDL_ThreadID();
}
void
@@ -283,6 +293,12 @@ I_lock_mutex (
I_mutex * anchor
){
SDL_mutex * mutex;
if (! i_threads_running.value)
return;
if (anchor == NULL)
return;
mutex = Identity(
&i_mutex_pool,
@@ -299,6 +315,12 @@ void
I_unlock_mutex (
I_mutex id
){
if (! i_threads_running.value)
return;
if (id == NULL)
return;
if (SDL_UnlockMutex(id) == -1)
abort();
}
@@ -309,6 +331,12 @@ I_hold_cond (
I_mutex mutex_id
){
SDL_cond * cond;
if (! i_threads_running.value)
return;
if (cond_anchor == NULL || mutex_id == NULL)
return;
cond = Identity(
&i_cond_pool,
@@ -326,6 +354,12 @@ I_wake_one_cond (
I_cond * anchor
){
SDL_cond * cond;
if (! i_threads_running.value)
return;
if (anchor == NULL)
return;
cond = Identity(
&i_cond_pool,
@@ -343,6 +377,12 @@ I_wake_all_cond (
I_cond * anchor
){
SDL_cond * cond;
if (! i_threads_running.value)
return;
if (anchor == NULL)
return;
cond = Identity(
&i_cond_pool,
+31 -2
View File
@@ -904,17 +904,46 @@ void W_UnloadWadFile(UINT16 num)
*/
INT32 W_InitMultipleFiles(char **filenames, boolean addons)
{
char filenamebufs[MAX_WADFILES][MAX_WADPATH];
filequery_t q[MAX_WADFILES];
int n = 0;
int i;
INT32 rc = 1;
INT32 overallrc = 1;
// will be realloced as lumps are added
for (; *filenames; filenames++)
{
if (addons && !W_VerifyNMUSlumps(*filenames))
if (FIL_FileOK(*filenames))
{
q[n].status = FS_FOUND;
q[n].filename = *filenames;
}
else
{
strcpy(filenamebufs[n], *filenames);
q[n].filename = filenamebufs[n];
}
n++;
}
findmultiplefiles(n, q, false, true, NULL);
for (i = 0; i < n; ++i)
{
if (q[i].status != FS_FOUND)
{
CONS_Alert(CONS_ERROR, M_GetText("File %s not found.\n"), q[i].filename);
continue;
}
if (addons && !W_VerifyNMUSlumps(q[i].filename))
G_SetGameModified(true, false);
//CONS_Debug(DBG_SETUP, "Loading %s\n", *filenames);
rc = W_InitFile(*filenames, 0, 0, false);
rc = W_InitFile(q[i].filename, 0, 0, false);
if (rc == INT16_MAX)
CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), *filenames);
overallrc &= (rc != INT16_MAX) ? 1 : 0;
+37 -1
View File
@@ -29,6 +29,7 @@
#include "doomstat.h"
#include "r_patch.h"
#include "i_system.h" // I_GetFreeMem
#include "i_threads.h"
#include "i_video.h" // rendermode
#include "z_zone.h"
#include "m_misc.h" // M_Memcpy
@@ -50,6 +51,16 @@ static boolean Z_calloc = false;
//#define ZDEBUG2
#endif
#ifdef HAVE_THREADS
static I_mutex z_mutex;
# define Lock_state() I_lock_mutex(&z_mutex)
# define Unlock_state() I_unlock_mutex(z_mutex)
#else/*HAVE_THREADS*/
# define Lock_state()
# define Unlock_state()
#endif/*HAVE_THREADS*/
typedef struct memblock_s
{
void **user;
@@ -135,6 +146,8 @@ void Z_Free(void *ptr)
CONS_Debug(DBG_MEMORY, "Z_Free %s:%d\n", file, line);
#endif
Lock_state();
block = MEMBLOCK(ptr);
#ifdef PARANOIA
if (block->id != ZONEID)
@@ -167,6 +180,8 @@ void Z_Free(void *ptr)
block->prev->next = block->next;
block->next->prev = block->prev;
free(block);
Unlock_state();
}
/** malloc() that doesn't accept failure.
@@ -233,6 +248,8 @@ void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits)
Z_calloc = false;
#endif
Lock_state();
block->next = head.next;
block->prev = &head;
head.next = block;
@@ -258,7 +275,10 @@ void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits)
block->user = user;
*(void **)user = ptr;
}
else if (tag >= PU_PURGELEVEL)
Unlock_state();
if (tag >= PU_PURGELEVEL)
I_Error("Z_Malloc: attempted to allocate purgable block "
"(size %s) with no user", sizeu1(size));
@@ -392,6 +412,8 @@ void *Z_ReallocAlign(void *ptr, size_t size, INT32 tag, void *user, INT32 alignb
void Z_FreeTags(INT32 lowtag, INT32 hightag)
{
memblock_t *block, *next;
Lock_state();
Z_CheckHeap(420);
for (block = head.next; block != &head; block = next)
@@ -400,6 +422,8 @@ void Z_FreeTags(INT32 lowtag, INT32 hightag)
if (block->tag >= lowtag && block->tag <= hightag)
Z_Free(MEMORY(block));
}
Unlock_state();
}
/** Iterates through all memory for a given set of tags.
@@ -627,6 +651,8 @@ size_t Z_TagsUsage(INT32 lowtag, INT32 hightag)
{
size_t cnt = 0;
memblock_t *rover;
Lock_state();
for (rover = head.next; rover != &head; rover = rover->next)
{
@@ -634,6 +660,8 @@ size_t Z_TagsUsage(INT32 lowtag, INT32 hightag)
continue;
cnt += rover->size + sizeof *rover;
}
Unlock_state();
return cnt;
}
@@ -648,6 +676,8 @@ size_t Z_TagsUsage(INT32 lowtag, INT32 hightag)
static void Command_Memfree_f(void)
{
size_t freebytes, totalbytes;
Lock_state();
Z_CheckHeap(-1);
CONS_Printf("\x82%s", M_GetText("Memory Info\n"));
@@ -677,6 +707,8 @@ static void Command_Memfree_f(void)
freebytes = I_GetFreeMem(&totalbytes);
CONS_Printf(M_GetText(" Total physical memory: %s KB\n"), sizeu1(totalbytes>>10));
CONS_Printf(M_GetText("Available physical memory: %s KB\n"), sizeu1(freebytes>>10));
Unlock_state();
}
@@ -698,6 +730,8 @@ static void Command_Memdump_f(void)
if ((i = COM_CheckParm("-max")))
maxtag = atoi(COM_Argv(i + 1));
Lock_state();
for (block = head.next; block != &head; block = block->next)
if (block->tag >= mintag && block->tag <= maxtag)
@@ -705,6 +739,8 @@ static void Command_Memdump_f(void)
char *filename = strrchr(block->ownerfile, PATHSEP[0]);
CONS_Printf("[%3d] %s (%s) bytes @ %s:%d\n", block->tag, sizeu1(block->size), sizeu2(block->realsize), filename ? filename + 1 : block->ownerfile, block->ownerline);
}
Unlock_state();
}
#endif