* Added kernel tracing. Even with optional stack traces.
* Added "mode" parameter to set_paranoia_check(), which specifies
whether the check is supposed to already exist/not exist yet. This
allows for, as it turns out, very useful additional tests. Added
{ADD,UPDATE}_PARANOIA_CHECK macros that imply the used "mode"
parameter.
* PARANOIA_SLOT_COUNT was accidentally redefined in the source file.
* Fixed remove_paranoia_check(). It didn't remove anything.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25207 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -20,6 +20,8 @@
|
|||||||
//#define BLOCK_CACHE_TRANSACTION_TRACING
|
//#define BLOCK_CACHE_TRANSACTION_TRACING
|
||||||
//#define KERNEL_HEAP_TRACING
|
//#define KERNEL_HEAP_TRACING
|
||||||
//#define PAGE_ALLOCATION_TRACING
|
//#define PAGE_ALLOCATION_TRACING
|
||||||
|
//#define PARANOIA_TRACING
|
||||||
|
//#define PARANOIA_TRACING_STACK_TRACE 0
|
||||||
//#define OBJECT_CACHE_TRACING
|
//#define OBJECT_CACHE_TRACING
|
||||||
//#define RUNTIME_LOADER_TRACING
|
//#define RUNTIME_LOADER_TRACING
|
||||||
//#define SIGNAL_TRACING
|
//#define SIGNAL_TRACING
|
||||||
|
|||||||
@@ -17,6 +17,13 @@
|
|||||||
// defined below and the ParanoiaChecker class.
|
// defined below and the ParanoiaChecker class.
|
||||||
|
|
||||||
|
|
||||||
|
enum paranoia_set_check_mode {
|
||||||
|
PARANOIA_DONT_FAIL,
|
||||||
|
PARANOIA_FAIL_IF_EXISTS,
|
||||||
|
PARANOIA_FAIL_IF_MISSING
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
#if ENABLE_PARANOIA_CHECKS
|
#if ENABLE_PARANOIA_CHECKS
|
||||||
@@ -27,7 +34,7 @@ status_t delete_paranoia_check_set(const void* object);
|
|||||||
status_t run_paranoia_checks(const void* object);
|
status_t run_paranoia_checks(const void* object);
|
||||||
|
|
||||||
status_t set_paranoia_check(const void* object, const void* address,
|
status_t set_paranoia_check(const void* object, const void* address,
|
||||||
size_t size);
|
size_t size, paranoia_set_check_mode mode);
|
||||||
status_t remove_paranoia_check(const void* object, const void* address,
|
status_t remove_paranoia_check(const void* object, const void* address,
|
||||||
size_t size);
|
size_t size);
|
||||||
|
|
||||||
@@ -50,8 +57,15 @@ __END_DECLS
|
|||||||
PARANOIA_ONLY(delete_paranoia_check_set((object)))
|
PARANOIA_ONLY(delete_paranoia_check_set((object)))
|
||||||
#define RUN_PARANOIA_CHECKS(object) \
|
#define RUN_PARANOIA_CHECKS(object) \
|
||||||
PARANOIA_ONLY(run_paranoia_checks((object)))
|
PARANOIA_ONLY(run_paranoia_checks((object)))
|
||||||
|
#define ADD_PARANOIA_CHECK(object, address, size) \
|
||||||
|
PARANOIA_ONLY(set_paranoia_check((object), (address), (size), \
|
||||||
|
PARANOIA_FAIL_IF_EXISTS))
|
||||||
|
#define UPDATE_PARANOIA_CHECK(object, address, size) \
|
||||||
|
PARANOIA_ONLY(set_paranoia_check((object), (address), (size), \
|
||||||
|
PARANOIA_FAIL_IF_MISSING))
|
||||||
#define SET_PARANOIA_CHECK(object, address, size) \
|
#define SET_PARANOIA_CHECK(object, address, size) \
|
||||||
PARANOIA_ONLY(set_paranoia_check((object), (address), (size)))
|
PARANOIA_ONLY(set_paranoia_check((object), (address), (size), \
|
||||||
|
PARANOIA_DONT_FAIL))
|
||||||
#define REMOVE_PARANOIA_CHECK(object, address, size) \
|
#define REMOVE_PARANOIA_CHECK(object, address, size) \
|
||||||
PARANOIA_ONLY(remove_paranoia_check((object), (address), (size)))
|
PARANOIA_ONLY(remove_paranoia_check((object), (address), (size)))
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
|
|
||||||
|
#include <tracing.h>
|
||||||
#include <util/AutoLock.h>
|
#include <util/AutoLock.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -192,10 +193,152 @@ union paranoia_slot {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Tracing
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PARANOIA_TRACING
|
||||||
|
|
||||||
|
|
||||||
|
namespace ParanoiaTracing {
|
||||||
|
|
||||||
|
class ParanoiaTraceEntry : public AbstractTraceEntry {
|
||||||
|
public:
|
||||||
|
ParanoiaTraceEntry(const void* object)
|
||||||
|
:
|
||||||
|
fObject(object)
|
||||||
|
{
|
||||||
|
#if PARANOIA_TRACING_STACK_TRACE
|
||||||
|
fStackTrace = capture_tracing_stack_trace(PARANOIA_TRACING_STACK_TRACE,
|
||||||
|
1, false);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if PARANOIA_TRACING_STACK_TRACE
|
||||||
|
virtual void DumpStackTrace(TraceOutput& out)
|
||||||
|
{
|
||||||
|
out.PrintStackTrace(fStackTrace);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const void* fObject;
|
||||||
|
#if PARANOIA_TRACING_STACK_TRACE
|
||||||
|
tracing_stack_trace* fStackTrace;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CreateCheckSet : public ParanoiaTraceEntry {
|
||||||
|
public:
|
||||||
|
CreateCheckSet(const void* object, const char* description)
|
||||||
|
:
|
||||||
|
ParanoiaTraceEntry(object)
|
||||||
|
{
|
||||||
|
fDescription = alloc_tracing_buffer_strcpy(description, 64, false);
|
||||||
|
Initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void AddDump(TraceOutput& out)
|
||||||
|
{
|
||||||
|
out.Print("paranoia create check set: object: %p, "
|
||||||
|
"description: \"%s\"", fObject, fDescription);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* fDescription;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteCheckSet : public ParanoiaTraceEntry {
|
||||||
|
public:
|
||||||
|
DeleteCheckSet(const void* object)
|
||||||
|
:
|
||||||
|
ParanoiaTraceEntry(object)
|
||||||
|
{
|
||||||
|
Initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void AddDump(TraceOutput& out)
|
||||||
|
{
|
||||||
|
out.Print("paranoia delete check set: object: %p", fObject);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class SetCheck : public ParanoiaTraceEntry {
|
||||||
|
public:
|
||||||
|
SetCheck(const void* object, const void* address, size_t size,
|
||||||
|
paranoia_set_check_mode mode)
|
||||||
|
:
|
||||||
|
ParanoiaTraceEntry(object),
|
||||||
|
fAddress(address),
|
||||||
|
fSize(size),
|
||||||
|
fMode(mode)
|
||||||
|
{
|
||||||
|
Initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void AddDump(TraceOutput& out)
|
||||||
|
{
|
||||||
|
const char* mode = "??? op:";
|
||||||
|
switch (fMode) {
|
||||||
|
case PARANOIA_DONT_FAIL:
|
||||||
|
mode = "set: ";
|
||||||
|
break;
|
||||||
|
case PARANOIA_FAIL_IF_EXISTS:
|
||||||
|
mode = "add: ";
|
||||||
|
break;
|
||||||
|
case PARANOIA_FAIL_IF_MISSING:
|
||||||
|
mode = "update:";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
out.Print("paranoia check %s object: %p, address: %p, size: %lu",
|
||||||
|
mode, fObject, fAddress, fSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const void* fAddress;
|
||||||
|
size_t fSize;
|
||||||
|
paranoia_set_check_mode fMode;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveCheck : public ParanoiaTraceEntry {
|
||||||
|
public:
|
||||||
|
RemoveCheck(const void* object, const void* address, size_t size)
|
||||||
|
:
|
||||||
|
ParanoiaTraceEntry(object),
|
||||||
|
fAddress(address),
|
||||||
|
fSize(size)
|
||||||
|
{
|
||||||
|
Initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void AddDump(TraceOutput& out)
|
||||||
|
{
|
||||||
|
out.Print("paranoia check remove: object: %p, address: %p, size: "
|
||||||
|
"%lu", fObject, fAddress, fSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const void* fAddress;
|
||||||
|
size_t fSize;
|
||||||
|
paranoia_set_check_mode fMode;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace ParanoiaTracing
|
||||||
|
|
||||||
|
# define T(x) new(std::nothrow) ParanoiaTracing::x
|
||||||
|
|
||||||
|
#else
|
||||||
|
# define T(x)
|
||||||
|
#endif // PARANOIA_TRACING
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
#define PARANOIA_SLOT_COUNT 1024
|
|
||||||
#define PARANOIA_HASH_SIZE PARANOIA_SLOT_COUNT
|
#define PARANOIA_HASH_SIZE PARANOIA_SLOT_COUNT
|
||||||
|
|
||||||
static paranoia_slot sSlots[PARANOIA_SLOT_COUNT];
|
static paranoia_slot sSlots[PARANOIA_SLOT_COUNT];
|
||||||
@@ -268,6 +411,8 @@ lookup_check_set(const void* object)
|
|||||||
status_t
|
status_t
|
||||||
create_paranoia_check_set(const void* object, const char* description)
|
create_paranoia_check_set(const void* object, const char* description)
|
||||||
{
|
{
|
||||||
|
T(CreateCheckSet(object, description));
|
||||||
|
|
||||||
if (object == NULL) {
|
if (object == NULL) {
|
||||||
panic("create_paranoia_check_set(): NULL object");
|
panic("create_paranoia_check_set(): NULL object");
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -300,6 +445,8 @@ create_paranoia_check_set(const void* object, const char* description)
|
|||||||
status_t
|
status_t
|
||||||
delete_paranoia_check_set(const void* object)
|
delete_paranoia_check_set(const void* object)
|
||||||
{
|
{
|
||||||
|
T(DeleteCheckSet(object));
|
||||||
|
|
||||||
InterruptsSpinLocker _(sParanoiaLock);
|
InterruptsSpinLocker _(sParanoiaLock);
|
||||||
|
|
||||||
// get check set
|
// get check set
|
||||||
@@ -354,8 +501,11 @@ run_paranoia_checks(const void* object)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
set_paranoia_check(const void* object, const void* address, size_t size)
|
set_paranoia_check(const void* object, const void* address, size_t size,
|
||||||
|
paranoia_set_check_mode mode)
|
||||||
{
|
{
|
||||||
|
T(SetCheck(object, address, size, mode));
|
||||||
|
|
||||||
InterruptsSpinLocker _(sParanoiaLock);
|
InterruptsSpinLocker _(sParanoiaLock);
|
||||||
|
|
||||||
// get check set
|
// get check set
|
||||||
@@ -369,6 +519,12 @@ set_paranoia_check(const void* object, const void* address, size_t size)
|
|||||||
// update check, if already existing
|
// update check, if already existing
|
||||||
ParanoiaCheck* check = set->FindCheck(address);
|
ParanoiaCheck* check = set->FindCheck(address);
|
||||||
if (check != NULL) {
|
if (check != NULL) {
|
||||||
|
if (mode == PARANOIA_FAIL_IF_EXISTS) {
|
||||||
|
panic("set_paranoia_check(): object %p already has a check for "
|
||||||
|
"address %p", object, address);
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (check->Size() != size) {
|
if (check->Size() != size) {
|
||||||
panic("set_paranoia_check(): changing check sizes not supported");
|
panic("set_paranoia_check(): changing check sizes not supported");
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -378,6 +534,12 @@ set_paranoia_check(const void* object, const void* address, size_t size)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mode == PARANOIA_FAIL_IF_MISSING) {
|
||||||
|
panic("set_paranoia_check(): object %p doesn't have a check for "
|
||||||
|
"address %p yet", object, address);
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
// allocate slot
|
// allocate slot
|
||||||
paranoia_slot* slot = allocate_slot();
|
paranoia_slot* slot = allocate_slot();
|
||||||
if (slot == NULL) {
|
if (slot == NULL) {
|
||||||
@@ -395,6 +557,8 @@ set_paranoia_check(const void* object, const void* address, size_t size)
|
|||||||
status_t
|
status_t
|
||||||
remove_paranoia_check(const void* object, const void* address, size_t size)
|
remove_paranoia_check(const void* object, const void* address, size_t size)
|
||||||
{
|
{
|
||||||
|
T(RemoveCheck(object, address, size));
|
||||||
|
|
||||||
InterruptsSpinLocker _(sParanoiaLock);
|
InterruptsSpinLocker _(sParanoiaLock);
|
||||||
|
|
||||||
// get check set
|
// get check set
|
||||||
@@ -407,15 +571,16 @@ remove_paranoia_check(const void* object, const void* address, size_t size)
|
|||||||
|
|
||||||
// get check
|
// get check
|
||||||
ParanoiaCheck* check = set->FindCheck(address);
|
ParanoiaCheck* check = set->FindCheck(address);
|
||||||
if (check != NULL) {
|
if (check == NULL) {
|
||||||
if (check->Size() != size) {
|
panic("remove_paranoia_check(): no check for address %p "
|
||||||
panic("remove_paranoia_check(): changing check sizes not "
|
"(object %p (%s))", address, object, set->Description());
|
||||||
"supported");
|
return B_BAD_VALUE;
|
||||||
return B_BAD_VALUE;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
check->Update();
|
if (check->Size() != size) {
|
||||||
return B_OK;
|
panic("remove_paranoia_check(): changing check sizes not "
|
||||||
|
"supported");
|
||||||
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
set->RemoveCheck(check);
|
set->RemoveCheck(check);
|
||||||
|
|||||||
Reference in New Issue
Block a user