Replaced the temporary storage used in the kernel debug command parser. We now
have a simple dedicated heap for the kernel debugger with stacked allocation pools (deleting a pool frees all memory allocated in it). The heap should eventually be used for all commands that need temporary storage too large for the stack instead of each using its own static buffer. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30949 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
5734ece852
commit
360d4974b9
@ -18,6 +18,9 @@
|
||||
// benaphore-style.
|
||||
#define KDEBUG KDEBUG_LEVEL_2
|
||||
|
||||
// Size of the heap used by the kernel debugger.
|
||||
#define KDEBUG_HEAP (64 * 1024)
|
||||
|
||||
// Set to 0 to disable support for kernel breakpoints.
|
||||
#define KERNEL_BREAKPOINTS 1
|
||||
|
||||
|
71
headers/private/kernel/debug_heap.h
Normal file
71
headers/private/kernel/debug_heap.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _KERNEL_DEBUG_HEAP_H
|
||||
#define _KERNEL_DEBUG_HEAP_H
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
struct DebugAllocPool;
|
||||
typedef struct DebugAllocPool debug_alloc_pool;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
debug_alloc_pool* create_debug_alloc_pool();
|
||||
void delete_debug_alloc_pool(debug_alloc_pool* pool);
|
||||
void* debug_malloc(size_t size);
|
||||
void debug_free(void* address);
|
||||
void debug_heap_init();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
struct kdebug_alloc_t {};
|
||||
extern const kdebug_alloc_t kdebug_alloc;
|
||||
|
||||
inline void*
|
||||
operator new(size_t size, const kdebug_alloc_t&) throw()
|
||||
{
|
||||
return debug_malloc(size);
|
||||
}
|
||||
|
||||
namespace DebugAlloc {
|
||||
template<typename Type>
|
||||
inline void
|
||||
destroy(Type* object)
|
||||
{
|
||||
if (object != NULL) {
|
||||
object->~Type();
|
||||
debug_free(object);
|
||||
// NOTE: Doesn't work for multiple inheritence!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct DebugAllocPoolScope {
|
||||
DebugAllocPoolScope()
|
||||
{
|
||||
fPool = create_debug_alloc_pool();
|
||||
}
|
||||
|
||||
~DebugAllocPoolScope()
|
||||
{
|
||||
delete_debug_alloc_pool(fPool);
|
||||
}
|
||||
|
||||
private:
|
||||
DebugAllocPool* fPool;
|
||||
};
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif /* _KERNEL_DEBUG_HEAP_H */
|
@ -10,6 +10,7 @@ KernelMergeObject kernel_debug.o :
|
||||
debug.cpp
|
||||
debug_builtin_commands.cpp
|
||||
debug_commands.cpp
|
||||
debug_heap.cpp
|
||||
debug_paranoia.cpp
|
||||
debug_parser.cpp
|
||||
debug_variables.cpp
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
@ -13,6 +13,7 @@
|
||||
|
||||
#include <cpu.h>
|
||||
#include <debug.h>
|
||||
#include <debug_heap.h>
|
||||
#include <debug_paranoia.h>
|
||||
#include <driver_settings.h>
|
||||
#include <frame_buffer_console.h>
|
||||
@ -665,6 +666,8 @@ kernel_debugger_loop(void)
|
||||
int32 previousCPU = sDebuggerOnCPU;
|
||||
sDebuggerOnCPU = smp_get_current_cpu();
|
||||
|
||||
DebugAllocPool* allocPool = create_debug_alloc_pool();
|
||||
|
||||
kprintf("Welcome to Kernel Debugging Land...\n");
|
||||
|
||||
if (struct thread* thread = thread_get_current_thread()) {
|
||||
@ -721,6 +724,8 @@ kernel_debugger_loop(void)
|
||||
sCurrentLine = 0;
|
||||
}
|
||||
|
||||
delete_debug_alloc_pool(allocPool);
|
||||
|
||||
sDebuggerOnCPU = previousCPU;
|
||||
}
|
||||
|
||||
@ -1210,6 +1215,7 @@ debug_init_post_vm(kernel_args* args)
|
||||
|
||||
debug_builtin_commands_init();
|
||||
|
||||
debug_heap_init();
|
||||
debug_variables_init();
|
||||
frame_buffer_console_init(args);
|
||||
arch_debug_console_init_settings(args);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de
|
||||
* Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de
|
||||
* Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
@ -16,6 +16,7 @@
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <debug.h>
|
||||
#include <debug_heap.h>
|
||||
#include <lock.h>
|
||||
#include <thread.h>
|
||||
#include <util/AutoLock.h>
|
||||
@ -273,6 +274,9 @@ invoke_debugger_command(struct debugger_command *command, int argc, char** argv)
|
||||
// replace argv[0] with the actual command name
|
||||
argv[0] = (char *)command->name;
|
||||
|
||||
DebugAllocPoolScope allocPoolScope;
|
||||
// Will automatically clean up all allocations the command leaves over.
|
||||
|
||||
// Invoking the command directly might be useful when debugging debugger
|
||||
// commands.
|
||||
if (gInvokeCommandDirectly)
|
||||
|
302
src/system/kernel/debug/debug_heap.cpp
Normal file
302
src/system/kernel/debug/debug_heap.cpp
Normal file
@ -0,0 +1,302 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <debug_heap.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <util/AutoLock.h>
|
||||
|
||||
|
||||
#define INITIAL_HEAP_SIZE B_PAGE_SIZE
|
||||
|
||||
static char sInitialHeap[INITIAL_HEAP_SIZE];
|
||||
static void* sHeapBase = sInitialHeap;
|
||||
static size_t sHeapSize = INITIAL_HEAP_SIZE;
|
||||
|
||||
const kdebug_alloc_t kdebug_alloc = {};
|
||||
|
||||
|
||||
struct allocation_header {
|
||||
uint32 size : 31; // size in allocation_header units
|
||||
bool free : 1;
|
||||
uint32 previous;
|
||||
};
|
||||
|
||||
struct free_entry : allocation_header {
|
||||
uint32 previous_free;
|
||||
uint32 next_free;
|
||||
};
|
||||
|
||||
|
||||
struct DebugAllocPool {
|
||||
void Init(void* heap, size_t heapSize)
|
||||
{
|
||||
fParent = NULL;
|
||||
fChild = NULL;
|
||||
|
||||
uint32 size = heapSize / 8;
|
||||
fBase = (allocation_header*)heap - 1;
|
||||
fEnd = size + 1;
|
||||
fFirstFree = 0;
|
||||
fLastFree = 0;
|
||||
|
||||
// add free entry spanning the whole area
|
||||
fBase[1].size = size - 1;
|
||||
fBase[1].previous = 0;
|
||||
_InsertFreeEntry(1);
|
||||
}
|
||||
|
||||
DebugAllocPool* CreateChildPool()
|
||||
{
|
||||
// do we already have a child pool?
|
||||
if (fChild != NULL)
|
||||
return NULL;
|
||||
|
||||
// create the pool object
|
||||
DebugAllocPool* pool
|
||||
= (DebugAllocPool*)Allocate(sizeof(DebugAllocPool));
|
||||
if (pool == NULL)
|
||||
return NULL;
|
||||
|
||||
// do we have enough free space?
|
||||
if (fLastFree == 0 || fBase[fLastFree].size < 2) {
|
||||
Free(pool);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
allocation_header* header = &fBase[fLastFree];
|
||||
_RemoveFreeEntry(fLastFree);
|
||||
|
||||
pool->Init(header + 1, header->size * 8);
|
||||
pool->fParent = this;
|
||||
|
||||
return fChild = pool;
|
||||
}
|
||||
|
||||
void Destroy()
|
||||
{
|
||||
if (fParent != NULL) {
|
||||
fParent->fChild = NULL;
|
||||
fParent->Free(fBase + 1);
|
||||
}
|
||||
}
|
||||
|
||||
DebugAllocPool* Parent() const
|
||||
{
|
||||
return fParent;
|
||||
}
|
||||
|
||||
void* Allocate(size_t size)
|
||||
{
|
||||
size = (size + 7) / 8;
|
||||
uint32 index = fFirstFree;
|
||||
while (index != 0 && fBase[index].size < size)
|
||||
index = ((free_entry*)&fBase[index])->next_free;
|
||||
|
||||
if (index == 0)
|
||||
return NULL;
|
||||
|
||||
_RemoveFreeEntry(index);
|
||||
|
||||
// if the entry is big enough, we split it
|
||||
if (fBase[index].size - size >= 2) {
|
||||
uint32 next = index + 1 + size;
|
||||
uint32 nextNext = index + 1 + fBase[index].size;
|
||||
fBase[next].size = fBase[index].size - size - 1;
|
||||
fBase[next].previous = index;
|
||||
fBase[index].size = size;
|
||||
_InsertFreeEntry(next);
|
||||
|
||||
if (nextNext < fEnd)
|
||||
fBase[nextNext].previous = next;
|
||||
}
|
||||
|
||||
return &fBase[index + 1];
|
||||
}
|
||||
|
||||
void Free(void* address)
|
||||
{
|
||||
// check address
|
||||
if (((addr_t)address & 7) != 0 || address <= fBase + 1
|
||||
|| address >= fBase + fEnd) {
|
||||
kprintf("DebugAllocator::Free(%p): bad address\n", address);
|
||||
return;
|
||||
}
|
||||
|
||||
// get header
|
||||
allocation_header* header = (allocation_header*)address - 1;
|
||||
uint32 index = header - fBase;
|
||||
if (header->free) {
|
||||
kprintf("DebugAllocator::Free(%p): double free\n", address);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 next = index + 1 + header->size;
|
||||
|
||||
// join with previous, if possible
|
||||
if (index > 1 && fBase[header->previous].free) {
|
||||
uint32 previous = header->previous;
|
||||
_RemoveFreeEntry(previous);
|
||||
|
||||
fBase[previous].size += 1 + header->size;
|
||||
fBase[next].previous = previous;
|
||||
|
||||
index = previous;
|
||||
header = fBase + index;
|
||||
}
|
||||
|
||||
// join with next, if possible
|
||||
if (next < fEnd && fBase[next].free) {
|
||||
_RemoveFreeEntry(next);
|
||||
|
||||
header->size += 1 + fBase[next].size;
|
||||
|
||||
uint32 nextNext = index + 1 + header->size;
|
||||
if (nextNext < fEnd)
|
||||
fBase[nextNext].previous = index;
|
||||
}
|
||||
|
||||
_InsertFreeEntry(index);
|
||||
}
|
||||
|
||||
private:
|
||||
void _InsertFreeEntry(uint32 index)
|
||||
{
|
||||
// find the insertion point -- list is sorted by ascending size
|
||||
uint32 size = fBase[index].size;
|
||||
uint32 next = fFirstFree;
|
||||
while (next != 0 && size > fBase[next].size)
|
||||
next = ((free_entry*)&fBase[next])->next_free;
|
||||
|
||||
// insert
|
||||
uint32 previous;
|
||||
if (next != 0) {
|
||||
previous = ((free_entry*)&fBase[next])->previous_free;
|
||||
((free_entry*)&fBase[next])->previous_free = index;
|
||||
} else {
|
||||
previous = fLastFree;
|
||||
fLastFree = index;
|
||||
}
|
||||
|
||||
if (previous != 0)
|
||||
((free_entry*)&fBase[previous])->next_free = index;
|
||||
else
|
||||
fFirstFree = index;
|
||||
|
||||
((free_entry*)&fBase[index])->previous_free = previous;
|
||||
((free_entry*)&fBase[index])->next_free = next;
|
||||
|
||||
fBase[index].free = true;
|
||||
}
|
||||
|
||||
void _RemoveFreeEntry(uint32 index)
|
||||
{
|
||||
uint32 previous = ((free_entry*)&fBase[index])->previous_free;
|
||||
uint32 next = ((free_entry*)&fBase[index])->next_free;
|
||||
|
||||
if (previous != 0)
|
||||
((free_entry*)&fBase[previous])->next_free = next;
|
||||
else
|
||||
fFirstFree = next;
|
||||
|
||||
if (next != 0)
|
||||
((free_entry*)&fBase[next])->previous_free = previous;
|
||||
else
|
||||
fLastFree = previous;
|
||||
|
||||
fBase[index].free = false;
|
||||
}
|
||||
|
||||
private:
|
||||
DebugAllocPool* fParent;
|
||||
DebugAllocPool* fChild;
|
||||
allocation_header* fBase; // actually base - 1, so that index 0 is
|
||||
// invalid
|
||||
uint32 fEnd;
|
||||
uint32 fFirstFree;
|
||||
uint32 fLastFree;
|
||||
};
|
||||
|
||||
|
||||
static DebugAllocPool* sCurrentPool;
|
||||
static DebugAllocPool sInitialPool;
|
||||
|
||||
|
||||
debug_alloc_pool*
|
||||
create_debug_alloc_pool()
|
||||
{
|
||||
if (sCurrentPool == NULL) {
|
||||
sInitialPool.Init(sHeapBase, sHeapSize);
|
||||
sCurrentPool = &sInitialPool;
|
||||
return sCurrentPool;
|
||||
}
|
||||
|
||||
DebugAllocPool* pool = sCurrentPool->CreateChildPool();
|
||||
if (pool == NULL)
|
||||
return NULL;
|
||||
|
||||
sCurrentPool = pool;
|
||||
return sCurrentPool;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
delete_debug_alloc_pool(debug_alloc_pool* pool)
|
||||
{
|
||||
if (pool == NULL || sCurrentPool == NULL)
|
||||
return;
|
||||
|
||||
// find the pool in the hierarchy
|
||||
DebugAllocPool* otherPool = sCurrentPool;
|
||||
while (otherPool != NULL && otherPool != pool)
|
||||
otherPool = otherPool->Parent();
|
||||
|
||||
if (otherPool == NULL)
|
||||
return;
|
||||
|
||||
// destroy the pool
|
||||
sCurrentPool = pool->Parent();
|
||||
pool->Destroy();
|
||||
|
||||
if (pool != &sInitialPool)
|
||||
debug_free(pool);
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
debug_malloc(size_t size)
|
||||
{
|
||||
if (sCurrentPool == NULL)
|
||||
return NULL;
|
||||
|
||||
return sCurrentPool->Allocate(size);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
debug_free(void* address)
|
||||
{
|
||||
if (address != NULL && sCurrentPool != NULL)
|
||||
sCurrentPool->Free(address);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
debug_heap_init()
|
||||
{
|
||||
// create the heap area
|
||||
void* base;
|
||||
area_id area = create_area("kdebug heap", (void**)&base,
|
||||
B_ANY_KERNEL_ADDRESS, KDEBUG_HEAP, B_FULL_LOCK,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
||||
if (area < 0)
|
||||
return;
|
||||
|
||||
// switch from the small static buffer to the area
|
||||
InterruptsLocker locker;
|
||||
sHeapBase = base;
|
||||
sHeapSize = KDEBUG_HEAP;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de
|
||||
* Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de
|
||||
* Copyright 2006, Stephan Aßmus, superstippi@gmx.de
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
@ -14,6 +14,8 @@
|
||||
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <debug_heap.h>
|
||||
|
||||
#include "debug_commands.h"
|
||||
#include "debug_variables.h"
|
||||
|
||||
@ -46,7 +48,6 @@ static const int kMaxTokenLength = 128;
|
||||
static const int kJumpBufferCount = 10;
|
||||
|
||||
static const int kMaxArgumentCount = 64;
|
||||
static const size_t kTemporaryStorageSize = 10240;
|
||||
|
||||
static jmp_buf sJumpBuffers[kJumpBufferCount];
|
||||
static int sNextJumpBufferIndex = 0;
|
||||
@ -57,10 +58,6 @@ static int sExceptionPosition;
|
||||
static char sTempBuffer[128];
|
||||
// for composing debug output etc.
|
||||
|
||||
// temporary storage for command argument vectors and the arguments itself
|
||||
static uint8 sTemporaryStorage[kTemporaryStorageSize];
|
||||
static size_t sTemporaryStorageUsed = 0;
|
||||
|
||||
enum {
|
||||
TOKEN_ASSIGN_FLAG = 0x100,
|
||||
TOKEN_FLAGS = TOKEN_ASSIGN_FLAG,
|
||||
@ -143,44 +140,16 @@ parse_exception(const char* message, int32 position)
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - temporary storage
|
||||
|
||||
|
||||
static void*
|
||||
allocate_temp_storage(size_t size)
|
||||
checked_malloc(size_t size)
|
||||
{
|
||||
// 8 byte align
|
||||
size = (size + 7) & ~7;
|
||||
|
||||
if (sTemporaryStorageUsed + size > kTemporaryStorageSize) {
|
||||
parse_exception("out of temporary storage for command execution", -1);
|
||||
void* address = debug_malloc(size);
|
||||
if (address == NULL) {
|
||||
parse_exception("out of memory for command execution", -1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* buffer = sTemporaryStorage + sTemporaryStorageUsed;
|
||||
sTemporaryStorageUsed += size;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
free_temp_storage(void* _buffer)
|
||||
{
|
||||
uint8* buffer = (uint8*)_buffer;
|
||||
|
||||
if (buffer == NULL)
|
||||
return;
|
||||
|
||||
// must be freed in the reverse allocation order
|
||||
if (buffer < sTemporaryStorage
|
||||
|| buffer > sTemporaryStorage + sTemporaryStorageUsed) {
|
||||
panic("Invalid pointer passed to free_temp_storage(): %p, temp "
|
||||
"storage base: %p", buffer, sTemporaryStorage);
|
||||
return;
|
||||
}
|
||||
|
||||
sTemporaryStorageUsed = buffer - sTemporaryStorage;
|
||||
return address;
|
||||
}
|
||||
|
||||
|
||||
@ -750,7 +719,7 @@ ExpressionParser::_ParseExpression(bool expectAssignment)
|
||||
uint64
|
||||
ExpressionParser::_ParseCommandPipe(int& returnCode)
|
||||
{
|
||||
debugger_command_pipe* pipe = (debugger_command_pipe*)allocate_temp_storage(
|
||||
debugger_command_pipe* pipe = (debugger_command_pipe*)checked_malloc(
|
||||
sizeof(debugger_command_pipe));
|
||||
|
||||
pipe->segment_count = 0;
|
||||
@ -773,7 +742,7 @@ ExpressionParser::_ParseCommandPipe(int& returnCode)
|
||||
// invoke the pipe
|
||||
returnCode = invoke_debugger_command_pipe(pipe);
|
||||
|
||||
free_temp_storage(pipe);
|
||||
debug_free(pipe);
|
||||
|
||||
return get_debug_variable("_", 0);
|
||||
}
|
||||
@ -806,8 +775,7 @@ ExpressionParser::_ParseCommand(debugger_command_pipe_segment& segment)
|
||||
}
|
||||
|
||||
// allocate temporary buffer for the argument vector
|
||||
char** argv = (char**)allocate_temp_storage(
|
||||
kMaxArgumentCount * sizeof(char*));
|
||||
char** argv = (char**)checked_malloc(kMaxArgumentCount * sizeof(char*));
|
||||
int argc = 0;
|
||||
argv[argc++] = (char*)command->name;
|
||||
|
||||
@ -955,7 +923,7 @@ ExpressionParser::_AddArgument(int& argc, char** argv, const char* argument,
|
||||
if (length < 0)
|
||||
length = strlen(argument);
|
||||
length++;
|
||||
char* buffer = (char*)allocate_temp_storage(length);
|
||||
char* buffer = (char*)checked_malloc(length);
|
||||
strlcpy(buffer, argument, length);
|
||||
|
||||
argv[argc++] = buffer;
|
||||
@ -1169,9 +1137,8 @@ evaluate_debug_expression(const char* expression, uint64* _result, bool silent)
|
||||
|
||||
bool success;
|
||||
uint64 result;
|
||||
void* temporaryStorageMark = allocate_temp_storage(0);
|
||||
// get a temporary storage mark, so we can cleanup everything that
|
||||
// is allocated during the evaluation
|
||||
DebugAllocPoolScope allocPoolScope;
|
||||
// Will clean up all allocations when we return.
|
||||
|
||||
if (setjmp(sJumpBuffers[sNextJumpBufferIndex++]) == 0) {
|
||||
result = ExpressionParser().EvaluateExpression(expression);
|
||||
@ -1190,9 +1157,6 @@ evaluate_debug_expression(const char* expression, uint64* _result, bool silent)
|
||||
|
||||
sNextJumpBufferIndex--;
|
||||
|
||||
// cleanup temp allocations
|
||||
free_temp_storage(temporaryStorageMark);
|
||||
|
||||
if (success && _result != NULL)
|
||||
*_result = result;
|
||||
|
||||
@ -1210,9 +1174,8 @@ evaluate_debug_command(const char* commandLine)
|
||||
}
|
||||
|
||||
int returnCode = 0;
|
||||
void* temporaryStorageMark = allocate_temp_storage(0);
|
||||
// get a temporary storage mark, so we can cleanup everything that
|
||||
// is allocated during the evaluation
|
||||
DebugAllocPoolScope allocPoolScope;
|
||||
// Will clean up all allocations when we return.
|
||||
|
||||
if (setjmp(sJumpBuffers[sNextJumpBufferIndex++]) == 0) {
|
||||
ExpressionParser().EvaluateCommand(commandLine, returnCode);
|
||||
@ -1226,9 +1189,6 @@ evaluate_debug_command(const char* commandLine)
|
||||
|
||||
sNextJumpBufferIndex--;
|
||||
|
||||
// cleanup temp allocations
|
||||
free_temp_storage(temporaryStorageMark);
|
||||
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
@ -1244,9 +1204,8 @@ parse_next_debug_command_argument(const char** expressionString, char* buffer,
|
||||
}
|
||||
|
||||
status_t error;
|
||||
void* temporaryStorageMark = allocate_temp_storage(0);
|
||||
// get a temporary storage mark, so we can cleanup everything that
|
||||
// is allocated during the evaluation
|
||||
DebugAllocPoolScope allocPoolScope;
|
||||
// Will clean up all allocations when we return.
|
||||
|
||||
if (setjmp(sJumpBuffers[sNextJumpBufferIndex++]) == 0) {
|
||||
error = ExpressionParser().ParseNextCommandArgument(expressionString,
|
||||
@ -1262,8 +1221,5 @@ parse_next_debug_command_argument(const char** expressionString, char* buffer,
|
||||
|
||||
sNextJumpBufferIndex--;
|
||||
|
||||
// cleanup temp allocations
|
||||
free_temp_storage(temporaryStorageMark);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user