1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-03-26 00:34:17 -07:00

Recording events downwards from the top of the buffer so that they can be recovered by a backtrace.

Copied from Perforce
 Change: 179131
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Richard Brooksby 2012-08-31 13:18:19 +01:00
parent 94e9227f38
commit 477d5f3cc2
5 changed files with 58 additions and 37 deletions

View file

@ -33,12 +33,12 @@ SRCID(event, "$Id$");
static Bool eventInited = FALSE;
static mps_io_t eventIO;
static char eventBuffer[EventBufferSIZE];
static Count eventUserCount;
static Serial EventInternSerial;
char *EventNext, *EventLimit; /* Used by macros in <code/event.h> */
EventControlSet EventKindControl; /* Bit set used to control output. */
char EventBuffer[EventBufferSIZE]; /* in which events are recorded */
char *EventLast; /* points to last written event */
EventControlSet EventKindControl; /* Bit set used to control output. */
/* EventFlush -- flush event buffer to the event stream */
@ -47,18 +47,24 @@ Res EventFlush(void)
{
Res res;
size_t size;
AVER(eventInited);
AVER(eventBuffer <= EventNext);
AVER(EventNext <= eventBuffer + EventBufferSIZE);
size = (size_t)(EventNext - eventBuffer);
AVER(EventBuffer <= EventLast);
AVER(EventLast <= EventBuffer + EventBufferSIZE);
size = (size_t)(EventBuffer + EventBufferSIZE - EventLast);
res = (Res)mps_io_write(eventIO, (void *)eventBuffer, size);
EventNext = eventBuffer;
if (res != ResOK) return res;
/* Writing might be faster if the size is aligned to a multiple of the
C library or kernel's buffer size. We could pad out the buffer with
a marker for this purpose. */
return ResOK;
res = (Res)mps_io_write(eventIO, (void *)EventLast, size);
/* Flush the in-memory buffer whether or not we succeeded, so that we can
record recent events there. */
EventLast = EventBuffer + EventBufferSIZE;
return res;
}
@ -98,9 +104,21 @@ Res EventInit(void)
/* Check consistency of the event definitions. These are all compile-time
checks and should get optimised away. */
#define EVENT_PARAM_CHECK_P(name, index, ident)
#define EVENT_PARAM_CHECK_A(name, index, ident)
#define EVENT_PARAM_CHECK_W(name, index, ident)
#define EVENT_PARAM_CHECK_U(name, index, ident)
#define EVENT_PARAM_CHECK_D(name, index, ident)
#define EVENT_PARAM_CHECK_B(name, index, ident)
#define EVENT_PARAM_CHECK_S(name, index, ident) \
AVER(index + 1 == Event##name##ParamLIMIT); /* strings must come last */ \
AVER(offsetof(Event##name##Struct, f##index.str) + EventStringLengthMAX \
<= EventSizeMAX);
#define EVENT_PARAM_CHECK(name, index, sort, ident) \
AVER(index == Event##name##Param##ident); \
AVER(sizeof(EventF##sort) >= 0); /* check existence of type */
AVER(sizeof(EventF##sort) >= 0); /* check existence of type */ \
EVENT_PARAM_CHECK_##sort(name, index, ident)
#define EVENT_CHECK(X, name, code, always, kind) \
AVER(size_tAlignUp(sizeof(Event##name##Struct), MPS_PF_ALIGN) \
@ -114,18 +132,16 @@ Res EventInit(void)
EVENT_##name##_PARAMS(EVENT_PARAM_CHECK, name)
EVENT_LIST(EVENT_CHECK, X)
/* Ensure that no event can be larger than the maximum event size. */
AVER(EventBufferSIZE <= EventSizeMAX);
/* Only if this is the first call. */
if(!eventInited) { /* See .trans.log */
AVER(EventNext == 0);
AVER(EventLimit == 0);
AVER(EventLast == NULL);
res = (Res)mps_io_create(&eventIO);
if(res != ResOK) return res;
EventNext = eventBuffer;
EventLimit = &eventBuffer[EventBufferSIZE];
EventLast = EventBuffer + EventBufferSIZE;
eventUserCount = (Count)1;
eventInited = TRUE;
EventKindControl = (Word)mps_lib_telemetry_control();

View file

@ -38,12 +38,13 @@ extern Res EventFlush(void);
/* Event writing support */
extern char *EventNext, *EventLimit;
extern char EventBuffer[EventBufferSIZE]; /* in which events are recorded */
extern char *EventLast; /* points to last written event */
extern Word EventKindControl;
/* TODO: Append a size at EventNext - sizeof(EventSize) so that a backtrace
can step backwards through the event buffer. */
/* Events are written into the buffer from the top down, so that a backtrace
can find them all starting at EventNext. */
#define EVENT_BEGIN(name, structSize) \
BEGIN \
@ -51,16 +52,16 @@ extern Word EventKindControl;
BS_IS_MEMBER(EventKindControl, (Index)Event##name##Kind)) { \
Event##name##Struct *_event; \
size_t _size = size_tAlignUp(structSize, MPS_PF_ALIGN); \
if (_size > (size_t)(EventLimit - EventNext)) \
if (_size > (size_t)(EventLast - EventBuffer)) \
EventFlush(); \
AVER(_size <= (size_t)(EventLimit - EventNext)); \
_event = (void *)EventNext; \
AVER(_size <= (size_t)(EventLast - EventBuffer)); \
_event = (void *)(EventLast - _size); \
_event->code = Event##name##Code; \
_event->size = (EventSize)_size; \
EVENT_CLOCK(_event->clock);
#define EVENT_END(name, size) \
EventNext += _size; \
EventLast -= _size; \
} \
END

View file

@ -55,7 +55,7 @@ static Bool verbose = FALSE;
static char style = '\0';
static Bool reportEvents = FALSE;
static Bool eventEnabled[EventCodeMAX+1];
static Bool partialLog = FALSE;
static Bool partialLog = FALSE; /* FIXME: can't read out-of-order labels */
static Word bucketSize = 0;
@ -453,24 +453,26 @@ static void readLog(EventProc proc)
if (style == 'L') putchar('(');
switch (style) {
case '\0': case 'L':
EVENT_CLOCK_PRINT(stdout, eventTime);
putchar(' ');
break;
case 'C':
EVENT_CLOCK_PRINT(stdout, eventTime);
fputs(", ", stdout);
break;
}
switch (style) {
case '\0': case 'L': {
printf("%-19s", EventCode2Name(code));
printf("%-19s ", EventCode2Name(code));
} break;
case 'C':
printf("%u", (unsigned)code);
break;
}
switch (style) {
case '\0':
printf(" %8"PRIuLONGEST, (ulongest_t)eventTime); break;
case 'C':
printf(", %"PRIuLONGEST, (ulongest_t)eventTime); break;
case 'L':
printf(" %"PRIXLONGEST, (ulongest_t)eventTime); break;
}
switch (event->any.code) {
case EventLabelCode:

View file

@ -68,7 +68,9 @@ __extension__ typedef unsigned long long EventClock;
END
#define EVENT_CLOCK_PRINT(stream, clock) \
fprintf(stream, "%lu", (unsigned long)clock) /* FIXME: Should be %llu */
fprintf(stream, "%08lX%08lX", /* FIXME: Should be %llu */ \
(unsigned long)((clock) >> 32), \
(unsigned long)(clock))
#endif /* Intel, GCC or Clang */

View file

@ -168,7 +168,7 @@
* - the positional index of the parameter in the list, used to define
* numeric field names using the C preprocessor
* - the parameter sort, similar to writef (Pointer, Addr, Word, Unsigned,
* String, Double)
* String, Double, Bool)
* - a parameter identifier for display or use in code
*
* TODO: Add a doc string to each parameter.