diff options
| author | Richard Brooksby | 2012-08-31 16:09:07 +0100 |
|---|---|---|
| committer | Richard Brooksby | 2012-08-31 16:09:07 +0100 |
| commit | 7047e27cd12f60df3313a36d62bb8dfb87a3ea5d (patch) | |
| tree | 132d2f51018b8e2ac4c8a02426ea3a83a59598ef /mps/code | |
| parent | bf36f61bb4e9d2d942abde9d12525a0610033f13 (diff) | |
| download | emacs-7047e27cd12f60df3313a36d62bb8dfb87a3ea5d.tar.gz emacs-7047e27cd12f60df3313a36d62bb8dfb87a3ea5d.zip | |
Writing events into separate buffers by kind.
Always recording events into buffers, but only writing them to the telemetry stream if they're enabled.
Copied from Perforce
Change: 179136
ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code')
| -rw-r--r-- | mps/code/arena.c | 5 | ||||
| -rw-r--r-- | mps/code/event.c | 105 | ||||
| -rw-r--r-- | mps/code/event.h | 23 | ||||
| -rw-r--r-- | mps/code/global.c | 1 | ||||
| -rw-r--r-- | mps/code/mpsi.c | 2 |
5 files changed, 83 insertions, 53 deletions
diff --git a/mps/code/arena.c b/mps/code/arena.c index 8a83b26fe5a..d01329dd57d 100644 --- a/mps/code/arena.c +++ b/mps/code/arena.c | |||
| @@ -219,6 +219,11 @@ Res ArenaCreateV(Arena *arenaReturn, ArenaClass class, va_list args) | |||
| 219 | AVER(arenaReturn != NULL); | 219 | AVER(arenaReturn != NULL); |
| 220 | AVERT(ArenaClass, class); | 220 | AVERT(ArenaClass, class); |
| 221 | 221 | ||
| 222 | /* We must initialise the event subsystem very early, because event logging | ||
| 223 | will start as soon as anything interesting happens and expect to write | ||
| 224 | to the EventLast pointers. */ | ||
| 225 | EventInit(); | ||
| 226 | |||
| 222 | /* Do initialization. This will call ArenaInit (see .init.caller). */ | 227 | /* Do initialization. This will call ArenaInit (see .init.caller). */ |
| 223 | res = (*class->init)(&arena, class, args); | 228 | res = (*class->init)(&arena, class, args); |
| 224 | if (res != ResOK) | 229 | if (res != ResOK) |
diff --git a/mps/code/event.c b/mps/code/event.c index 7657e71cc37..9018e8e9b33 100644 --- a/mps/code/event.c +++ b/mps/code/event.c | |||
| @@ -37,46 +37,66 @@ static mps_io_t eventIO; | |||
| 37 | static Count eventUserCount; | 37 | static Count eventUserCount; |
| 38 | static Serial EventInternSerial; | 38 | static Serial EventInternSerial; |
| 39 | 39 | ||
| 40 | char EventBuffer[EventBufferSIZE]; /* in which events are recorded */ | 40 | /* Buffers in which events are recorded, from the top down. */ |
| 41 | char *EventLast; /* points to last written event */ | 41 | char EventBuffer[EventKindLIMIT][EventBufferSIZE]; |
| 42 | |||
| 43 | /* Pointers to last written event in each buffer. */ | ||
| 44 | char *EventLast[EventKindLIMIT]; | ||
| 45 | |||
| 42 | EventControlSet EventKindControl; /* Bit set used to control output. */ | 46 | EventControlSet EventKindControl; /* Bit set used to control output. */ |
| 43 | 47 | ||
| 44 | 48 | ||
| 45 | /* EventFlush -- flush event buffer to the event stream */ | 49 | /* EventFlush -- flush event buffer to the event stream */ |
| 46 | 50 | ||
| 47 | Res EventFlush(void) | 51 | Res EventFlush(EventKind kind) |
| 48 | { | 52 | { |
| 49 | Res res; | 53 | Res res; |
| 50 | size_t size; | 54 | size_t size; |
| 51 | 55 | ||
| 52 | AVER(eventInited); | 56 | AVER(eventInited); |
| 57 | AVER(0 <= kind && kind < EventKindLIMIT); | ||
| 53 | 58 | ||
| 54 | AVER(EventBuffer <= EventLast); | 59 | AVER(EventBuffer[kind] <= EventLast[kind]); |
| 55 | AVER(EventLast <= EventBuffer + EventBufferSIZE); | 60 | AVER(EventLast[kind] <= EventBuffer[kind] + EventBufferSIZE); |
| 56 | size = (size_t)(EventBuffer + EventBufferSIZE - EventLast); | ||
| 57 | |||
| 58 | /* Checking the size avoids creating the event stream when the arena is | ||
| 59 | destroyed and no events have been logged. */ | ||
| 60 | if (size == 0) | ||
| 61 | return ResOK; | ||
| 62 | |||
| 63 | /* Ensure the IO stream is open. We do this late so that no stream is | ||
| 64 | created if no events are enabled by telemetry control. */ | ||
| 65 | if (!eventIOInited) { | ||
| 66 | res = (Res)mps_io_create(&eventIO); | ||
| 67 | if(res != ResOK) return res; | ||
| 68 | eventIOInited = TRUE; | ||
| 69 | } | ||
| 70 | 61 | ||
| 71 | /* Writing might be faster if the size is aligned to a multiple of the | 62 | /* Is event logging enabled for this kind of event, or are or are we just |
| 72 | C library or kernel's buffer size. We could pad out the buffer with | 63 | writing to the buffer for backtraces, cores, and other debugging? */ |
| 73 | a marker for this purpose. */ | 64 | if (BS_IS_MEMBER(EventKindControl, kind)) { |
| 65 | |||
| 66 | size = (size_t)(EventBuffer[kind] + EventBufferSIZE - EventLast[kind]); | ||
| 67 | |||
| 68 | /* Checking the size avoids creating the event stream when the arena is | ||
| 69 | destroyed and no events have been logged. */ | ||
| 70 | if (size == 0) | ||
| 71 | return ResOK; | ||
| 72 | |||
| 73 | /* Ensure the IO stream is open. We do this late so that no stream is | ||
| 74 | created if no events are enabled by telemetry control. */ | ||
| 75 | if (!eventIOInited) { | ||
| 76 | res = (Res)mps_io_create(&eventIO); | ||
| 77 | if(res != ResOK) | ||
| 78 | goto failCreate; | ||
| 79 | eventIOInited = TRUE; | ||
| 80 | } | ||
| 81 | |||
| 82 | /* Writing might be faster if the size is aligned to a multiple of the | ||
| 83 | C library or kernel's buffer size. We could pad out the buffer with | ||
| 84 | a marker for this purpose. */ | ||
| 85 | |||
| 86 | res = (Res)mps_io_write(eventIO, (void *)EventLast[kind], size); | ||
| 87 | if (res != ResOK) | ||
| 88 | goto failWrite; | ||
| 74 | 89 | ||
| 75 | res = (Res)mps_io_write(eventIO, (void *)EventLast, size); | 90 | } |
| 91 | |||
| 92 | res = ResOK; | ||
| 93 | |||
| 94 | failWrite: | ||
| 95 | failCreate: | ||
| 76 | 96 | ||
| 77 | /* Flush the in-memory buffer whether or not we succeeded, so that we can | 97 | /* Flush the in-memory buffer whether or not we succeeded, so that we can |
| 78 | record recent events there. */ | 98 | record recent events there. */ |
| 79 | EventLast = EventBuffer + EventBufferSIZE; | 99 | EventLast[kind] = EventBuffer[kind] + EventBufferSIZE; |
| 80 | 100 | ||
| 81 | return res; | 101 | return res; |
| 82 | } | 102 | } |
| @@ -84,13 +104,12 @@ Res EventFlush(void) | |||
| 84 | 104 | ||
| 85 | /* EventSync -- synchronize the event stream with the buffers */ | 105 | /* EventSync -- synchronize the event stream with the buffers */ |
| 86 | 106 | ||
| 87 | Res EventSync(void) | 107 | void EventSync(void) |
| 88 | { | 108 | { |
| 89 | Res resEv, resIO; | 109 | EventKind kind; |
| 90 | 110 | for (kind = 0; kind < EventKindLIMIT; ++kind) | |
| 91 | resEv = EventFlush(); | 111 | (void)EventFlush(kind); |
| 92 | resIO = mps_io_flush(eventIO); | 112 | (void)mps_io_flush(eventIO); |
| 93 | return (resEv != ResOK) ? resEv : resIO; | ||
| 94 | } | 113 | } |
| 95 | 114 | ||
| 96 | 115 | ||
| @@ -152,8 +171,11 @@ Res EventInit(void) | |||
| 152 | 171 | ||
| 153 | /* Only if this is the first call. */ | 172 | /* Only if this is the first call. */ |
| 154 | if(!eventInited) { /* See .trans.log */ | 173 | if(!eventInited) { /* See .trans.log */ |
| 155 | AVER(EventLast == NULL); | 174 | EventKind kind; |
| 156 | EventLast = EventBuffer + EventBufferSIZE; | 175 | for (kind = 0; kind < EventKindLIMIT; ++kind) { |
| 176 | AVER(EventLast[kind] == NULL); | ||
| 177 | EventLast[kind] = EventBuffer[kind] + EventBufferSIZE; | ||
| 178 | } | ||
| 157 | eventUserCount = (Count)1; | 179 | eventUserCount = (Count)1; |
| 158 | eventInited = TRUE; | 180 | eventInited = TRUE; |
| 159 | EventKindControl = (Word)mps_lib_telemetry_control(); | 181 | EventKindControl = (Word)mps_lib_telemetry_control(); |
| @@ -174,7 +196,7 @@ void EventFinish(void) | |||
| 174 | AVER(eventInited); | 196 | AVER(eventInited); |
| 175 | AVER(eventUserCount > 0); | 197 | AVER(eventUserCount > 0); |
| 176 | 198 | ||
| 177 | (void)EventSync(); | 199 | EventSync(); |
| 178 | 200 | ||
| 179 | --eventUserCount; | 201 | --eventUserCount; |
| 180 | } | 202 | } |
| @@ -341,16 +363,19 @@ Res EventWrite(Event event, mps_lib_FILE *stream) | |||
| 341 | void EventDump(mps_lib_FILE *stream) | 363 | void EventDump(mps_lib_FILE *stream) |
| 342 | { | 364 | { |
| 343 | Event event; | 365 | Event event; |
| 366 | EventKind kind; | ||
| 344 | 367 | ||
| 345 | AVER(stream != NULL); | 368 | AVER(stream != NULL); |
| 346 | 369 | ||
| 347 | for (event = (Event)EventLast; | 370 | for (kind = 0; kind < EventKindLIMIT; ++kind) { |
| 348 | event < (Event)(EventBuffer + EventBufferSIZE); | 371 | for (event = (Event)EventLast[kind]; |
| 349 | event = (Event)((char *)event + event->any.size)) { | 372 | event < (Event)(EventBuffer[kind] + EventBufferSIZE); |
| 350 | /* Try to keep going even if there's an error, because this is used as a | 373 | event = (Event)((char *)event + event->any.size)) { |
| 351 | backtrace and we'll take what we can get. */ | 374 | /* Try to keep going even if there's an error, because this is used as a |
| 352 | (void)EventWrite(event, stream); | 375 | backtrace and we'll take what we can get. */ |
| 353 | (void)WriteF(stream, "\n", NULL); | 376 | (void)EventWrite(event, stream); |
| 377 | (void)WriteF(stream, "\n", NULL); | ||
| 378 | } | ||
| 354 | } | 379 | } |
| 355 | } | 380 | } |
| 356 | 381 | ||
diff --git a/mps/code/event.h b/mps/code/event.h index 7d02b947d3e..4694dc820c0 100644 --- a/mps/code/event.h +++ b/mps/code/event.h | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | typedef Word EventStringId; | 24 | typedef Word EventStringId; |
| 25 | typedef Word EventControlSet; | 25 | typedef Word EventControlSet; |
| 26 | 26 | ||
| 27 | extern Res EventSync(void); | 27 | extern void EventSync(void); |
| 28 | extern Res EventInit(void); | 28 | extern Res EventInit(void); |
| 29 | extern void EventFinish(void); | 29 | extern void EventFinish(void); |
| 30 | extern EventControlSet EventControl(EventControlSet resetMask, | 30 | extern EventControlSet EventControl(EventControlSet resetMask, |
| @@ -32,7 +32,7 @@ extern EventControlSet EventControl(EventControlSet resetMask, | |||
| 32 | extern EventStringId EventInternString(const char *label); | 32 | extern EventStringId EventInternString(const char *label); |
| 33 | extern EventStringId EventInternGenString(size_t, const char *label); | 33 | extern EventStringId EventInternGenString(size_t, const char *label); |
| 34 | extern void EventLabelAddr(Addr addr, Word id); | 34 | extern void EventLabelAddr(Addr addr, Word id); |
| 35 | extern Res EventFlush(void); | 35 | extern Res EventFlush(EventKind kind); |
| 36 | extern Res EventDescribe(Event event, mps_lib_FILE *stream); | 36 | extern Res EventDescribe(Event event, mps_lib_FILE *stream); |
| 37 | extern Res EventWrite(Event event, mps_lib_FILE *stream); | 37 | extern Res EventWrite(Event event, mps_lib_FILE *stream); |
| 38 | extern void EventDump(mps_lib_FILE *stream); | 38 | extern void EventDump(mps_lib_FILE *stream); |
| @@ -42,8 +42,8 @@ extern void EventDump(mps_lib_FILE *stream); | |||
| 42 | 42 | ||
| 43 | /* Event writing support */ | 43 | /* Event writing support */ |
| 44 | 44 | ||
| 45 | extern char EventBuffer[EventBufferSIZE]; /* in which events are recorded */ | 45 | extern char EventBuffer[EventKindLIMIT][EventBufferSIZE]; |
| 46 | extern char *EventLast; /* points to last written event */ | 46 | extern char *EventLast[EventKindLIMIT]; |
| 47 | extern Word EventKindControl; | 47 | extern Word EventKindControl; |
| 48 | 48 | ||
| 49 | 49 | ||
| @@ -52,20 +52,21 @@ extern Word EventKindControl; | |||
| 52 | 52 | ||
| 53 | #define EVENT_BEGIN(name, structSize) \ | 53 | #define EVENT_BEGIN(name, structSize) \ |
| 54 | BEGIN \ | 54 | BEGIN \ |
| 55 | if(/* Event##name##Always && FIXME: depend on variety */ \ | 55 | if(Event##name##Always) { /* FIXME: depend on variety */ \ |
| 56 | BS_IS_MEMBER(EventKindControl, (Index)Event##name##Kind)) { \ | ||
| 57 | Event##name##Struct *_event; \ | 56 | Event##name##Struct *_event; \ |
| 58 | size_t _size = size_tAlignUp(structSize, MPS_PF_ALIGN); \ | 57 | size_t _size = size_tAlignUp(structSize, MPS_PF_ALIGN); \ |
| 59 | if (_size > (size_t)(EventLast - EventBuffer)) \ | 58 | if (_size > (size_t)(EventLast[Event##name##Kind] \ |
| 60 | EventFlush(); \ | 59 | - EventBuffer[Event##name##Kind])) \ |
| 61 | AVER(_size <= (size_t)(EventLast - EventBuffer)); \ | 60 | EventFlush(Event##name##Kind); \ |
| 62 | _event = (void *)(EventLast - _size); \ | 61 | AVER(_size <= (size_t)(EventLast[Event##name##Kind] \ |
| 62 | - EventBuffer[Event##name##Kind])); \ | ||
| 63 | _event = (void *)(EventLast[Event##name##Kind] - _size); \ | ||
| 63 | _event->code = Event##name##Code; \ | 64 | _event->code = Event##name##Code; \ |
| 64 | _event->size = (EventSize)_size; \ | 65 | _event->size = (EventSize)_size; \ |
| 65 | EVENT_CLOCK(_event->clock); | 66 | EVENT_CLOCK(_event->clock); |
| 66 | 67 | ||
| 67 | #define EVENT_END(name, size) \ | 68 | #define EVENT_END(name, size) \ |
| 68 | EventLast -= _size; \ | 69 | EventLast[Event##name##Kind] -= _size; \ |
| 69 | } \ | 70 | } \ |
| 70 | END | 71 | END |
| 71 | 72 | ||
diff --git a/mps/code/global.c b/mps/code/global.c index 9f06af73cca..bb666f4e44b 100644 --- a/mps/code/global.c +++ b/mps/code/global.c | |||
| @@ -239,7 +239,6 @@ Res GlobalsInit(Globals arenaGlobals) | |||
| 239 | RingInit(&arenaRing); | 239 | RingInit(&arenaRing); |
| 240 | ProtSetup(); | 240 | ProtSetup(); |
| 241 | } | 241 | } |
| 242 | EventInit(); | ||
| 243 | arenaReleaseRingLock(); | 242 | arenaReleaseRingLock(); |
| 244 | 243 | ||
| 245 | arena = GlobalsArena(arenaGlobals); | 244 | arena = GlobalsArena(arenaGlobals); |
diff --git a/mps/code/mpsi.c b/mps/code/mpsi.c index 3a356f5d50a..8bf0aee3af2 100644 --- a/mps/code/mpsi.c +++ b/mps/code/mpsi.c | |||
| @@ -1908,7 +1908,7 @@ void mps_telemetry_label(mps_addr_t addr, mps_word_t intern_id) | |||
| 1908 | void mps_telemetry_flush(void) | 1908 | void mps_telemetry_flush(void) |
| 1909 | { | 1909 | { |
| 1910 | /* Telemetry does its own concurrency control, so none here. */ | 1910 | /* Telemetry does its own concurrency control, so none here. */ |
| 1911 | (void)EventSync(); | 1911 | EventSync(); |
| 1912 | } | 1912 | } |
| 1913 | 1913 | ||
| 1914 | 1914 | ||