diff options
| author | Richard Brooksby | 2012-08-31 13:18:19 +0100 |
|---|---|---|
| committer | Richard Brooksby | 2012-08-31 13:18:19 +0100 |
| commit | a7a9ed15ff91778f01d6884ef40a97443f7417a1 (patch) | |
| tree | 072fb1e2ea73794e4728b5673f3e43bf98f67605 /mps/code | |
| parent | faffc587eb58ffef64be6427739a5cbc28274088 (diff) | |
| download | emacs-a7a9ed15ff91778f01d6884ef40a97443f7417a1.tar.gz emacs-a7a9ed15ff91778f01d6884ef40a97443f7417a1.zip | |
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
Diffstat (limited to 'mps/code')
| -rw-r--r-- | mps/code/event.c | 50 | ||||
| -rw-r--r-- | mps/code/event.h | 15 | ||||
| -rw-r--r-- | mps/code/eventcnv.c | 24 | ||||
| -rw-r--r-- | mps/code/eventcom.h | 4 | ||||
| -rw-r--r-- | mps/code/eventdef.h | 2 |
5 files changed, 58 insertions, 37 deletions
diff --git a/mps/code/event.c b/mps/code/event.c index b97714f62b4..d3ea72277fc 100644 --- a/mps/code/event.c +++ b/mps/code/event.c | |||
| @@ -33,12 +33,12 @@ SRCID(event, "$Id$"); | |||
| 33 | 33 | ||
| 34 | static Bool eventInited = FALSE; | 34 | static Bool eventInited = FALSE; |
| 35 | static mps_io_t eventIO; | 35 | static mps_io_t eventIO; |
| 36 | static char eventBuffer[EventBufferSIZE]; | ||
| 37 | static Count eventUserCount; | 36 | static Count eventUserCount; |
| 38 | static Serial EventInternSerial; | 37 | static Serial EventInternSerial; |
| 39 | 38 | ||
| 40 | char *EventNext, *EventLimit; /* Used by macros in <code/event.h> */ | 39 | char EventBuffer[EventBufferSIZE]; /* in which events are recorded */ |
| 41 | EventControlSet EventKindControl; /* Bit set used to control output. */ | 40 | char *EventLast; /* points to last written event */ |
| 41 | EventControlSet EventKindControl; /* Bit set used to control output. */ | ||
| 42 | 42 | ||
| 43 | 43 | ||
| 44 | /* EventFlush -- flush event buffer to the event stream */ | 44 | /* EventFlush -- flush event buffer to the event stream */ |
| @@ -47,18 +47,24 @@ Res EventFlush(void) | |||
| 47 | { | 47 | { |
| 48 | Res res; | 48 | Res res; |
| 49 | size_t size; | 49 | size_t size; |
| 50 | 50 | ||
| 51 | AVER(eventInited); | 51 | AVER(eventInited); |
| 52 | 52 | ||
| 53 | AVER(eventBuffer <= EventNext); | 53 | AVER(EventBuffer <= EventLast); |
| 54 | AVER(EventNext <= eventBuffer + EventBufferSIZE); | 54 | AVER(EventLast <= EventBuffer + EventBufferSIZE); |
| 55 | size = (size_t)(EventNext - eventBuffer); | 55 | size = (size_t)(EventBuffer + EventBufferSIZE - EventLast); |
| 56 | 56 | ||
| 57 | res = (Res)mps_io_write(eventIO, (void *)eventBuffer, size); | 57 | /* Writing might be faster if the size is aligned to a multiple of the |
| 58 | EventNext = eventBuffer; | 58 | C library or kernel's buffer size. We could pad out the buffer with |
| 59 | if (res != ResOK) return res; | 59 | a marker for this purpose. */ |
| 60 | 60 | ||
| 61 | return ResOK; | 61 | res = (Res)mps_io_write(eventIO, (void *)EventLast, size); |
| 62 | |||
| 63 | /* Flush the in-memory buffer whether or not we succeeded, so that we can | ||
| 64 | record recent events there. */ | ||
| 65 | EventLast = EventBuffer + EventBufferSIZE; | ||
| 66 | |||
| 67 | return res; | ||
| 62 | } | 68 | } |
| 63 | 69 | ||
| 64 | 70 | ||
| @@ -98,9 +104,21 @@ Res EventInit(void) | |||
| 98 | /* Check consistency of the event definitions. These are all compile-time | 104 | /* Check consistency of the event definitions. These are all compile-time |
| 99 | checks and should get optimised away. */ | 105 | checks and should get optimised away. */ |
| 100 | 106 | ||
| 107 | #define EVENT_PARAM_CHECK_P(name, index, ident) | ||
| 108 | #define EVENT_PARAM_CHECK_A(name, index, ident) | ||
| 109 | #define EVENT_PARAM_CHECK_W(name, index, ident) | ||
| 110 | #define EVENT_PARAM_CHECK_U(name, index, ident) | ||
| 111 | #define EVENT_PARAM_CHECK_D(name, index, ident) | ||
| 112 | #define EVENT_PARAM_CHECK_B(name, index, ident) | ||
| 113 | #define EVENT_PARAM_CHECK_S(name, index, ident) \ | ||
| 114 | AVER(index + 1 == Event##name##ParamLIMIT); /* strings must come last */ \ | ||
| 115 | AVER(offsetof(Event##name##Struct, f##index.str) + EventStringLengthMAX \ | ||
| 116 | <= EventSizeMAX); | ||
| 117 | |||
| 101 | #define EVENT_PARAM_CHECK(name, index, sort, ident) \ | 118 | #define EVENT_PARAM_CHECK(name, index, sort, ident) \ |
| 102 | AVER(index == Event##name##Param##ident); \ | 119 | AVER(index == Event##name##Param##ident); \ |
| 103 | AVER(sizeof(EventF##sort) >= 0); /* check existence of type */ | 120 | AVER(sizeof(EventF##sort) >= 0); /* check existence of type */ \ |
| 121 | EVENT_PARAM_CHECK_##sort(name, index, ident) | ||
| 104 | 122 | ||
| 105 | #define EVENT_CHECK(X, name, code, always, kind) \ | 123 | #define EVENT_CHECK(X, name, code, always, kind) \ |
| 106 | AVER(size_tAlignUp(sizeof(Event##name##Struct), MPS_PF_ALIGN) \ | 124 | AVER(size_tAlignUp(sizeof(Event##name##Struct), MPS_PF_ALIGN) \ |
| @@ -114,18 +132,16 @@ Res EventInit(void) | |||
| 114 | EVENT_##name##_PARAMS(EVENT_PARAM_CHECK, name) | 132 | EVENT_##name##_PARAMS(EVENT_PARAM_CHECK, name) |
| 115 | 133 | ||
| 116 | EVENT_LIST(EVENT_CHECK, X) | 134 | EVENT_LIST(EVENT_CHECK, X) |
| 117 | 135 | ||
| 118 | /* Ensure that no event can be larger than the maximum event size. */ | 136 | /* Ensure that no event can be larger than the maximum event size. */ |
| 119 | AVER(EventBufferSIZE <= EventSizeMAX); | 137 | AVER(EventBufferSIZE <= EventSizeMAX); |
| 120 | 138 | ||
| 121 | /* Only if this is the first call. */ | 139 | /* Only if this is the first call. */ |
| 122 | if(!eventInited) { /* See .trans.log */ | 140 | if(!eventInited) { /* See .trans.log */ |
| 123 | AVER(EventNext == 0); | 141 | AVER(EventLast == NULL); |
| 124 | AVER(EventLimit == 0); | ||
| 125 | res = (Res)mps_io_create(&eventIO); | 142 | res = (Res)mps_io_create(&eventIO); |
| 126 | if(res != ResOK) return res; | 143 | if(res != ResOK) return res; |
| 127 | EventNext = eventBuffer; | 144 | EventLast = EventBuffer + EventBufferSIZE; |
| 128 | EventLimit = &eventBuffer[EventBufferSIZE]; | ||
| 129 | eventUserCount = (Count)1; | 145 | eventUserCount = (Count)1; |
| 130 | eventInited = TRUE; | 146 | eventInited = TRUE; |
| 131 | EventKindControl = (Word)mps_lib_telemetry_control(); | 147 | EventKindControl = (Word)mps_lib_telemetry_control(); |
diff --git a/mps/code/event.h b/mps/code/event.h index 9af0225d7fd..d4c2ce83b95 100644 --- a/mps/code/event.h +++ b/mps/code/event.h | |||
| @@ -38,12 +38,13 @@ extern Res EventFlush(void); | |||
| 38 | 38 | ||
| 39 | /* Event writing support */ | 39 | /* Event writing support */ |
| 40 | 40 | ||
| 41 | extern char *EventNext, *EventLimit; | 41 | extern char EventBuffer[EventBufferSIZE]; /* in which events are recorded */ |
| 42 | extern char *EventLast; /* points to last written event */ | ||
| 42 | extern Word EventKindControl; | 43 | extern Word EventKindControl; |
| 43 | 44 | ||
| 44 | 45 | ||
| 45 | /* TODO: Append a size at EventNext - sizeof(EventSize) so that a backtrace | 46 | /* Events are written into the buffer from the top down, so that a backtrace |
| 46 | can step backwards through the event buffer. */ | 47 | can find them all starting at EventNext. */ |
| 47 | 48 | ||
| 48 | #define EVENT_BEGIN(name, structSize) \ | 49 | #define EVENT_BEGIN(name, structSize) \ |
| 49 | BEGIN \ | 50 | BEGIN \ |
| @@ -51,16 +52,16 @@ extern Word EventKindControl; | |||
| 51 | BS_IS_MEMBER(EventKindControl, (Index)Event##name##Kind)) { \ | 52 | BS_IS_MEMBER(EventKindControl, (Index)Event##name##Kind)) { \ |
| 52 | Event##name##Struct *_event; \ | 53 | Event##name##Struct *_event; \ |
| 53 | size_t _size = size_tAlignUp(structSize, MPS_PF_ALIGN); \ | 54 | size_t _size = size_tAlignUp(structSize, MPS_PF_ALIGN); \ |
| 54 | if (_size > (size_t)(EventLimit - EventNext)) \ | 55 | if (_size > (size_t)(EventLast - EventBuffer)) \ |
| 55 | EventFlush(); \ | 56 | EventFlush(); \ |
| 56 | AVER(_size <= (size_t)(EventLimit - EventNext)); \ | 57 | AVER(_size <= (size_t)(EventLast - EventBuffer)); \ |
| 57 | _event = (void *)EventNext; \ | 58 | _event = (void *)(EventLast - _size); \ |
| 58 | _event->code = Event##name##Code; \ | 59 | _event->code = Event##name##Code; \ |
| 59 | _event->size = (EventSize)_size; \ | 60 | _event->size = (EventSize)_size; \ |
| 60 | EVENT_CLOCK(_event->clock); | 61 | EVENT_CLOCK(_event->clock); |
| 61 | 62 | ||
| 62 | #define EVENT_END(name, size) \ | 63 | #define EVENT_END(name, size) \ |
| 63 | EventNext += _size; \ | 64 | EventLast -= _size; \ |
| 64 | } \ | 65 | } \ |
| 65 | END | 66 | END |
| 66 | 67 | ||
diff --git a/mps/code/eventcnv.c b/mps/code/eventcnv.c index c5a436d1df9..ffdad909ad6 100644 --- a/mps/code/eventcnv.c +++ b/mps/code/eventcnv.c | |||
| @@ -55,7 +55,7 @@ static Bool verbose = FALSE; | |||
| 55 | static char style = '\0'; | 55 | static char style = '\0'; |
| 56 | static Bool reportEvents = FALSE; | 56 | static Bool reportEvents = FALSE; |
| 57 | static Bool eventEnabled[EventCodeMAX+1]; | 57 | static Bool eventEnabled[EventCodeMAX+1]; |
| 58 | static Bool partialLog = FALSE; | 58 | static Bool partialLog = FALSE; /* FIXME: can't read out-of-order labels */ |
| 59 | static Word bucketSize = 0; | 59 | static Word bucketSize = 0; |
| 60 | 60 | ||
| 61 | 61 | ||
| @@ -454,23 +454,25 @@ static void readLog(EventProc proc) | |||
| 454 | if (style == 'L') putchar('('); | 454 | if (style == 'L') putchar('('); |
| 455 | 455 | ||
| 456 | switch (style) { | 456 | switch (style) { |
| 457 | case '\0': case 'L': | ||
| 458 | EVENT_CLOCK_PRINT(stdout, eventTime); | ||
| 459 | putchar(' '); | ||
| 460 | break; | ||
| 461 | case 'C': | ||
| 462 | EVENT_CLOCK_PRINT(stdout, eventTime); | ||
| 463 | fputs(", ", stdout); | ||
| 464 | break; | ||
| 465 | } | ||
| 466 | |||
| 467 | switch (style) { | ||
| 457 | case '\0': case 'L': { | 468 | case '\0': case 'L': { |
| 458 | printf("%-19s", EventCode2Name(code)); | 469 | printf("%-19s ", EventCode2Name(code)); |
| 459 | } break; | 470 | } break; |
| 460 | case 'C': | 471 | case 'C': |
| 461 | printf("%u", (unsigned)code); | 472 | printf("%u", (unsigned)code); |
| 462 | break; | 473 | break; |
| 463 | } | 474 | } |
| 464 | 475 | ||
| 465 | switch (style) { | ||
| 466 | case '\0': | ||
| 467 | printf(" %8"PRIuLONGEST, (ulongest_t)eventTime); break; | ||
| 468 | case 'C': | ||
| 469 | printf(", %"PRIuLONGEST, (ulongest_t)eventTime); break; | ||
| 470 | case 'L': | ||
| 471 | printf(" %"PRIXLONGEST, (ulongest_t)eventTime); break; | ||
| 472 | } | ||
| 473 | |||
| 474 | switch (event->any.code) { | 476 | switch (event->any.code) { |
| 475 | 477 | ||
| 476 | case EventLabelCode: | 478 | case EventLabelCode: |
diff --git a/mps/code/eventcom.h b/mps/code/eventcom.h index d5e3959d72c..d572c56bdc8 100644 --- a/mps/code/eventcom.h +++ b/mps/code/eventcom.h | |||
| @@ -68,7 +68,9 @@ __extension__ typedef unsigned long long EventClock; | |||
| 68 | END | 68 | END |
| 69 | 69 | ||
| 70 | #define EVENT_CLOCK_PRINT(stream, clock) \ | 70 | #define EVENT_CLOCK_PRINT(stream, clock) \ |
| 71 | fprintf(stream, "%lu", (unsigned long)clock) /* FIXME: Should be %llu */ | 71 | fprintf(stream, "%08lX%08lX", /* FIXME: Should be %llu */ \ |
| 72 | (unsigned long)((clock) >> 32), \ | ||
| 73 | (unsigned long)(clock)) | ||
| 72 | 74 | ||
| 73 | #endif /* Intel, GCC or Clang */ | 75 | #endif /* Intel, GCC or Clang */ |
| 74 | 76 | ||
diff --git a/mps/code/eventdef.h b/mps/code/eventdef.h index 77a1269369b..27bb3bb6320 100644 --- a/mps/code/eventdef.h +++ b/mps/code/eventdef.h | |||
| @@ -168,7 +168,7 @@ | |||
| 168 | * - the positional index of the parameter in the list, used to define | 168 | * - the positional index of the parameter in the list, used to define |
| 169 | * numeric field names using the C preprocessor | 169 | * numeric field names using the C preprocessor |
| 170 | * - the parameter sort, similar to writef (Pointer, Addr, Word, Unsigned, | 170 | * - the parameter sort, similar to writef (Pointer, Addr, Word, Unsigned, |
| 171 | * String, Double) | 171 | * String, Double, Bool) |
| 172 | * - a parameter identifier for display or use in code | 172 | * - a parameter identifier for display or use in code |
| 173 | * | 173 | * |
| 174 | * TODO: Add a doc string to each parameter. | 174 | * TODO: Add a doc string to each parameter. |