aboutsummaryrefslogtreecommitdiffstats
path: root/mps/code
diff options
context:
space:
mode:
authorRichard Brooksby2012-08-31 16:09:07 +0100
committerRichard Brooksby2012-08-31 16:09:07 +0100
commit7047e27cd12f60df3313a36d62bb8dfb87a3ea5d (patch)
tree132d2f51018b8e2ac4c8a02426ea3a83a59598ef /mps/code
parentbf36f61bb4e9d2d942abde9d12525a0610033f13 (diff)
downloademacs-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.c5
-rw-r--r--mps/code/event.c105
-rw-r--r--mps/code/event.h23
-rw-r--r--mps/code/global.c1
-rw-r--r--mps/code/mpsi.c2
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;
37static Count eventUserCount; 37static Count eventUserCount;
38static Serial EventInternSerial; 38static Serial EventInternSerial;
39 39
40char EventBuffer[EventBufferSIZE]; /* in which events are recorded */ 40/* Buffers in which events are recorded, from the top down. */
41char *EventLast; /* points to last written event */ 41char EventBuffer[EventKindLIMIT][EventBufferSIZE];
42
43/* Pointers to last written event in each buffer. */
44char *EventLast[EventKindLIMIT];
45
42EventControlSet EventKindControl; /* Bit set used to control output. */ 46EventControlSet 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
47Res EventFlush(void) 51Res 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
94failWrite:
95failCreate:
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
87Res EventSync(void) 107void 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)
341void EventDump(mps_lib_FILE *stream) 363void 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 @@
24typedef Word EventStringId; 24typedef Word EventStringId;
25typedef Word EventControlSet; 25typedef Word EventControlSet;
26 26
27extern Res EventSync(void); 27extern void EventSync(void);
28extern Res EventInit(void); 28extern Res EventInit(void);
29extern void EventFinish(void); 29extern void EventFinish(void);
30extern EventControlSet EventControl(EventControlSet resetMask, 30extern EventControlSet EventControl(EventControlSet resetMask,
@@ -32,7 +32,7 @@ extern EventControlSet EventControl(EventControlSet resetMask,
32extern EventStringId EventInternString(const char *label); 32extern EventStringId EventInternString(const char *label);
33extern EventStringId EventInternGenString(size_t, const char *label); 33extern EventStringId EventInternGenString(size_t, const char *label);
34extern void EventLabelAddr(Addr addr, Word id); 34extern void EventLabelAddr(Addr addr, Word id);
35extern Res EventFlush(void); 35extern Res EventFlush(EventKind kind);
36extern Res EventDescribe(Event event, mps_lib_FILE *stream); 36extern Res EventDescribe(Event event, mps_lib_FILE *stream);
37extern Res EventWrite(Event event, mps_lib_FILE *stream); 37extern Res EventWrite(Event event, mps_lib_FILE *stream);
38extern void EventDump(mps_lib_FILE *stream); 38extern 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
45extern char EventBuffer[EventBufferSIZE]; /* in which events are recorded */ 45extern char EventBuffer[EventKindLIMIT][EventBufferSIZE];
46extern char *EventLast; /* points to last written event */ 46extern char *EventLast[EventKindLIMIT];
47extern Word EventKindControl; 47extern 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)
1908void mps_telemetry_flush(void) 1908void 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