aboutsummaryrefslogtreecommitdiffstats
path: root/mps/code
diff options
context:
space:
mode:
authorRichard Brooksby2012-08-31 13:18:19 +0100
committerRichard Brooksby2012-08-31 13:18:19 +0100
commita7a9ed15ff91778f01d6884ef40a97443f7417a1 (patch)
tree072fb1e2ea73794e4728b5673f3e43bf98f67605 /mps/code
parentfaffc587eb58ffef64be6427739a5cbc28274088 (diff)
downloademacs-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.c50
-rw-r--r--mps/code/event.h15
-rw-r--r--mps/code/eventcnv.c24
-rw-r--r--mps/code/eventcom.h4
-rw-r--r--mps/code/eventdef.h2
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
34static Bool eventInited = FALSE; 34static Bool eventInited = FALSE;
35static mps_io_t eventIO; 35static mps_io_t eventIO;
36static char eventBuffer[EventBufferSIZE];
37static Count eventUserCount; 36static Count eventUserCount;
38static Serial EventInternSerial; 37static Serial EventInternSerial;
39 38
40char *EventNext, *EventLimit; /* Used by macros in <code/event.h> */ 39char EventBuffer[EventBufferSIZE]; /* in which events are recorded */
41EventControlSet EventKindControl; /* Bit set used to control output. */ 40char *EventLast; /* points to last written event */
41EventControlSet 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
41extern char *EventNext, *EventLimit; 41extern char EventBuffer[EventBufferSIZE]; /* in which events are recorded */
42extern char *EventLast; /* points to last written event */
42extern Word EventKindControl; 43extern 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;
55static char style = '\0'; 55static char style = '\0';
56static Bool reportEvents = FALSE; 56static Bool reportEvents = FALSE;
57static Bool eventEnabled[EventCodeMAX+1]; 57static Bool eventEnabled[EventCodeMAX+1];
58static Bool partialLog = FALSE; 58static Bool partialLog = FALSE; /* FIXME: can't read out-of-order labels */
59static Word bucketSize = 0; 59static 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.