forked from mirrors/0ad
remove sys_alloca (difficult to wrap in a sysdep function) and eliminate the need for it
debug: when building error message, use mmap instead of alloca scheduler: remove reference to deleted header This was SVN commit r5019.
This commit is contained in:
+9
-41
@@ -26,11 +26,12 @@
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/posix/posix_pthread.h"
|
||||
#include "lib.h"
|
||||
#include "app_hooks.h"
|
||||
#include "path_util.h"
|
||||
#include "debug_stl.h"
|
||||
#include "allocators.h"
|
||||
#include "lib/posix/posix_pthread.h"
|
||||
#include "lib/sysdep/cpu.h" // CAS
|
||||
#include "lib/sysdep/sysdep.h"
|
||||
#include "lib/res/file/file.h" // FILE_ACCESS
|
||||
@@ -504,45 +505,12 @@ static bool should_suppress_error(u8* suppress)
|
||||
return false;
|
||||
}
|
||||
|
||||
static wchar_t* alloc_mem(void* alloca_buf, size_t alloca_buf_size,
|
||||
void*& heap_mem, size_t& max_chars)
|
||||
{
|
||||
void* chosen_buf;
|
||||
size_t chosen_size;
|
||||
|
||||
// rationale:
|
||||
// - this needs to be quite large, so preallocating is undesirable.
|
||||
// - prefer malloc to alloca because it allows returning larger
|
||||
// buffers (stack space may be quite limited).
|
||||
// - do not rely on malloc because we might be called upon to report
|
||||
// heap corruption errors. therefore, the caller should allocate some
|
||||
// scratch memory via alloca, which is used as an (optional) backup.
|
||||
// - note: we can't alloca here because it'd be lost after
|
||||
// function return, but must be passed on to debug_display_error.
|
||||
|
||||
// try allocating from heap.
|
||||
chosen_size = 500*KiB; // 'enough'
|
||||
chosen_buf = heap_mem = malloc(chosen_size);
|
||||
// .. failed; use alloca_buf.
|
||||
if(!chosen_buf)
|
||||
{
|
||||
// caller didn't set it up => we have no memory to return; abort.
|
||||
if(!alloca_buf)
|
||||
return 0;
|
||||
|
||||
chosen_buf = alloca_buf;
|
||||
chosen_size = alloca_buf_size;
|
||||
}
|
||||
|
||||
max_chars = chosen_size / sizeof(wchar_t);
|
||||
return (wchar_t*)chosen_buf;
|
||||
}
|
||||
|
||||
static const size_t message_size_bytes = 256*KiB; // enough
|
||||
|
||||
void debug_error_message_free(ErrorMessageMem* emm)
|
||||
{
|
||||
// note: no-op if wasn't allocated from heap.
|
||||
free(emm->heap_mem);
|
||||
page_aligned_free(emm->pa_mem, message_size_bytes);
|
||||
}
|
||||
|
||||
// split out of debug_display_error because it's used by the self-test.
|
||||
@@ -552,10 +520,12 @@ const wchar_t* debug_error_message_build(
|
||||
uint skip, void* context,
|
||||
ErrorMessageMem* emm)
|
||||
{
|
||||
size_t max_chars;
|
||||
wchar_t* buf = alloc_mem(emm->alloca_buf, emm->alloca_buf_size, emm->heap_mem, max_chars);
|
||||
if(!buf)
|
||||
// rationale: see ErrorMessageMem
|
||||
emm->pa_mem = page_aligned_alloc(message_size_bytes);
|
||||
if(!emm->pa_mem)
|
||||
return L"(insufficient memory to generate error message)";
|
||||
wchar_t* const buf = (wchar_t*)emm->pa_mem;
|
||||
const size_t max_chars = size_bytes / sizeof(wchar_t);
|
||||
wchar_t* pos = buf; size_t chars_left = max_chars; int len;
|
||||
|
||||
// header
|
||||
@@ -700,8 +670,6 @@ ErrorReaction debug_display_error(const wchar_t* description,
|
||||
|
||||
|
||||
ErrorMessageMem emm;
|
||||
emm.alloca_buf_size = 50000;
|
||||
emm.alloca_buf = sys_alloca(emm.alloca_buf_size);
|
||||
const wchar_t* text = debug_error_message_build(description,
|
||||
fn_only, line, func, skip, context, &emm);
|
||||
|
||||
|
||||
+10
-6
@@ -650,12 +650,16 @@ extern const char* debug_get_thread_name();
|
||||
**/
|
||||
struct ErrorMessageMem
|
||||
{
|
||||
// passed to debug_error_message_build from caller
|
||||
void* alloca_buf;
|
||||
size_t alloca_buf_size;
|
||||
|
||||
// allocated within debug_error_message_build
|
||||
void* heap_mem;
|
||||
// rationale:
|
||||
// - error messages with stack traces require a good deal of memory
|
||||
// (dozens of KB). static buffers of that size are undesirable.
|
||||
// - the heap may be corrupted, so don't use malloc. allocator.h's
|
||||
// page_aligned_malloc (implemented via mmap) should be safe.
|
||||
// - alloca is a bit iffy (the stack may be maxed out), non-portable and
|
||||
// complicates the code because it can't be allocated by a subroutine.
|
||||
// - this method is probably slow, but error messages aren't built often.
|
||||
// if necessary, first try malloc and use mmap if that fails.
|
||||
void* pa_mem;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -284,7 +284,7 @@ static void smr_release_unreferenced_nodes(TLS* tls)
|
||||
retry:
|
||||
const size_t max_hps = (active_threads+3) * NUM_HPS;
|
||||
// allow for creating a few additional threads during the loop
|
||||
void** hps = (void**)sys_alloca(max_hps * sizeof(void*));
|
||||
void** hps = (void**)alloca(max_hps * sizeof(void*));
|
||||
size_t num_hps = 0;
|
||||
// for each participating thread:
|
||||
for(TLS* t = tls_list; t; t = t->next)
|
||||
@@ -561,7 +561,7 @@ retry:
|
||||
// or 0 if not found in the list.
|
||||
void* lfl_find(LFList* list, uintptr_t key)
|
||||
{
|
||||
ListPos* pos = (ListPos*)sys_alloca(sizeof(ListPos));
|
||||
ListPos* pos = (ListPos*)alloca(sizeof(ListPos));
|
||||
if(!list_lookup(list, key, pos))
|
||||
return 0;
|
||||
return node_user_data(pos->cur);
|
||||
@@ -579,7 +579,7 @@ void* lfl_insert(LFList* list, uintptr_t key, size_t additional_bytes, int* was_
|
||||
// if this triggers, tls_alloc called from lfl_init failed due to
|
||||
// lack of memory and the caller didn't check its return value.
|
||||
|
||||
ListPos* pos = (ListPos*)sys_alloca(sizeof(ListPos));
|
||||
ListPos* pos = (ListPos*)alloca(sizeof(ListPos));
|
||||
|
||||
Node* node = 0;
|
||||
if(was_inserted)
|
||||
@@ -632,7 +632,7 @@ LibError lfl_erase(LFList* list, uintptr_t key)
|
||||
// if this triggers, tls_alloc called from lfl_init failed due to
|
||||
// lack of memory and the caller didn't check its return value.
|
||||
|
||||
ListPos* pos = (ListPos*)sys_alloca(sizeof(ListPos));
|
||||
ListPos* pos = (ListPos*)alloca(sizeof(ListPos));
|
||||
|
||||
retry:
|
||||
// not found in list - abort.
|
||||
|
||||
@@ -106,11 +106,6 @@ extern LibError sys_cursor_free(void* cursor);
|
||||
extern int sys_vsnprintf(char* buffer, size_t count, const char* format, va_list argptr);
|
||||
|
||||
|
||||
/**
|
||||
* allocate on stack, automatically free when current function returns.
|
||||
**/
|
||||
extern void* sys_alloca(size_t size);
|
||||
|
||||
// describe the current OS error state.
|
||||
//
|
||||
// err: if not 0, use that as the error code to translate; otherwise,
|
||||
|
||||
@@ -46,24 +46,6 @@ void sys_display_msgw(const wchar_t* caption, const wchar_t* msg)
|
||||
}
|
||||
|
||||
|
||||
void* sys_alloca(size_t size)
|
||||
{
|
||||
void* ret;
|
||||
__try
|
||||
{
|
||||
ret = _alloca(size);
|
||||
}
|
||||
// if stack overflow, handle it; otherwise, continue handler search.
|
||||
__except(GetExceptionCode() == STATUS_STACK_OVERFLOW)
|
||||
{
|
||||
// restore guard page - necessary on XP, works everywhere.
|
||||
_resetstkoflw();
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// "program error" dialog (triggered by debug_assert and exception)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include <list>
|
||||
#include <set>
|
||||
|
||||
#include "EntityMessage.h"
|
||||
#include "EntityHandles.h"
|
||||
#include "ps/Singleton.h"
|
||||
#include "ps/CStr.h"
|
||||
|
||||
Reference in New Issue
Block a user