* Changed the way temporary variables work. They won't be unset before
a command is executed anymore. Instead the least recently used
temporary variable is overwritten, if there's no free slot for a new
temporary variable.
* Removed the special handling for the command result variable ("_"). It
just works like any other temporary variable, now.
* Individual temporary variables can be removed (e.g. using the "unset"
command).
* Added unset_all_debug_variables() and "unset_all" command to unset
all persistent and temporary variables.
* Removed remove_all_temporary_debug_variables and renamed
remove_debug_variable() to unset_debug_variable().
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23568 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -63,8 +63,8 @@ extern bool is_debug_variable_defined(const char* variableName);
|
|||||||
extern bool set_debug_variable(const char* variableName, uint64 value);
|
extern bool set_debug_variable(const char* variableName, uint64 value);
|
||||||
extern uint64 get_debug_variable(const char* variableName,
|
extern uint64 get_debug_variable(const char* variableName,
|
||||||
uint64 defaultValue);
|
uint64 defaultValue);
|
||||||
extern bool remove_debug_variable(const char* variableName);
|
extern bool unset_debug_variable(const char* variableName);
|
||||||
extern void remove_all_temporary_debug_variables();
|
extern void unset_all_debug_variables();
|
||||||
|
|
||||||
extern bool evaluate_debug_expression(const char* expression,
|
extern bool evaluate_debug_expression(const char* expression,
|
||||||
uint64* result, bool silent);
|
uint64* result, bool silent);
|
||||||
|
|||||||
@@ -94,10 +94,6 @@ in_command_invocation(void)
|
|||||||
int
|
int
|
||||||
invoke_debugger_command(struct debugger_command *command, int argc, char** argv)
|
invoke_debugger_command(struct debugger_command *command, int argc, char** argv)
|
||||||
{
|
{
|
||||||
// remove the temporary variables of the previously executed command, if
|
|
||||||
// this command sets a temporary variable
|
|
||||||
mark_temporary_debug_variables_obsolete();
|
|
||||||
|
|
||||||
struct thread* thread = thread_get_current_thread();
|
struct thread* thread = thread_get_current_thread();
|
||||||
addr_t oldFaultHandler = thread->fault_handler;
|
addr_t oldFaultHandler = thread->fault_handler;
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
|
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
#include <util/DoublyLinkedList.h>
|
||||||
|
|
||||||
|
|
||||||
static const int kVariableCount = 64;
|
static const int kVariableCount = 64;
|
||||||
@@ -42,10 +43,14 @@ struct Variable {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static Variable sVariables[kVariableCount];
|
struct TemporaryVariable : Variable,
|
||||||
static Variable sTemporaryVariables[kTemporaryVariableCount];
|
DoublyLinkedListLinkImpl<TemporaryVariable> {
|
||||||
|
};
|
||||||
|
|
||||||
static bool sTemporaryVariablesObsolete = false;
|
static Variable sVariables[kVariableCount];
|
||||||
|
static TemporaryVariable sTemporaryVariables[kTemporaryVariableCount];
|
||||||
|
|
||||||
|
static DoublyLinkedList<TemporaryVariable> sTemporaryVariablesLRUQueue;
|
||||||
|
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
@@ -55,25 +60,66 @@ is_temporary_variable(const char* variableName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
dequeue_temporary_variable(TemporaryVariable* variable)
|
||||||
|
{
|
||||||
|
// dequeue if queued
|
||||||
|
if (variable->GetDoublyLinkedListLink()->previous != NULL
|
||||||
|
|| sTemporaryVariablesLRUQueue.Head() == variable) {
|
||||||
|
sTemporaryVariablesLRUQueue.Remove(variable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
unset_variable(Variable* variable)
|
||||||
|
{
|
||||||
|
if (is_temporary_variable(variable->name))
|
||||||
|
dequeue_temporary_variable(static_cast<TemporaryVariable*>(variable));
|
||||||
|
|
||||||
|
variable->Uninit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
touch_variable(Variable* _variable)
|
||||||
|
{
|
||||||
|
if (!is_temporary_variable(_variable->name))
|
||||||
|
return;
|
||||||
|
|
||||||
|
TemporaryVariable* variable = static_cast<TemporaryVariable*>(_variable);
|
||||||
|
|
||||||
|
// move to the end of the queue
|
||||||
|
dequeue_temporary_variable(variable);
|
||||||
|
sTemporaryVariablesLRUQueue.Add(variable);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static Variable*
|
||||||
|
free_temporary_variable_slot()
|
||||||
|
{
|
||||||
|
TemporaryVariable* variable = sTemporaryVariablesLRUQueue.RemoveHead();
|
||||||
|
if (variable)
|
||||||
|
variable->Uninit();
|
||||||
|
|
||||||
|
return variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static Variable*
|
static Variable*
|
||||||
get_variable(const char* variableName, bool create)
|
get_variable(const char* variableName, bool create)
|
||||||
{
|
{
|
||||||
Variable* variables;
|
Variable* variables;
|
||||||
int variableCount;
|
int variableCount;
|
||||||
|
|
||||||
// get the variable domain (persistent or temporary)
|
// find the variable in the respective array and a free slot, we can
|
||||||
if (is_temporary_variable(variableName)) {
|
// use, if it doesn't exist yet
|
||||||
variables = sTemporaryVariables;
|
|
||||||
variableCount = kTemporaryVariableCount;
|
|
||||||
} else {
|
|
||||||
variables = sVariables;
|
|
||||||
variableCount = kVariableCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
Variable* freeSlot = NULL;
|
Variable* freeSlot = NULL;
|
||||||
|
|
||||||
for (int i = 0; i < variableCount; i++) {
|
if (is_temporary_variable(variableName)) {
|
||||||
Variable* variable = variables + i;
|
// temporary variable
|
||||||
|
for (int i = 0; i < kTemporaryVariableCount; i++) {
|
||||||
|
TemporaryVariable* variable = sTemporaryVariables + i;
|
||||||
|
|
||||||
if (!variable->IsUsed()) {
|
if (!variable->IsUsed()) {
|
||||||
if (freeSlot == NULL)
|
if (freeSlot == NULL)
|
||||||
@@ -82,6 +128,22 @@ get_variable(const char* variableName, bool create)
|
|||||||
return variable;
|
return variable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (create && freeSlot == NULL)
|
||||||
|
freeSlot = free_temporary_variable_slot();
|
||||||
|
} else {
|
||||||
|
// persistent variable
|
||||||
|
for (int i = 0; i < kVariableCount; i++) {
|
||||||
|
Variable* variable = sVariables + i;
|
||||||
|
|
||||||
|
if (!variable->IsUsed()) {
|
||||||
|
if (freeSlot == NULL)
|
||||||
|
freeSlot = variable;
|
||||||
|
} else if (variable->HasName(variableName))
|
||||||
|
return variable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (create && freeSlot != NULL) {
|
if (create && freeSlot != NULL) {
|
||||||
freeSlot->Init(variableName);
|
freeSlot->Init(variableName);
|
||||||
return freeSlot;
|
return freeSlot;
|
||||||
@@ -106,15 +168,29 @@ cmd_unset_variable(int argc, char **argv)
|
|||||||
|
|
||||||
const char* variable = argv[1];
|
const char* variable = argv[1];
|
||||||
|
|
||||||
if (is_temporary_variable(variable))
|
if (!unset_debug_variable(variable))
|
||||||
kprintf("You cannot remove temporary variables.\n");
|
|
||||||
else if (!remove_debug_variable(variable))
|
|
||||||
kprintf("Did not find variable %s.\n", variable);
|
kprintf("Did not find variable %s.\n", variable);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
cmd_unset_all_variables(int argc, char **argv)
|
||||||
|
{
|
||||||
|
static const char* usage = "usage: %s\n"
|
||||||
|
"Unsets all variables.\n";
|
||||||
|
if (argc == 2 && strcmp(argv[1], "--help") == 0) {
|
||||||
|
kprintf(usage, argv[0]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unset_all_debug_variables();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cmd_variables(int argc, char **argv)
|
cmd_variables(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@@ -160,14 +236,9 @@ is_debug_variable_defined(const char* variableName)
|
|||||||
bool
|
bool
|
||||||
set_debug_variable(const char* variableName, uint64 value)
|
set_debug_variable(const char* variableName, uint64 value)
|
||||||
{
|
{
|
||||||
if (sTemporaryVariablesObsolete && is_temporary_variable(variableName)
|
|
||||||
&& strcmp(variableName, kCommandReturnValueVariable) != 0) {
|
|
||||||
remove_all_temporary_debug_variables();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (Variable* variable = get_variable(variableName, true)) {
|
if (Variable* variable = get_variable(variableName, true)) {
|
||||||
variable->value = value;
|
variable->value = value;
|
||||||
|
touch_variable(variable);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,23 +249,20 @@ set_debug_variable(const char* variableName, uint64 value)
|
|||||||
uint64
|
uint64
|
||||||
get_debug_variable(const char* variableName, uint64 defaultValue)
|
get_debug_variable(const char* variableName, uint64 defaultValue)
|
||||||
{
|
{
|
||||||
if (Variable* variable = get_variable(variableName, false))
|
if (Variable* variable = get_variable(variableName, false)) {
|
||||||
|
touch_variable(variable);
|
||||||
return variable->value;
|
return variable->value;
|
||||||
|
}
|
||||||
|
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
remove_debug_variable(const char* variableName)
|
unset_debug_variable(const char* variableName)
|
||||||
{
|
{
|
||||||
// We don't allow explicit removal of inidividual temporary variables.
|
|
||||||
// This speeds up removing them all.
|
|
||||||
if (is_temporary_variable(variableName))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (Variable* variable = get_variable(variableName, false)) {
|
if (Variable* variable = get_variable(variableName, false)) {
|
||||||
variable->Uninit();
|
unset_variable(variable);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,42 +271,31 @@ remove_debug_variable(const char* variableName)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
remove_all_temporary_debug_variables()
|
unset_all_debug_variables()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < kTemporaryVariableCount; i++) {
|
// persistent variables
|
||||||
Variable& variable = sTemporaryVariables[i];
|
for (int i = 0; i < kVariableCount; i++) {
|
||||||
if (!variable.IsUsed())
|
Variable& variable = sVariables[i];
|
||||||
break;
|
if (variable.IsUsed())
|
||||||
|
unset_variable(&variable);
|
||||||
variable.Uninit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// always keep the return value variable defined
|
// temporary variables
|
||||||
set_debug_variable(kCommandReturnValueVariable, 0);
|
for (int i = 0; i < kTemporaryVariableCount; i++) {
|
||||||
|
Variable& variable = sTemporaryVariables[i];
|
||||||
sTemporaryVariablesObsolete = false;
|
if (variable.IsUsed())
|
||||||
}
|
unset_variable(&variable);
|
||||||
|
}
|
||||||
|
|
||||||
/*! Schedules all temporary variables for removal.
|
|
||||||
They will be removed, the next time set_debug_variable() is invoked
|
|
||||||
for a temporary variable other than the command return value variable.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
mark_temporary_debug_variables_obsolete()
|
|
||||||
{
|
|
||||||
sTemporaryVariablesObsolete = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
debug_variables_init()
|
debug_variables_init()
|
||||||
{
|
{
|
||||||
// always keep the return value variable defined
|
|
||||||
set_debug_variable(kCommandReturnValueVariable, 0);
|
|
||||||
|
|
||||||
add_debugger_command("unset", &cmd_unset_variable,
|
add_debugger_command("unset", &cmd_unset_variable,
|
||||||
"Unsets the given variable");
|
"Unsets the given variable");
|
||||||
|
add_debugger_command("unset_all", &cmd_unset_all_variables,
|
||||||
|
"Unsets all variables");
|
||||||
add_debugger_command("vars", &cmd_variables,
|
add_debugger_command("vars", &cmd_variables,
|
||||||
"Lists all defined variables with their values");
|
"Lists all defined variables with their values");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,6 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void mark_temporary_debug_variables_obsolete();
|
|
||||||
|
|
||||||
void debug_variables_init();
|
void debug_variables_init();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
Reference in New Issue
Block a user