/* -- Event Logging Interface * * Copyright (c) 2001-2020 Ravenbrook Limited. See end of file for license. * $Id$ * * READERSHIP * * .readership: MPS developers. * * DESIGN * * .design: . */ #ifndef event_h #define event_h #include "eventcom.h" #include "mpm.h" #include "eventdef.h" #include "mpslib.h" typedef Word EventStringId; typedef Word EventControlSet; extern void EventSync(void); extern void EventInit(void); extern void EventFinish(void); extern EventControlSet EventControl(EventControlSet resetMask, EventControlSet flipMask); extern EventStringId EventInternString(const char *label); extern EventStringId EventInternGenString(size_t, const char *label); extern void EventLabelAddr(Addr addr, Word id); extern void EventLabelPointer(Pointer pointer, Word id); extern void EventFlush(EventKind kind); extern Res EventDescribe(Event event, mps_lib_FILE *stream, Count depth); extern Res EventWrite(Event event, mps_lib_FILE *stream); extern void EventDump(mps_lib_FILE *stream); #ifdef EVENT /* Event writing support */ extern char EventBuffer[EventKindLIMIT][EventBufferSIZE]; extern char *EventLast[EventKindLIMIT]; extern Word EventKindControl; /* EVENT_BEGIN -- flush buffer if necessary and write event header */ #define EVENT_BEGIN(name, structSize) \ BEGIN \ Event##name##Struct *_event; \ EventKind _kind = Event##name##Kind; \ size_t _size = size_tAlignUp(structSize, EVENT_ALIGN); \ AVER(Event##name##Used); \ if (_size > (size_t)(EventLast[Event##name##Kind] \ - EventBuffer[Event##name##Kind])) \ EventFlush(Event##name##Kind); \ AVER(_size <= (size_t)(EventLast[Event##name##Kind] \ - EventBuffer[Event##name##Kind])); \ _event = (void *)(EventLast[Event##name##Kind] - _size); \ _event->code = Event##name##Code; \ _event->size = (EventSize)_size; \ EVENT_CLOCK(_event->clock); #define EVENT_END \ EventLast[_kind] -= _size; \ END /* EVENTn -- event emitting macros * * The macros EVENT0, EVENT1, etc. are used throughout the MPS to emit an * event with parameters. They work by appending the event parameters to * an event buffer, which is flushed to the telemetry output stream when * full. EVENT2S is a special case that takes a variable length string. */ #define EVENT2S(name, p0, length, string) \ BEGIN \ size_t _string_len = (length); \ size_t size; \ AVER(_string_len <= EventStringLengthMAX); \ size = offsetof(Event##name##Struct, f1) + _string_len + sizeof('\0'); \ EVENT_BEGIN(name, size) \ _event->f0 = (p0); \ (void)mps_lib_memcpy(_event->f1, (string), _string_len); \ _event->f1[_string_len] = '\0'; \ EVENT_END; \ END #define EVENT0 EVENT_RECORD0 #define EVENT1 EVENT_RECORD1 #define EVENT2 EVENT_RECORD2 #define EVENT3 EVENT_RECORD3 #define EVENT4 EVENT_RECORD4 #define EVENT5 EVENT_RECORD5 #define EVENT6 EVENT_RECORD6 #define EVENT7 EVENT_RECORD7 #define EVENT8 EVENT_RECORD8 #define EVENT9 EVENT_RECORD9 #define EVENT10 EVENT_RECORD10 #define EVENT11 EVENT_RECORD11 #define EVENT12 EVENT_RECORD12 #define EVENT13 EVENT_RECORD13 #define EVENT14 EVENT_RECORD14 #else /* !EVENT */ #define EVENT0 EVENT_IGNORE0 #define EVENT1 EVENT_IGNORE1 #define EVENT2 EVENT_IGNORE2 #define EVENT3 EVENT_IGNORE3 #define EVENT4 EVENT_IGNORE4 #define EVENT5 EVENT_IGNORE5 #define EVENT6 EVENT_IGNORE6 #define EVENT7 EVENT_IGNORE7 #define EVENT8 EVENT_IGNORE8 #define EVENT9 EVENT_IGNORE9 #define EVENT10 EVENT_IGNORE10 #define EVENT11 EVENT_IGNORE11 #define EVENT12 EVENT_IGNORE12 #define EVENT13 EVENT_IGNORE13 #define EVENT14 EVENT_IGNORE14 #endif /* !EVENT */ #if EVENT_ALL #define EVENT_CRITICAL0 EVENT0 #define EVENT_CRITICAL1 EVENT1 #define EVENT_CRITICAL2 EVENT2 #define EVENT_CRITICAL3 EVENT3 #define EVENT_CRITICAL4 EVENT4 #define EVENT_CRITICAL5 EVENT5 #define EVENT_CRITICAL6 EVENT6 #define EVENT_CRITICAL7 EVENT7 #define EVENT_CRITICAL8 EVENT8 #define EVENT_CRITICAL9 EVENT9 #define EVENT_CRITICAL10 EVENT10 #define EVENT_CRITICAL11 EVENT11 #define EVENT_CRITICAL12 EVENT12 #define EVENT_CRITICAL13 EVENT13 #define EVENT_CRITICAL14 EVENT14 #else /* !EVENT_ALL */ #define EVENT_CRITICAL0 EVENT_IGNORE0 #define EVENT_CRITICAL1 EVENT_IGNORE1 #define EVENT_CRITICAL2 EVENT_IGNORE2 #define EVENT_CRITICAL3 EVENT_IGNORE3 #define EVENT_CRITICAL4 EVENT_IGNORE4 #define EVENT_CRITICAL5 EVENT_IGNORE5 #define EVENT_CRITICAL6 EVENT_IGNORE6 #define EVENT_CRITICAL7 EVENT_IGNORE7 #define EVENT_CRITICAL8 EVENT_IGNORE8 #define EVENT_CRITICAL9 EVENT_IGNORE9 #define EVENT_CRITICAL10 EVENT_IGNORE10 #define EVENT_CRITICAL11 EVENT_IGNORE11 #define EVENT_CRITICAL12 EVENT_IGNORE12 #define EVENT_CRITICAL13 EVENT_IGNORE13 #define EVENT_CRITICAL14 EVENT_IGNORE14 #endif /* !EVENT_ALL */ /* The following lines were generated with python -c 'for i in range(15): print("#define EVENT_RECORD{i}(name{args}) EVENT_BEGIN(name, sizeof(Event##name##Struct)) {assign} EVENT_END\n#define EVENT_IGNORE{i}(name{args}) BEGIN {unused} END".format(i=i, args="".join(map(", p{}".format, range(i))), assign=" ".join(map("_event->f{0} = (p{0});".format, range(i))), unused=" ".join(map("UNUSED(p{});".format, range(i)))))' */ #define EVENT_RECORD0(name) EVENT_BEGIN(name, sizeof(Event##name##Struct)) EVENT_END #define EVENT_IGNORE0(name) BEGIN END #define EVENT_RECORD1(name, p0) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); EVENT_END #define EVENT_IGNORE1(name, p0) BEGIN UNUSED(p0); END #define EVENT_RECORD2(name, p0, p1) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); EVENT_END #define EVENT_IGNORE2(name, p0, p1) BEGIN UNUSED(p0); UNUSED(p1); END #define EVENT_RECORD3(name, p0, p1, p2) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); EVENT_END #define EVENT_IGNORE3(name, p0, p1, p2) BEGIN UNUSED(p0); UNUSED(p1); UNUSED(p2); END #define EVENT_RECORD4(name, p0, p1, p2, p3) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); EVENT_END #define EVENT_IGNORE4(name, p0, p1, p2, p3) BEGIN UNUSED(p0); UNUSED(p1); UNUSED(p2); UNUSED(p3); END #define EVENT_RECORD5(name, p0, p1, p2, p3, p4) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); _event->f4 = (p4); EVENT_END #define EVENT_IGNORE5(name, p0, p1, p2, p3, p4) BEGIN UNUSED(p0); UNUSED(p1); UNUSED(p2); UNUSED(p3); UNUSED(p4); END #define EVENT_RECORD6(name, p0, p1, p2, p3, p4, p5) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); _event->f4 = (p4); _event->f5 = (p5); EVENT_END #define EVENT_IGNORE6(name, p0, p1, p2, p3, p4, p5) BEGIN UNUSED(p0); UNUSED(p1); UNUSED(p2); UNUSED(p3); UNUSED(p4); UNUSED(p5); END #define EVENT_RECORD7(name, p0, p1, p2, p3, p4, p5, p6) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); _event->f4 = (p4); _event->f5 = (p5); _event->f6 = (p6); EVENT_END #define EVENT_IGNORE7(name, p0, p1, p2, p3, p4, p5, p6) BEGIN UNUSED(p0); UNUSED(p1); UNUSED(p2); UNUSED(p3); UNUSED(p4); UNUSED(p5); UNUSED(p6); END #define EVENT_RECORD8(name, p0, p1, p2, p3, p4, p5, p6, p7) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); _event->f4 = (p4); _event->f5 = (p5); _event->f6 = (p6); _event->f7 = (p7); EVENT_END #define EVENT_IGNORE8(name, p0, p1, p2, p3, p4, p5, p6, p7) BEGIN UNUSED(p0); UNUSED(p1); UNUSED(p2); UNUSED(p3); UNUSED(p4); UNUSED(p5); UNUSED(p6); UNUSED(p7); END #define EVENT_RECORD9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); _event->f4 = (p4); _event->f5 = (p5); _event->f6 = (p6); _event->f7 = (p7); _event->f8 = (p8); EVENT_END #define EVENT_IGNORE9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8) BEGIN UNUSED(p0); UNUSED(p1); UNUSED(p2); UNUSED(p3); UNUSED(p4); UNUSED(p5); UNUSED(p6); UNUSED(p7); UNUSED(p8); END #define EVENT_RECORD10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); _event->f4 = (p4); _event->f5 = (p5); _event->f6 = (p6); _event->f7 = (p7); _event->f8 = (p8); _event->f9 = (p9); EVENT_END #define EVENT_IGNORE10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9) BEGIN UNUSED(p0); UNUSED(p1); UNUSED(p2); UNUSED(p3); UNUSED(p4); UNUSED(p5); UNUSED(p6); UNUSED(p7); UNUSED(p8); UNUSED(p9); END #define EVENT_RECORD11(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); _event->f4 = (p4); _event->f5 = (p5); _event->f6 = (p6); _event->f7 = (p7); _event->f8 = (p8); _event->f9 = (p9); _event->f10 = (p10); EVENT_END #define EVENT_IGNORE11(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) BEGIN UNUSED(p0); UNUSED(p1); UNUSED(p2); UNUSED(p3); UNUSED(p4); UNUSED(p5); UNUSED(p6); UNUSED(p7); UNUSED(p8); UNUSED(p9); UNUSED(p10); END #define EVENT_RECORD12(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); _event->f4 = (p4); _event->f5 = (p5); _event->f6 = (p6); _event->f7 = (p7); _event->f8 = (p8); _event->f9 = (p9); _event->f10 = (p10); _event->f11 = (p11); EVENT_END #define EVENT_IGNORE12(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11) BEGIN UNUSED(p0); UNUSED(p1); UNUSED(p2); UNUSED(p3); UNUSED(p4); UNUSED(p5); UNUSED(p6); UNUSED(p7); UNUSED(p8); UNUSED(p9); UNUSED(p10); UNUSED(p11); END #define EVENT_RECORD13(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); _event->f4 = (p4); _event->f5 = (p5); _event->f6 = (p6); _event->f7 = (p7); _event->f8 = (p8); _event->f9 = (p9); _event->f10 = (p10); _event->f11 = (p11); _event->f12 = (p12); EVENT_END #define EVENT_IGNORE13(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12) BEGIN UNUSED(p0); UNUSED(p1); UNUSED(p2); UNUSED(p3); UNUSED(p4); UNUSED(p5); UNUSED(p6); UNUSED(p7); UNUSED(p8); UNUSED(p9); UNUSED(p10); UNUSED(p11); UNUSED(p12); END #define EVENT_RECORD14(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); _event->f2 = (p2); _event->f3 = (p3); _event->f4 = (p4); _event->f5 = (p5); _event->f6 = (p6); _event->f7 = (p7); _event->f8 = (p8); _event->f9 = (p9); _event->f10 = (p10); _event->f11 = (p11); _event->f12 = (p12); _event->f13 = (p13); EVENT_END #define EVENT_IGNORE14(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13) BEGIN UNUSED(p0); UNUSED(p1); UNUSED(p2); UNUSED(p3); UNUSED(p4); UNUSED(p5); UNUSED(p6); UNUSED(p7); UNUSED(p8); UNUSED(p9); UNUSED(p10); UNUSED(p11); UNUSED(p12); UNUSED(p13); END #endif /* event_h */ /* C. COPYRIGHT AND LICENSE * * Copyright (C) 2001-2020 Ravenbrook Limited . * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */