Skip to content

Commit

Permalink
Add support for longer records with more than 4 arguments (up to 8)
Browse files Browse the repository at this point in the history
  • Loading branch information
c3d committed Jul 6, 2017
1 parent c3c38f3 commit be291f7
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 52 deletions.
59 changes: 37 additions & 22 deletions recorder.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ recorder_info * recorders = NULL;
recorder_tweak *tweaks = NULL;


static void recorder_dump_entry(const char *label,
static void recorder_dump_entry(recorder_info *rec,
recorder_entry *entry,
recorder_format_fn format,
recorder_show_fn show,
Expand All @@ -63,6 +63,7 @@ static void recorder_dump_entry(const char *label,
// Dump a recorder entry in a buffer between dst and dst_end, return last pos
// ----------------------------------------------------------------------------
{
const char *label = rec->name;
char buffer[256];
char format_buffer[32];
char *dst = buffer;
Expand All @@ -71,6 +72,10 @@ static void recorder_dump_entry(const char *label,
unsigned argIndex = 0;
const unsigned maxArgIndex = sizeof(entry->args) / sizeof(entry->args[0]);

// Exit if we get there for a long-format second entry
if (!fmt)
return;

// Apply formatting. This complicated loop is because
// we need to detect floating-point values, which are passed
// differently on many architectures such as x86 or ARM
Expand All @@ -79,7 +84,7 @@ static void recorder_dump_entry(const char *label,
// and call the variadic snprintf passing a double value that will
// naturally go in the right register. A bit ugly.
bool finishedInNewline = false;
while (dst < dst_end && argIndex < maxArgIndex)
while (dst < dst_end)
{
char c = *fmt++;
if (c != '%')
Expand Down Expand Up @@ -149,6 +154,17 @@ static void recorder_dump_entry(const char *label,
break;
int isString = (c == 's' || c == 'S');
*fmtCopy++ = 0;

// Check for long entry, need to skip to next entry
if (argIndex >= maxArgIndex)
{
ring_p ring = rec->ring;
recorder_entry *base = (recorder_entry *) (ring + 1);
ringidx_t idx = entry - base;
entry = &base[(idx + 1) % ring->size];
argIndex = 0;
}

if (floatingPoint)
{
double floatArg;
Expand Down Expand Up @@ -304,18 +320,18 @@ unsigned recorder_sort(const char *what,
// Dump all entries, sorted by their global 'order' field
// ----------------------------------------------------------------------------
{
recorder_entry entry;
regex_t re;
regmatch_t rm;
unsigned dumped = 0;
recorder_entry *entry;
regex_t re;
regmatch_t rm;
unsigned dumped = 0;

int status = regcomp(&re, what, REG_EXTENDED|REG_ICASE);

while (status == 0)
{
uintptr_t lowestOrder = ~0UL;
recorder_info *lowest = NULL;
recorder_info *rec;
uintptr_t lowest_order = ~0UL;
recorder_entry *lowest_entry = NULL;
recorder_info *lowest_rec = NULL;
recorder_info *rec;

for (rec = recorders; rec; rec = rec->next)
{
Expand All @@ -325,25 +341,24 @@ unsigned recorder_sort(const char *what,
continue;

// Loop while this recorder is readable and we can find next order
if (rec->readable())
entry = rec->peek();
if (entry)
{
rec->peek(&entry);
if (entry.order < lowestOrder)
uintptr_t order = entry->order;
if (order < lowest_order)
{
lowest = rec;
lowestOrder = entry.order;
lowest_rec = rec;
lowest_order = order;
lowest_entry = entry;
}
}
}

if (!lowest)
if (!lowest_rec)
break;

// The first read may fail due to 'catch up', if so continue
if (!lowest->read(&entry, 1))
continue;

recorder_dump_entry(lowest->name, &entry, format, show, output);
ring_fetch_add(lowest_rec->ring->reader, 1);
recorder_dump_entry(lowest_rec, lowest_entry, format, show, output);
dumped++;
}

Expand Down Expand Up @@ -1003,7 +1018,7 @@ void recorder_trace_entry(recorder_info *info, recorder_entry *entry)
{
unsigned i;
if (info->trace != RECORDER_CHAN_MAGIC)
recorder_dump_entry(info->name, entry,
recorder_dump_entry(info, entry,
recorder_format, recorder_show, recorder_output);
for (i = 0; i < 4; i++)
{
Expand Down
143 changes: 133 additions & 10 deletions recorder.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,8 @@ extern uintptr_t recorder_order;
typedef size_t (*recorder_read_fn)(recorder_entry *entries, size_t count);

/// A function pointer type used by generic code to peek into each recorder.
/// \param entries will be filled with the first readable entry.
/// \return the read index of the entry that was read.
typedef size_t (*recorder_peek_fn)(recorder_entry *entry);
/// \return a pointer to the next entry to read, or NULL of none available
typedef recorder_entry *(*recorder_peek_fn)(void);

/// A function pointer type used by generic code to count readable items.
/// \return the number of recorder entries that can safely be read.
Expand All @@ -138,10 +137,8 @@ typedef struct recorder_info
const char * description;///< Description of what is recorded
struct recorder_info * next; ///< Pointer to next in list

recorder_read_fn read; ///< Read entries
ring_p ring; ///< Pointer to ring for this recorder
recorder_peek_fn peek; ///< Peek first readable entry
recorder_readable_fn readable; ///< Count readable entries
size_t size; ///< Size (maximum number of entries)

struct recorder_chan * exported[4];///< Shared-memory ring export
} recorder_info;
Expand Down Expand Up @@ -194,6 +191,17 @@ extern ringidx_t recorder_##Name##_record(const char *where, \
uintptr_t a2, \
uintptr_t a3); \
\
extern ringidx_t recorder_##Name##_record2(const char *where, \
const char *format, \
uintptr_t a0, \
uintptr_t a1, \
uintptr_t a2, \
uintptr_t a3, \
uintptr_t a4, \
uintptr_t a5, \
uintptr_t a6, \
uintptr_t a7); \
\
extern ringidx_t recorder_##Name##_recfast(const char *where, \
const char *format, \
uintptr_t a0, \
Expand Down Expand Up @@ -229,10 +237,8 @@ RING_DEFINE (recorder_##Name, recorder_entry, Size); \
recorder_info recorder_##Name##_info = \
{ \
0, #Name, Info, NULL, \
(recorder_read_fn) recorder_##Name##_read, \
&recorder_##Name.ring, \
(recorder_peek_fn) recorder_##Name##_peek, \
(recorder_readable_fn) recorder_##Name##_readable, \
Size, \
{ NULL, NULL, NULL, NULL } \
}; \
\
Expand Down Expand Up @@ -274,6 +280,46 @@ ringidx_t recorder_##Name##_record(const char *where, \
} \
\
\
ringidx_t recorder_##Name##_record2(const char *where, \
const char *format, \
uintptr_t a0, \
uintptr_t a1, \
uintptr_t a2, \
uintptr_t a3, \
uintptr_t a4, \
uintptr_t a5, \
uintptr_t a6, \
uintptr_t a7) \
/* ----------------------------------------------------------------*/ \
/* Enter a record entry in ring buffer with given set of args */ \
/* ----------------------------------------------------------------*/ \
{ \
ringidx_t writer = ring_fetch_add(recorder_##Name.ring.writer, 2); \
recorder_entry *entry = &recorder_##Name.data[writer % Size]; \
entry->format = format; \
entry->order = ring_fetch_add(recorder_order, 1); \
entry->timestamp = recorder_tick(); \
entry->where = where; \
entry->args[0] = a0; \
entry->args[1] = a1; \
entry->args[2] = a2; \
entry->args[3] = a3; \
recorder_entry *entry2 = &recorder_##Name.data[(writer+1) % Size]; \
entry2->format = NULL; \
entry2->order = entry->order; \
entry2->timestamp = entry->timestamp; \
entry2->where = where; \
entry2->args[0] = a4; \
entry2->args[1] = a5; \
entry2->args[2] = a6; \
entry2->args[3] = a7; \
ring_fetch_add(recorder_##Name.ring.commit, 2); \
if (recorder_##Name##_info.trace) \
recorder_trace_entry(&recorder_##Name##_info, entry); \
return writer; \
} \
\
\
ringidx_t recorder_##Name##_recfast(const char *where, \
const char *format, \
uintptr_t a0, \
Expand Down Expand Up @@ -331,7 +377,7 @@ static void recorder_##Name##_tweak_activate() \
RECORD__(RECORD,RCOUNT,Name,Format,## __VA_ARGS__)
#define RECORD__(RECORD,RCOUNT,Name,Format,...) \
RECORD##RCOUNT(Name,Format,##__VA_ARGS__)
#define RECORD_COUNT_(...) RECORD_COUNT__(Dummy,##__VA_ARGS__,_X,_X,_X,_X,_X,_X,_4,_3,_2,_1,_0)
#define RECORD_COUNT_(...) RECORD_COUNT__(Dummy,##__VA_ARGS__,_X,_X,_8,_7,_6,_5,_4,_3,_2,_1,_0)
#define RECORD_COUNT__(Dummy,_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_N,...) _N

#define RECORD_0(Name, Format) \
Expand Down Expand Up @@ -359,6 +405,44 @@ static void recorder_##Name##_tweak_activate() \
RECORDER_ARG(b), \
RECORDER_ARG(c), \
RECORDER_ARG(d))
#define RECORD_5(Name, Format, a,b,c,d,e) \
recorder_##Name##_record2(RECORDER_SOURCE_LOCATION, \
Format, \
RECORDER_ARG(a), \
RECORDER_ARG(b), \
RECORDER_ARG(c), \
RECORDER_ARG(d), \
RECORDER_ARG(e), 0, 0, 0)
#define RECORD_6(Name, Format, a,b,c,d,e,f) \
recorder_##Name##_record2(RECORDER_SOURCE_LOCATION, \
Format, \
RECORDER_ARG(a), \
RECORDER_ARG(b), \
RECORDER_ARG(c), \
RECORDER_ARG(d), \
RECORDER_ARG(e), \
RECORDER_ARG(f), 0, 0)
#define RECORD_7(Name, Format, a,b,c,d,e,f,g) \
recorder_##Name##_record2(RECORDER_SOURCE_LOCATION, \
Format, \
RECORDER_ARG(a), \
RECORDER_ARG(b), \
RECORDER_ARG(c), \
RECORDER_ARG(d), \
RECORDER_ARG(e), \
RECORDER_ARG(f), \
RECORDER_ARG(g), 0)
#define RECORD_8(Name, Format, a,b,c,d,e,f,g,h) \
recorder_##Name##_record2(RECORDER_SOURCE_LOCATION, \
Format, \
RECORDER_ARG(a), \
RECORDER_ARG(b), \
RECORDER_ARG(c), \
RECORDER_ARG(d), \
RECORDER_ARG(e), \
RECORDER_ARG(f), \
RECORDER_ARG(g), \
RECORDER_ARG(h))
#define RECORD_X(Name, Format, ...) RECORD_TOO_MANY_ARGS(printf(Format, __VA_ARGS__))

// Faster version that does not record time, about 2x faster on x86
Expand Down Expand Up @@ -389,6 +473,45 @@ static void recorder_##Name##_tweak_activate() \
RECORDER_ARG(b), \
RECORDER_ARG(c), \
RECORDER_ARG(d))
#define RECORD_FAST_5(Name, Format, a,b,c,d,e) \
recorder_##Name##_record2(RECORDER_SOURCE_LOCATION, \
Format, \
RECORDER_ARG(a), \
RECORDER_ARG(b), \
RECORDER_ARG(c), \
RECORDER_ARG(d), \
RECORDER_ARG(e), 0, 0, 0)
#define RECORD_FAST_6(Name, Format, a,b,c,d,e,f) \
recorder_##Name##_record2(RECORDER_SOURCE_LOCATION, \
Format, \
RECORDER_ARG(a), \
RECORDER_ARG(b), \
RECORDER_ARG(c), \
RECORDER_ARG(d), \
RECORDER_ARG(e), \
RECORDER_ARG(f), 0, 0)
#define RECORD_FAST_7(Name, Format, a,b,c,d,e,f,g) \
recorder_##Name##_record2(RECORDER_SOURCE_LOCATION, \
Format, \
RECORDER_ARG(a), \
RECORDER_ARG(b), \
RECORDER_ARG(c), \
RECORDER_ARG(d), \
RECORDER_ARG(e), \
RECORDER_ARG(f), \
RECORDER_ARG(g), 0)
#define RECORD_FAST_8(Name, Format, a,b,c,d,e,f,g,h) \
recorder_##Name##_record2(RECORDER_SOURCE_LOCATION, \
Format, \
RECORDER_ARG(a), \
RECORDER_ARG(b), \
RECORDER_ARG(c), \
RECORDER_ARG(d), \
RECORDER_ARG(e), \
RECORDER_ARG(f), \
RECORDER_ARG(g), \
RECORDER_ARG(h))
#define RECORD_FAST_X(Name, Format, ...) RECORD_TOO_MANY_ARGS(printf(Format, __VA_ARGS__))

// Some ugly macro drudgery to make things easy to use. Adjust type.
#define RECORDER_ARG(arg) \
Expand Down
4 changes: 3 additions & 1 deletion recorder_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ void flight_recorder_test(int argc, char **argv)
{
int i, j;
uintptr_t count = argc >= 2 ? atoi(argv[1]) : 16;
unsigned howLong = argc >= 3 ? atoi(argv[2]) : 10;
unsigned howLong = argc >= 3 ? atoi(argv[2]) : 1;

for (i = 0; i < 2; i++)
{
Expand Down Expand Up @@ -186,6 +186,8 @@ void flight_recorder_test(int argc, char **argv)
RECORD(Special, "Float X 3.1415 = %x", 3.1415f);
RECORD(Special, "Double 3.1415 = %f", 3.1415);
RECORD(Special, "Double X 3.1415 = %x", 3.1415);
RECORD(Special, "Large %d %u %ld %lu %f %s %p %g",
1,2u,3l,4lu,5.0,"six",(void *) 7,8.0);


recorder_dump_for("Special");
Expand Down

0 comments on commit be291f7

Please sign in to comment.