Some more work on the tracing API:

* Added function to allocate space in the buffer.
* Dump() now fills a buffer instead of printing its data directly.
* This allows the new "#pattern" argument of the "traced" command to 
  work. When you're using that, the index of the trace entry is printed
  out, too, so that you can then get a full dump around the hits.
* Added an AddDump() method to the AbstractTraceEntry class so that 
  there is no need to call the inherited function anymore.
* Minor cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23479 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-01-13 02:50:32 +00:00
parent a5ec34950d
commit 8e43ece8b8
4 changed files with 128 additions and 76 deletions

View File

@ -5,6 +5,8 @@
#include <SupportDefs.h>
#include <KernelExport.h>
#include <stdio.h>
#define ENABLE_TRACING 0
#define MAX_TRACE_SIZE 1024 * 1024
@ -23,7 +25,7 @@ class TraceEntry : trace_entry {
TraceEntry();
virtual ~TraceEntry();
virtual void Dump();
virtual void Dump(char* buffer, size_t bufferSize);
size_t Size() const { return size; }
uint16 Flags() const { return flags; }
@ -42,9 +44,15 @@ class AbstractTraceEntry : public TraceEntry {
{
}
virtual void Dump()
virtual void Dump(char* buffer, size_t bufferSize)
{
int length = snprintf(buffer, bufferSize, "[%6ld] %Ld: ",
fThread, fTime);
AddDump(buffer + length, bufferSize - length);
}
virtual void AddDump(char* buffer, size_t bufferSize)
{
kprintf("[%6ld] %Ld: ", fThread, fTime);
}
thread_id Thread() const { return fThread; }
@ -58,8 +66,14 @@ class AbstractTraceEntry : public TraceEntry {
#endif // __cplusplus
#ifdef __cplusplus
extern "C"
extern "C" {
#endif
uint8* alloc_tracing_buffer(size_t size);
status_t tracing_init(void);
#ifdef __cplusplus
}
#endif
#endif /* KERNEL_UTIL_TRACING_H */

View File

@ -48,11 +48,10 @@ class Allocate : public AbstractTraceEntry {
Initialized();
}
virtual void Dump()
virtual void AddDump(char *buffer, size_t size)
{
AbstractTraceEntry::Dump();
kprintf("alloc %lu.%u.%u\n", fRun.AllocationGroup(), fRun.Start(),
fRun.Length());
snprintf(buffer, size, "alloc %lu.%u.%u", fRun.AllocationGroup(),
fRun.Start(), fRun.Length());
}
private:
@ -68,11 +67,10 @@ class Free : public AbstractTraceEntry {
Initialized();
}
virtual void Dump()
virtual void AddDump(char *buffer, size_t size)
{
AbstractTraceEntry::Dump();
kprintf("free %lu.%u.%u\n", fRun.AllocationGroup(), fRun.Start(),
fRun.Length());
snprintf(buffer, size, "free %lu.%u.%u\n", fRun.AllocationGroup(),
fRun.Start(), fRun.Length());
}
private:

View File

@ -36,12 +36,11 @@ class Create : public AbstractTraceEntry {
Initialized();
}
virtual void Dump()
virtual void AddDump(char *buffer, size_t size)
{
AbstractTraceEntry::Dump();
kprintf("CREATE %Ld (%p), parent %Ld (%p), \"%s\", mode %lx, "
"omode %x, type %lx\n", fID, fInode, fParentID, fParent,
fName, fMode, fOpenMode, fType);
snprintf(buffer, size, "CREATE %Ld (%p), parent %Ld (%p), \"%s\", "
"mode %lx, omode %x, type %lx\n", fID, fInode, fParentID,
fParent, fName, fMode, fOpenMode, fType);
}
private:
@ -67,10 +66,10 @@ class Remove : public AbstractTraceEntry {
Initialized();
}
virtual void Dump()
virtual void AddDump(char *buffer, size_t size)
{
AbstractTraceEntry::Dump();
kprintf("REMOVE %Ld (%p), \"%s\"\n", fID, fInode, fName);
snprintf(buffer, size, "REMOVE %Ld (%p), \"%s\"\n", fID, fInode,
fName);
}
private:
@ -91,11 +90,10 @@ class Resize : public AbstractTraceEntry {
Initialized();
}
virtual void Dump()
virtual void AddDump(char *buffer, size_t size)
{
AbstractTraceEntry::Dump();
kprintf("RESIZE %Ld (%p), %Ld -> %Ld\n", fID, fInode, fOldSize,
fNewSize);
snprintf(buffer, size, "RESIZE %Ld (%p), %Ld -> %Ld\n", fID, fInode,
fOldSize, fNewSize);
}
private:

View File

@ -9,7 +9,8 @@
enum {
WRAP_ENTRY = 0x01,
ENTRY_INITIALIZED = 0x02
ENTRY_INITIALIZED = 0x02,
BUFFER_ENTRY = 0x04
};
static const size_t kBufferSize = MAX_TRACE_SIZE / 4 - 1;
@ -36,9 +37,9 @@ next_entry(trace_entry* entry)
static void
make_space(size_t size)
make_space(size_t needed)
{
if (sBufferEnd + size / 4 > sBuffer + kBufferSize - 1) {
if (sBufferEnd + needed / 4 > sBuffer + kBufferSize - 1) {
sBufferEnd->size = 0;
sBufferEnd->flags = WRAP_ENTRY;
sBufferEnd = sBuffer;
@ -48,62 +49,26 @@ make_space(size_t size)
if (diff < 0)
sBufferEnd = sBuffer;
else
size -= diff;
needed -= diff;
while (true) {
uint16 skip = sBufferStart->size;
uint16 freed = sBufferStart->size;
sBufferStart = next_entry(sBufferStart);
if (sBufferStart == NULL)
sBufferStart = sBuffer;
sBufferStart = sBufferEnd;
sEntries--;
if (size <= skip)
if (needed <= freed)
break;
size -= skip;
needed -= freed;
}
}
#endif // ENABLE_TRACING
// #pragma mark -
TraceEntry::TraceEntry()
trace_entry*
allocate_entry(size_t size)
{
}
TraceEntry::~TraceEntry()
{
}
void
TraceEntry::Dump()
{
#if ENABLE_TRACING
// to be overloaded by subclasses
kprintf("ENTRY %p\n", this);
#endif
}
void
TraceEntry::Initialized()
{
#if ENABLE_TRACING
flags |= ENTRY_INITIALIZED;
#endif
}
void*
TraceEntry::operator new(size_t size, const std::nothrow_t&) throw()
{
#if ENABLE_TRACING
if (sBuffer == NULL)
return NULL;
@ -127,7 +92,50 @@ TraceEntry::operator new(size_t size, const std::nothrow_t&) throw()
sBufferEnd += size >> 2;
sEntries++;
return entry;
#else // !ENABLE_TRACING
}
#endif // ENABLE_TRACING
// #pragma mark -
TraceEntry::TraceEntry()
{
}
TraceEntry::~TraceEntry()
{
}
void
TraceEntry::Dump(char* buffer, size_t bufferSize)
{
#if ENABLE_TRACING
// to be overloaded by subclasses
snprintf(buffer, bufferSize, "ENTRY %p", this);
#endif
}
void
TraceEntry::Initialized()
{
#if ENABLE_TRACING
flags |= ENTRY_INITIALIZED;
#endif
}
void*
TraceEntry::operator new(size_t size, const std::nothrow_t&) throw()
{
#if ENABLE_TRACING
return allocate_entry(size);
#else
return NULL;
#endif
}
@ -142,6 +150,10 @@ TraceEntry::operator new(size_t size, const std::nothrow_t&) throw()
int
dump_tracing(int argc, char** argv)
{
const char *pattern = NULL;
if (argv[argc - 1][0] == '#')
pattern = argv[--argc] + 1;
int32 count = 30;
if (argc == 2)
count = strtol(argv[1], NULL, 0);
@ -152,7 +164,7 @@ dump_tracing(int argc, char** argv)
start = strtol(argv[1], NULL, 0);
count = strtol(argv[2], NULL, 0);
} else if (argc > 3) {
kprintf("usage: %s [start] [count]\n", argv[0]);
kprintf("usage: %s [start] [count] [#pattern]\n", argv[0]);
return 0;
}
// TODO: add pattern matching mechanism for the class name
@ -168,11 +180,26 @@ dump_tracing(int argc, char** argv)
continue;
if (index > start + count)
break;
if ((entry->flags & BUFFER_ENTRY) != 0) {
// skip buffer entries
index--;
continue;
}
if ((current->flags & ENTRY_INITIALIZED) != 0)
((TraceEntry*)current)->Dump();
else
kprintf("** uninitialized entry **\n");
if ((current->flags & ENTRY_INITIALIZED) != 0) {
char buffer[256];
buffer[0] = '\0';
((TraceEntry*)current)->Dump(buffer, sizeof(buffer));
if (pattern != NULL && strstr(buffer, pattern) == NULL)
continue;
if (pattern != NULL)
kprintf("%5ld. %s\n", index, buffer);
else
kprintf("%s\n", buffer);
} else
kprintf("%5ld. ** uninitialized entry **\n", index);
}
kprintf("%ld of %ld entries.\n", count, sEntries);
@ -182,6 +209,21 @@ dump_tracing(int argc, char** argv)
#endif // ENABLE_TRACING
extern "C" uint8*
alloc_tracing_buffer(size_t size)
{
#if ENABLE_TRACING
trace_entry* entry = allocate_entry(size + sizeof(trace_entry));
if (entry == NULL)
return NULL;
entry->flags = BUFFER_ENTRY;
return (uint8*)(entry + 1);
#else
return NULL;
#endif
}
extern "C" status_t
tracing_init(void)