/* <code/event.h> -- Event Logging Interface
*
* Copyright (c) 2001-2020 Ravenbrook Limited. See end of file for license.
* $Id: //info.ravenbrook.com/project/mps/master/code/event.h#23 $
*
* READERSHIP
*
* .readership: MPS developers.
*
* DESIGN
*
* .design: <design/telemetry>.
*/
#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 <https://www.ravenbrook.com/>.
*
* 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.
*/