mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-03-26 08:41:47 -07:00
Remove diag facility.
Copied from Perforce Change: 182553 ServerID: perforce.ravenbrook.com
This commit is contained in:
parent
ad35f3cac3
commit
4e22988865
18 changed files with 208 additions and 1422 deletions
|
|
@ -1135,12 +1135,7 @@ static Res vmArenaExtend(VMArena vmArena, Size size)
|
|||
} while(0);
|
||||
|
||||
EVENT3(vmArenaExtendStart, size, chunkSize,
|
||||
VMArenaReserved(VMArena2Arena(vmArena)));
|
||||
DIAG_SINGLEF(( "vmArenaExtend_Start",
|
||||
"to accommodate size $W, try chunkSize $W", (WriteFW)size, (WriteFW)chunkSize,
|
||||
" (VMArenaReserved currently $W bytes)\n",
|
||||
(WriteFW)VMArenaReserved(VMArena2Arena(vmArena)),
|
||||
NULL ));
|
||||
VMArenaReserved(VMArena2Arena(vmArena)));
|
||||
|
||||
/* .chunk-create.fail: If we fail, try again with a smaller size */
|
||||
{
|
||||
|
|
@ -1163,12 +1158,7 @@ static Res vmArenaExtend(VMArena vmArena, Size size)
|
|||
for(; chunkSize > chunkHalf; chunkSize -= sliceSize) {
|
||||
if(chunkSize < chunkMin) {
|
||||
EVENT2(vmArenaExtendFail, chunkMin,
|
||||
VMArenaReserved(VMArena2Arena(vmArena)));
|
||||
DIAG_SINGLEF(( "vmArenaExtend_FailMin",
|
||||
"no remaining address-space chunk >= min($W)", (WriteFW)chunkMin,
|
||||
" (so VMArenaReserved remains $W bytes)\n",
|
||||
(WriteFW)VMArenaReserved(VMArena2Arena(vmArena)),
|
||||
NULL ));
|
||||
VMArenaReserved(VMArena2Arena(vmArena)));
|
||||
return ResRESOURCE;
|
||||
}
|
||||
res = VMChunkCreate(&newChunk, vmArena, chunkSize);
|
||||
|
|
@ -1179,14 +1169,7 @@ static Res vmArenaExtend(VMArena vmArena, Size size)
|
|||
}
|
||||
|
||||
vmArenaExtend_Done:
|
||||
|
||||
EVENT2(vmArenaExtendDone, chunkSize, VMArenaReserved(VMArena2Arena(vmArena)));
|
||||
DIAG_SINGLEF(( "vmArenaExtend_Done",
|
||||
"Request for new chunk of VM $W bytes succeeded", (WriteFW)chunkSize,
|
||||
" (VMArenaReserved now $W bytes)\n",
|
||||
(WriteFW)VMArenaReserved(VMArena2Arena(vmArena)),
|
||||
NULL ));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -1677,46 +1660,17 @@ static void VMFree(Addr base, Size size, Pool pool)
|
|||
}
|
||||
|
||||
|
||||
/* M_whole, M_frac -- print count of bytes as Megabytes
|
||||
*
|
||||
* Split into a whole number of MB, "m" for the decimal point, and
|
||||
* then the decimal fraction (thousandths of a MB, ie. kB).
|
||||
*
|
||||
* Input: 208896
|
||||
* Output: (Megabytes) 0m209
|
||||
*/
|
||||
#define bPerM ((Size)1000000) /* Megabytes */
|
||||
#define bThou ((Size)1000)
|
||||
DIAG_DECL(
|
||||
static Count M_whole(Size bytes)
|
||||
{
|
||||
Count M; /* MBs */
|
||||
M = (bytes + (bThou / 2)) / bPerM;
|
||||
return M;
|
||||
}
|
||||
static Count M_frac(Size bytes)
|
||||
{
|
||||
Count Mthou; /* thousandths of a MB */
|
||||
Mthou = (bytes + (bThou / 2)) / bThou;
|
||||
Mthou = Mthou % 1000;
|
||||
return Mthou;
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
static void VMCompact(Arena arena, Trace trace)
|
||||
{
|
||||
VMArena vmArena;
|
||||
Ring node, next;
|
||||
DIAG_DECL( Size vmem1; )
|
||||
Size vmem1;
|
||||
|
||||
vmArena = Arena2VMArena(arena);
|
||||
AVERT(VMArena, vmArena);
|
||||
AVERT(Trace, trace);
|
||||
|
||||
DIAG(
|
||||
vmem1 = VMArenaReserved(arena);
|
||||
);
|
||||
vmem1 = VMArenaReserved(arena);
|
||||
|
||||
/* Destroy any empty chunks (except the primary). */
|
||||
sparePagesPurge(vmArena);
|
||||
|
|
@ -1728,44 +1682,19 @@ static void VMCompact(Arena arena, Trace trace)
|
|||
}
|
||||
}
|
||||
|
||||
DIAG(
|
||||
{
|
||||
Size vmem0 = trace->preTraceArenaReserved;
|
||||
Size vmem2 = VMArenaReserved(arena);
|
||||
Size vmemD = vmem1 - vmem2;
|
||||
Size live = trace->forwardedSize + trace->preservedInPlaceSize;
|
||||
Size livePerc = 0;
|
||||
|
||||
if(trace->condemned / 100 != 0)
|
||||
livePerc = live / (trace->condemned / 100);
|
||||
|
||||
/* VMCompact diag: emit for all client-requested collections, */
|
||||
/* VMCompact event: emit for all client-requested collections, */
|
||||
/* plus any others where chunks were gained or lost during the */
|
||||
/* collection. */
|
||||
if(trace->why == TraceStartWhyCLIENTFULL_INCREMENTAL
|
||||
|| trace->why == TraceStartWhyCLIENTFULL_BLOCK
|
||||
|| vmem0 != vmem1
|
||||
|| vmem1 != vmem2) {
|
||||
DIAG_SINGLEF(( "VMCompact",
|
||||
"pre-collection vmem was $Um$3, ",
|
||||
(WriteFU)M_whole(vmem0), (WriteFU)M_frac(vmem0),
|
||||
"peaked at $Um$3, ", (WriteFU)M_whole(vmem1), (WriteFU)M_frac(vmem1),
|
||||
"released $Um$3, ", (WriteFU)M_whole(vmemD), (WriteFU)M_frac(vmemD),
|
||||
"now $Um$3", (WriteFU)M_whole(vmem2), (WriteFU)M_frac(vmem2),
|
||||
" (why $U", (WriteFU)trace->why,
|
||||
": $Um$3",
|
||||
(WriteFU)M_whole(trace->condemned), (WriteFU)M_frac(trace->condemned),
|
||||
"[->$Um$3", (WriteFU)M_whole(live), (WriteFU)M_frac(live),
|
||||
" $U%-live", (WriteFU)livePerc,
|
||||
" $Um$3-stuck]",
|
||||
(WriteFU)M_whole(trace->preservedInPlaceSize),
|
||||
(WriteFU)M_frac(trace->preservedInPlaceSize),
|
||||
" ($Um$3-not)",
|
||||
(WriteFU)M_whole(trace->notCondemned),
|
||||
(WriteFU)M_frac(trace->notCondemned),
|
||||
" )",
|
||||
NULL));
|
||||
}
|
||||
);
|
||||
|| vmem1 != vmem2)
|
||||
EVENT3(VMCompact, vmem0, vmem1, vmem2);
|
||||
}
|
||||
}
|
||||
|
||||
mps_res_t mps_arena_vm_growth(mps_arena_t mps_arena,
|
||||
|
|
|
|||
|
|
@ -51,11 +51,11 @@ typedef struct PoolGenStruct {
|
|||
RingStruct genRing;
|
||||
Size totalSize; /* total size of segs in gen in this pool */
|
||||
Size newSize; /* size allocated since last GC */
|
||||
/* newSize when TraceCreate is called. This is for diagnostic */
|
||||
/* purposes only. It's used in a DIAG message emitted in TraceStart; */
|
||||
/* at that time, newSize has already been diminished by Whiten so we */
|
||||
/* can't use that value. This will not work well with multiple */
|
||||
/* traces. */
|
||||
/* newSize when TraceCreate was called. This is used in the
|
||||
* TraceStartPoolGen event emitted at the start of a trace; at that
|
||||
* time, newSize has already been diminished by Whiten so we can't
|
||||
* use that value. TODO: This will not work well with multiple
|
||||
* traces. */
|
||||
Size newSizeAtCreate;
|
||||
} PoolGenStruct;
|
||||
|
||||
|
|
|
|||
|
|
@ -131,10 +131,6 @@ ifeq ($(VARIETY),hot)
|
|||
CFLAGS=$(CFLAGSCOMMON) $(CFHOT)
|
||||
CFLAGSLAX=$(CFLAGSCOMMONLAX) $(CFHOT)
|
||||
else
|
||||
ifeq ($(VARIETY),diag)
|
||||
CFLAGS=$(CFLAGSCOMMON) $(CFDIAG)
|
||||
CFLAGSLAX=$(CFLAGSCOMMONLAX) $(CFDIAG)
|
||||
else
|
||||
ifeq ($(VARIETY),cool)
|
||||
CFLAGS=$(CFLAGSCOMMON) $(CFCOOL)
|
||||
CFLAGSLAX=$(CFLAGSCOMMONLAX) $(CFCOOL)
|
||||
|
|
@ -168,10 +164,10 @@ FMTHETST = fmthe.c fmtdy.c fmtno.c fmtdytst.c
|
|||
PLINTH = mpsliban.c mpsioan.c
|
||||
EVENTPROC = eventcnv.c eventpro.c table.c
|
||||
MPMCOMMON = abq.c arena.c arenacl.c arenavm.c arg.c boot.c bt.c \
|
||||
buffer.c cbs.c dbgpool.c dbgpooli.c diag.c event.c format.c \
|
||||
global.c ld.c locus.c message.c meter.c mpm.c mpsi.c pool.c \
|
||||
poolabs.c poolmfs.c poolmrg.c poolmv.c protocol.c ref.c reserv.c \
|
||||
ring.c root.c sac.c seg.c shield.c splay.c ss.c table.c trace.c \
|
||||
buffer.c cbs.c dbgpool.c dbgpooli.c event.c format.c global.c \
|
||||
ld.c locus.c message.c meter.c mpm.c mpsi.c pool.c poolabs.c \
|
||||
poolmfs.c poolmrg.c poolmv.c protocol.c ref.c reserv.c ring.c \
|
||||
root.c sac.c seg.c shield.c splay.c ss.c table.c trace.c \
|
||||
traceanc.c tract.c walk.c
|
||||
MPM = $(MPMCOMMON) $(MPMPF)
|
||||
|
||||
|
|
@ -326,9 +322,6 @@ endif
|
|||
$(PFM)/rash/mps.a: $(PFM)/rash/mps.o
|
||||
$(PFM)/hot/mps.a: $(PFM)/hot/mps.o
|
||||
|
||||
$(PFM)/diag/mps.a: \
|
||||
$(MPMOBJ) $(AMCOBJ) $(AMSOBJ) $(AWLOBJ) $(LOOBJ) $(SNCOBJ) \
|
||||
$(MV2OBJ) $(MVFFOBJ) $(PLINTHOBJ) $(POOLNOBJ)
|
||||
$(PFM)/cool/mps.a: \
|
||||
$(MPMOBJ) $(AMCOBJ) $(AMSOBJ) $(AWLOBJ) $(LOOBJ) $(SNCOBJ) \
|
||||
$(MV2OBJ) $(MVFFOBJ) $(PLINTHOBJ) $(POOLNOBJ)
|
||||
|
|
|
|||
|
|
@ -88,9 +88,9 @@ ALL_TARGETS=$(LIB_TARGETS) $(AUTO_TEST_TARGETS) $(OTHER_TEST_TARGETS) $(EXTRA_TA
|
|||
# %%PART: When adding a new part, add the sources for the new part here.
|
||||
|
||||
MPMCOMMON = <abq> <arena> <arenacl> <arenavm> <arg> <boot> <bt> \
|
||||
<buffer> <cbs> <dbgpool> <dbgpooli> <diag> <event> <format> \
|
||||
<global> <ld> <lockw3> <locus> <message> <meter> <mpm> <mpsi> \
|
||||
<mpsiw3> <pool> <poolabs> <poolmfs> <poolmrg> <poolmv2> <poolmv> \
|
||||
<buffer> <cbs> <dbgpool> <dbgpooli> <event> <format> <global> \
|
||||
<ld> <lockw3> <locus> <message> <meter> <mpm> <mpsi> <mpsiw3> \
|
||||
<pool> <poolabs> <poolmfs> <poolmrg> <poolmv2> <poolmv> \
|
||||
<protocol> <protw3> <ref> <reserv> <ring> <root> <sac> <seg> \
|
||||
<shield> <splay> <ss> <table> <thw3> <trace> <traceanc> <tract> \
|
||||
<vmw3> <walk>
|
||||
|
|
|
|||
|
|
@ -39,29 +39,6 @@
|
|||
/* no telemetry log events */
|
||||
|
||||
|
||||
/* CONFIG_VAR_DIAG -- diagnostic variety
|
||||
*
|
||||
* Deprecated. The diagnostic variety prints messages about the internals
|
||||
* of the MPS to an output stream. This is being replaced by an extended
|
||||
* telemetry system. RB 2012-08-31
|
||||
*/
|
||||
|
||||
#elif defined(CONFIG_VAR_DIAG) /* Diagnostic variety */
|
||||
#define CONFIG_ASSERT
|
||||
#define CONFIG_ASSERT_ABORT
|
||||
#ifndef CHECKLEVEL
|
||||
#define CHECKLEVEL CheckLevelMINIMAL
|
||||
#endif
|
||||
#define CONFIG_STATS
|
||||
/* For diagnostics, choose a DIAG_WITH_... output method.
|
||||
* (We need to choose because the DIAG output system is under
|
||||
* development. RHSK 2007-05-21).
|
||||
*/
|
||||
#define DIAG_WITH_STREAM_AND_WRITEF
|
||||
/* #define DIAG_WITH_PRINTF */
|
||||
#define CONFIG_LOG
|
||||
|
||||
|
||||
/* CONFIG_VAR_COOL -- cool variety
|
||||
*
|
||||
* The cool variety is intended for use when developing an integration with
|
||||
|
|
@ -129,10 +106,6 @@
|
|||
|
||||
#if defined(CONFIG_STATS)
|
||||
/* CONFIG_STATS = STATISTICS = METERs */
|
||||
/* Note: the STATISTICS define used to be called "DIAGNOSTICS" (even */
|
||||
/* though it controls the STATISTIC system), but the term */
|
||||
/* "diagnostic" means something else now: see design/diag/. */
|
||||
/* RHSK 2007-06-28 */
|
||||
/* WARNING: this may change the size and fields of MPS structs */
|
||||
/* (...but see STATISTIC_DECL, which is invariant) */
|
||||
#define STATISTICS
|
||||
|
|
@ -414,20 +387,6 @@
|
|||
#define ASSERT_BUFFER_SIZE ((Size)512)
|
||||
|
||||
|
||||
/* Diagnostics Buffer */
|
||||
|
||||
#ifdef DIAG_WITH_STREAM_AND_WRITEF
|
||||
/* DIAG_BUFFER_SIZE: 100 screenfuls: 100x80x25 = 200000 */
|
||||
#define DIAG_BUFFER_SIZE ((Size)200000)
|
||||
#else
|
||||
#define DIAG_BUFFER_SIZE ((Size)1)
|
||||
#endif
|
||||
|
||||
#define DIAG_PREFIX_TAGSTART "MPS."
|
||||
#define DIAG_PREFIX_LINE " "
|
||||
#define DIAG_PREFIX_TAGEND ""
|
||||
|
||||
|
||||
/* memory operator configuration
|
||||
*
|
||||
* We need efficient operators similar to memcpy, memset, and memcmp.
|
||||
|
|
|
|||
773
mps/code/diag.c
773
mps/code/diag.c
|
|
@ -1,773 +0,0 @@
|
|||
/* diag.c: MEMORY POOL MANAGER DIAGNOSTICS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2007 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* To Do: [RHSK 2007-08-13]
|
||||
* @@ sigs and AVERTs for Rule, and macro for Rules initializer
|
||||
* @@ deprecate un-tagged diags, remove old macros
|
||||
* @@ every diag should end with \n: warn if this is missing.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "mpm.h"
|
||||
#include "mpslib.h" /* for mps_lib_stdout */
|
||||
|
||||
#if defined(DIAG_WITH_STREAM_AND_WRITEF)
|
||||
|
||||
typedef struct RuleStruct {
|
||||
const char *action;
|
||||
const char *tag;
|
||||
const char *para;
|
||||
const char *line;
|
||||
int tpMatch; /* .tpmatch */
|
||||
/* @@ needs sig; (at end, to make initializer expression easy?) */
|
||||
} *Rule;
|
||||
|
||||
|
||||
/* RulesGlobal -- throw away some diags (see INSTRUCTIONS below) */
|
||||
|
||||
struct RuleStruct RulesGlobal[] = {
|
||||
{ "-", "*", "*", "*" },
|
||||
{ "+", "DiagFilter_Rules", "*", "*" },
|
||||
{ "+", "VMCompact", "*", "*" },
|
||||
/* ----v---- always on please (RHSK) ----v---- */
|
||||
{ "+", "MPSVersion", "*", "*" },
|
||||
{ "+", "traceSetSignalEmergency", "*", "*" },
|
||||
{ NULL, "", "", "" }
|
||||
};
|
||||
|
||||
struct RuleStruct RulesGlobal_RHSK[] = {
|
||||
{ "+", "*", "*", "*" },
|
||||
{ "+", "DiagFilter_Rules", "*", "*" },
|
||||
{ "-", "DIAGTEST_", "*", "*" },
|
||||
{ "+", "AMCTraceEnd_pageret", "*", "*" },
|
||||
{ "-", "ChainCondemnAuto", "*", "*" },
|
||||
{ "+", "VM_ix_", "*", "*" },
|
||||
{ "-", "vmArenaExtend_", "*", "*" },
|
||||
{ "-", "traceFindGrey", "*", "*" },
|
||||
{ "-", "TraceStart", "*", "*" },
|
||||
{ "+", "TraceStart", "*", "controlPool" },
|
||||
{ "+", "TraceStart", "*", "reserved" },
|
||||
{ "+", "TraceStart", "*", "committed" },
|
||||
{ "+", "TraceStart", "*", "genZoneSet" },
|
||||
{ "-", "TraceStart", "because code 1", "*" },
|
||||
{ "+", "VMCompact", "*", "*" },
|
||||
{ "-", "VMCompact_hex", "*", "*" },
|
||||
{ "+", "VM_ix_Create", "*", "*" },
|
||||
/* ----v---- always on please (RHSK) ----v---- */
|
||||
{ "+", "traceSetSignalEmergency", "*", "*" },
|
||||
{ NULL, "", "", "" }
|
||||
};
|
||||
|
||||
struct RuleStruct RulesGlobalExample[] = {
|
||||
{ "+", "*", "*", "*" },
|
||||
{ "+", "DiagFilter_Rules", "*", "*" },
|
||||
{ "-", "DIAGTEST_", "*", "*" },
|
||||
{ "+", "ChainCondemnAuto", "gens [0..0]", "*" },
|
||||
{ "+", "TraceStart", "*", "*" },
|
||||
{ "+", "TraceStart", "because code 1:", "*" },
|
||||
{ "-", "TraceStart", "*", "controlPool" },
|
||||
{ "-", "TraceStart", "*", "ommit" },
|
||||
{ "-", "TraceStart", "*", "zoneShift" },
|
||||
{ "-", "TraceStart", "*", "alignment" },
|
||||
{ "-", "amcScanNailed-loop", "*", "*" },
|
||||
{ NULL, "", "", "" }
|
||||
};
|
||||
|
||||
/* RulesGlobal -- INSTRUCTIONS
|
||||
*
|
||||
* In your local copy of diag.c, you can modify RulesGlobal as you
|
||||
* wish, to control what diags you see.
|
||||
*
|
||||
* Each rule consists of: action, tag, para, and line. A rule that
|
||||
* matches on TAG, PARA and LINE determines what ACTION is taken
|
||||
* for that line of that diag. Later rules override earlier rules,
|
||||
* ie. the lowest matching rule wins. (And at least one rule must
|
||||
* match, so the first rule should be a catch-all).
|
||||
*
|
||||
* ACTION = "+" (output this line of diag), or "-" (skip this line).
|
||||
*
|
||||
* TAG: does pattern (text or *) appear in diag's tag?
|
||||
*
|
||||
* PARA: does pattern (text or *) appear anywhere in diag's text output
|
||||
* (does not match the tag)?
|
||||
*
|
||||
* LINE: does pattern (text or *) appear on this line of the diag
|
||||
* text?
|
||||
*
|
||||
* Note: a diag that deliberately has no output, eg.
|
||||
* DIAG_SINGLEF(( "MyTag", NULL )),
|
||||
* is treated as having a single empty 'line'. See .empty-diag.
|
||||
*
|
||||
* Note: for help debugging your ruleset, see .rules.debug below.
|
||||
*
|
||||
* Note: the entire filtering mechanism can be turned off, so that
|
||||
* diagnostics go immediately to mps_lib_stdout: see .filter-disable.
|
||||
*/
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
|
||||
static mps_lib_FILE *filterStream(void);
|
||||
static int filterStream_fputc(int c, mps_lib_FILE *stream);
|
||||
static int filterStream_fputs(const char *s, mps_lib_FILE *stream);
|
||||
static void diag_test(void);
|
||||
|
||||
|
||||
/* Stream -- output to filterStream or to a real mps_lib_FILE stream
|
||||
*
|
||||
* There are only two functions and two destinations; a full class
|
||||
* hierarchy would be overkill! RHSK 2007-08-08.
|
||||
*/
|
||||
|
||||
int Stream_fputc(int c, mps_lib_FILE *stream)
|
||||
{
|
||||
if(stream == filterStream())
|
||||
return filterStream_fputc(c, stream);
|
||||
else
|
||||
return mps_lib_fputc(c, stream);
|
||||
}
|
||||
|
||||
int Stream_fputs(const char *s, mps_lib_FILE *stream)
|
||||
{
|
||||
if(stream == filterStream())
|
||||
return filterStream_fputs(s, stream);
|
||||
else
|
||||
return mps_lib_fputs(s, stream);
|
||||
}
|
||||
|
||||
|
||||
/* Diag -- a buffer to store a diagnostic
|
||||
*
|
||||
*/
|
||||
|
||||
#define DiagSig ((Sig)0x519D1A99) /* SIGnature DIAG */
|
||||
|
||||
typedef struct DiagStruct {
|
||||
Sig sig;
|
||||
const char *tag;
|
||||
Bool overflow; /* diag > buf? set flag, truncate, force output */
|
||||
Count n;
|
||||
char buf[DIAG_BUFFER_SIZE];
|
||||
} *Diag;
|
||||
|
||||
static Bool DiagCheck(Diag diag)
|
||||
{
|
||||
CHECKS(Diag, diag);
|
||||
CHECKL(diag->n <= sizeof(diag->buf));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* filterStream -- capable of filtering diagnostics
|
||||
*
|
||||
* This is not really an mps_lib_FILE*; it is a single global instance
|
||||
* of a DiagStruct.
|
||||
*
|
||||
* Output is stored in a DiagStruct, to be filtered and output
|
||||
* (or not) when complete.
|
||||
*/
|
||||
|
||||
static struct DiagStruct filterDiagGlobal = { DiagSig, NULL, FALSE, 0 };
|
||||
|
||||
static mps_lib_FILE *filterStream(void)
|
||||
{
|
||||
return (mps_lib_FILE*)&filterDiagGlobal;
|
||||
}
|
||||
|
||||
/* filterStream_under: the underlying stream used to output diags */
|
||||
/* that pass the filter. */
|
||||
static mps_lib_FILE *filterStream_under(void)
|
||||
{
|
||||
return mps_lib_stdout;
|
||||
}
|
||||
|
||||
/* .tpmatch: does this rule match current diag's tag and para? */
|
||||
enum {
|
||||
TPMatch_Unknown = 0, /* initial value = 0 */
|
||||
TPMatch_Yes,
|
||||
TPMatch_No
|
||||
};
|
||||
|
||||
static void version_diag(void)
|
||||
{
|
||||
DIAG_SINGLEF(( "MPSVersion",
|
||||
"$S", (WriteFS)MPSVersion(), NULL ));
|
||||
}
|
||||
|
||||
static void rules_diag(Rule rules)
|
||||
{
|
||||
Index ir;
|
||||
|
||||
AVER(rules);
|
||||
DIAG_FIRSTF(( "DiagFilter_Rules",
|
||||
"Only showing diags permitted by these tag/paragraph/line"
|
||||
" rules:\n", NULL ));
|
||||
for(ir = 0; rules[ir].action != NULL; ir++) {
|
||||
DIAG_DECL( Rule rule = &rules[ir]; )
|
||||
DIAG_MOREF(( "$S$S/$S/$S\n", (WriteFS)rule->action, (WriteFS)rule->tag,
|
||||
(WriteFS)rule->para, (WriteFS)rule->line,
|
||||
NULL ));
|
||||
}
|
||||
DIAG_END("DiagFilter_Rules");
|
||||
}
|
||||
|
||||
|
||||
/* patternOccurs -- does patt occur in buf[i..j)?
|
||||
*
|
||||
* Returns true iff patt[0..pattLen) literally occurs in buf[i..j).
|
||||
*/
|
||||
|
||||
static Bool patternOccurs(const char *patt, Count pattLen,
|
||||
const char *buf, Index i, Index j)
|
||||
{
|
||||
Index im; /* start of tentative match */
|
||||
Index ip; /* index into patt */
|
||||
|
||||
AVER(patt);
|
||||
AVER(buf);
|
||||
AVER(i <= j);
|
||||
|
||||
/* Search (naively) for patt anywhere inside buf[i..j) */
|
||||
for(im = i; im + pattLen <= j; im++) {
|
||||
/* Consider upto pattLen chars starting at patt[0] and buf[im] */
|
||||
for(ip = 0; ip < pattLen; ip++) {
|
||||
if(patt[ip] != buf[im + ip])
|
||||
break;
|
||||
}
|
||||
if(ip == pattLen) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static Bool matchLine(Rule rule, Diag diag, Index i, Index j)
|
||||
{
|
||||
AVER(rule);
|
||||
AVER(diag);
|
||||
AVER(i <= j);
|
||||
AVER(j <= diag->n);
|
||||
|
||||
if(rule->line[0] == '*')
|
||||
return TRUE;
|
||||
|
||||
return patternOccurs(rule->line, StringLength(rule->line),
|
||||
diag->buf, i, j);
|
||||
}
|
||||
|
||||
static Bool matchPara(Rule rule, Diag diag)
|
||||
{
|
||||
AVER(rule);
|
||||
AVER(diag);
|
||||
|
||||
if(rule->para[0] == '*')
|
||||
return TRUE;
|
||||
|
||||
return patternOccurs(rule->para, StringLength(rule->para),
|
||||
diag->buf, 0, diag->n);
|
||||
}
|
||||
|
||||
static Bool matchTag(Rule rule, const char *tag)
|
||||
{
|
||||
AVER(rule);
|
||||
AVER(rule->tag);
|
||||
AVER(tag);
|
||||
|
||||
if(rule->tag[0] == '*')
|
||||
return TRUE;
|
||||
|
||||
return patternOccurs(rule->tag, StringLength(rule->tag),
|
||||
tag, 0, StringLength(tag));
|
||||
}
|
||||
|
||||
static void filterStream_LineOut(Diag diag, Index i, Index j)
|
||||
{
|
||||
int r;
|
||||
|
||||
AVER(diag);
|
||||
AVER(i <= j);
|
||||
AVER(j <= diag->n);
|
||||
|
||||
r = Stream_fputs(DIAG_PREFIX_LINE, filterStream_under());
|
||||
AVER(r != mps_lib_EOF);
|
||||
|
||||
for(; i < j; i++) {
|
||||
char c;
|
||||
c = diag->buf[i];
|
||||
r = Stream_fputc(c, filterStream_under());
|
||||
AVER(r != mps_lib_EOF);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* filterStream_Output -- output this diag, if the rules select it
|
||||
*
|
||||
*/
|
||||
|
||||
static void filterStream_Output(Diag diag, Rule rules)
|
||||
{
|
||||
static Bool inside = FALSE;
|
||||
Res res;
|
||||
Count nr;
|
||||
Index ir;
|
||||
Index i, j;
|
||||
Bool nolinesyet = TRUE;
|
||||
Bool emptyonce;
|
||||
|
||||
AVER(!inside);
|
||||
inside = TRUE;
|
||||
AVER(diag);
|
||||
AVER(rules);
|
||||
|
||||
if(diag->tag == NULL)
|
||||
diag->tag = "(no tag)";
|
||||
|
||||
/* Count the rules */
|
||||
for(ir = 0; rules[ir].action != NULL; ir++) {
|
||||
rules[ir].tpMatch = TPMatch_Unknown;
|
||||
}
|
||||
nr = ir;
|
||||
|
||||
/* Filter */
|
||||
/* .empty-diag: Treat a diag that deliberately has no output, */
|
||||
/* eg: DIAG_SINGLEF(( "Tag", NULL )), as having a single empty */
|
||||
/* 'line'. This is the only time a line may be empty. */
|
||||
emptyonce = (diag->n == 0);
|
||||
for(i = 0; emptyonce || i < diag->n; i = j) {
|
||||
|
||||
/* Get the next line [i..j) */
|
||||
for(j = i; j < diag->n; j++) {
|
||||
if(diag->buf[j] == '\n') {
|
||||
j++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
AVER(emptyonce || i < j); /* .empty-diag */
|
||||
emptyonce = FALSE;
|
||||
|
||||
/* Find the lowest rule that matches it. */
|
||||
ir = nr - 1;
|
||||
for(;;) {
|
||||
Rule rule = &rules[ir];
|
||||
if(rule->tpMatch == TPMatch_Unknown) {
|
||||
/* memoize .tpMatch */
|
||||
if(matchTag(rule, diag->tag) && matchPara(rule, diag)) {
|
||||
rule->tpMatch = TPMatch_Yes;
|
||||
} else {
|
||||
rule->tpMatch = TPMatch_No;
|
||||
}
|
||||
}
|
||||
if(rule->tpMatch == TPMatch_Yes && matchLine(rule, diag, i, j))
|
||||
break;
|
||||
AVER(ir != 0); /* there must ALWAYS be a matching rule */
|
||||
ir--;
|
||||
}
|
||||
|
||||
/* Do the rule's action. */
|
||||
if(0) {
|
||||
/* .rules.debug: Turn this on to show which rule applied. */
|
||||
Rule rule = &rules[ir];
|
||||
(void) WriteF(filterStream_under(), "[$U/$U:", ir, nr,
|
||||
" $S$S/$S/$S] ", rule->action, rule->tag,
|
||||
rule->para, rule->line, NULL);
|
||||
}
|
||||
if(rules[ir].action[0] == '+' || diag->overflow) {
|
||||
if(nolinesyet) {
|
||||
res = WriteF(filterStream_under(),
|
||||
DIAG_PREFIX_TAGSTART "$S {", (WriteFS)diag->tag, NULL);
|
||||
AVER(res == ResOK);
|
||||
nolinesyet = FALSE;
|
||||
}
|
||||
filterStream_LineOut(diag, i, j);
|
||||
}
|
||||
}
|
||||
|
||||
if(diag->overflow) {
|
||||
res = WriteF(filterStream_under(),
|
||||
"\n--- diagnostic too large: "
|
||||
"forced to output, but truncated here ---\n"
|
||||
"--- (for a bigger buffer, change DIAG_BUFFER_SIZE) ---\n", NULL);
|
||||
AVER(res == ResOK);
|
||||
}
|
||||
if(!nolinesyet) {
|
||||
res = WriteF(filterStream_under(), DIAG_PREFIX_TAGEND "}\n", NULL);
|
||||
AVER(res == ResOK);
|
||||
}
|
||||
inside = FALSE;
|
||||
}
|
||||
|
||||
static void filterStream_TagBegin(mps_lib_FILE *stream, const char *tag)
|
||||
{
|
||||
static Bool first = TRUE;
|
||||
Diag diag;
|
||||
|
||||
AVER(stream);
|
||||
AVER(tag);
|
||||
|
||||
diag = (Diag)stream;
|
||||
AVERT(Diag, diag);
|
||||
|
||||
if(first) {
|
||||
first = FALSE;
|
||||
version_diag();
|
||||
rules_diag(&RulesGlobal[0]);
|
||||
diag_test();
|
||||
}
|
||||
|
||||
if(diag->tag != NULL) {
|
||||
/* Be helpful to the poor programmer! */
|
||||
(void) WriteF(filterStream_under(),
|
||||
"\nWARNING: diag tag \"$S\" is still current"
|
||||
" (missing DIAG_END()).",
|
||||
diag->tag, NULL);
|
||||
}
|
||||
AVER(diag->tag == NULL);
|
||||
|
||||
/* @@ when all diags are tagged, the buffer must be empty */
|
||||
/* @@ but for now, as a courtesy... */
|
||||
if(diag->n > 0) {
|
||||
filterStream_Output(diag, &RulesGlobal[0]);
|
||||
diag->n = 0;
|
||||
}
|
||||
|
||||
diag->tag = tag;
|
||||
diag->overflow = FALSE;
|
||||
AVER(diag->n == 0);
|
||||
}
|
||||
|
||||
static void filterStream_TagEnd(mps_lib_FILE *stream, const char *tag)
|
||||
{
|
||||
Diag diag;
|
||||
diag = (Diag)stream;
|
||||
AVERT(Diag, diag);
|
||||
|
||||
AVER(diag->tag != NULL);
|
||||
|
||||
if(!StringEqual(diag->tag, tag)) {
|
||||
/* Be helpful to the poor programmer! */
|
||||
(void) WriteF(filterStream_under(),
|
||||
"\nWARNING: diag tag \"$S\" is current, "
|
||||
"but got DIAG_END(\"$S\"). (They must match).",
|
||||
(WriteFS)diag->tag, (WriteFS)tag, NULL);
|
||||
}
|
||||
AVER(StringEqual(diag->tag, tag));
|
||||
|
||||
/* Output the diag */
|
||||
filterStream_Output(diag, &RulesGlobal[0]);
|
||||
|
||||
diag->tag = NULL;
|
||||
diag->n = 0;
|
||||
}
|
||||
|
||||
static int filterStream_fputc(int c, mps_lib_FILE *stream)
|
||||
{
|
||||
Diag diag;
|
||||
|
||||
AVER(c != mps_lib_EOF);
|
||||
AVER(stream == filterStream());
|
||||
|
||||
diag = (Diag)stream;
|
||||
AVERT(Diag, diag);
|
||||
/* @@ when all diags are tagged: AVER(diag->tag != NULL); */
|
||||
|
||||
/* AVER(diag->n + 1 <= sizeof(diag->buf)); */
|
||||
if(!(diag->n + 1 <= sizeof(diag->buf))) {
|
||||
diag->overflow = TRUE;
|
||||
/* ignore failure; do not return mps_lib_EOF */
|
||||
return c;
|
||||
}
|
||||
|
||||
/* add c to buffer */
|
||||
diag->buf[diag->n++] = (char)c;
|
||||
return c;
|
||||
}
|
||||
|
||||
static int filterStream_fputs(const char *s, mps_lib_FILE *stream)
|
||||
{
|
||||
Diag diag;
|
||||
Count l;
|
||||
Index i;
|
||||
|
||||
AVER(s);
|
||||
AVER(stream == filterStream());
|
||||
|
||||
diag = (Diag)stream;
|
||||
AVERT(Diag, diag);
|
||||
/* @@ when all diags are tagged: AVER(diag->tag != NULL); */
|
||||
|
||||
l = StringLength(s);
|
||||
|
||||
/* AVER(diag->n + l <= sizeof(diag->buf)); */
|
||||
if(!(diag->n + l <= sizeof(diag->buf))) {
|
||||
diag->overflow = TRUE;
|
||||
/* ignore failure; do not return mps_lib_EOF */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* add s to buffer */
|
||||
for (i = 0; i < l; i++) {
|
||||
diag->buf[diag->n++] = s[i];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* DIAG_WITH_STREAM_AND_WRITEF -- Diagnostic output channel
|
||||
*
|
||||
* Only used for DIAG_WITH_STREAM_AND_WRITEF; see config.h.
|
||||
*/
|
||||
|
||||
Bool DiagEnabledGlobal = TRUE;
|
||||
|
||||
Bool DiagIsOn(void)
|
||||
{
|
||||
return DiagEnabledGlobal;
|
||||
}
|
||||
|
||||
mps_lib_FILE *DiagStream(void)
|
||||
{
|
||||
/* .filter-disable: the entire filtering mechanism can be turned */
|
||||
/* off, so that diagnostics go immediately to mps_lib_stdout, */
|
||||
/* with no buffering or filtering. */
|
||||
Bool filter = TRUE;
|
||||
|
||||
if(filter) {
|
||||
return filterStream();
|
||||
} else {
|
||||
return mps_lib_stdout;
|
||||
}
|
||||
}
|
||||
|
||||
static void diagTagBegin(mps_lib_FILE *stream, const char *tag)
|
||||
{
|
||||
AVER(stream);
|
||||
AVER(tag);
|
||||
|
||||
if(stream == filterStream()) {
|
||||
filterStream_TagBegin(stream, tag);
|
||||
} else {
|
||||
Res res;
|
||||
res = WriteF(stream, DIAG_PREFIX_TAGSTART "$S {\n", (WriteFS)tag, NULL);
|
||||
AVER(res == ResOK);
|
||||
}
|
||||
}
|
||||
|
||||
static void diagTagEnd(mps_lib_FILE *stream, const char *tag)
|
||||
{
|
||||
AVER(stream);
|
||||
AVER(tag);
|
||||
|
||||
if(stream == filterStream()) {
|
||||
filterStream_TagEnd(stream, tag);
|
||||
} else {
|
||||
Res res;
|
||||
res = WriteF(stream, DIAG_PREFIX_TAGEND "}\n", tag, NULL);
|
||||
AVER(res == ResOK);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Diag*F functions -- interface for general MPS code (via macros)
|
||||
*
|
||||
* These function manage TagBegin/End, and WriteF the text to
|
||||
* DiagStream().
|
||||
*
|
||||
* Direct writing to DiagStream() is also permitted (eg. from a
|
||||
* Describe method).
|
||||
*/
|
||||
|
||||
void DiagSingleF(const char *tag, ...)
|
||||
{
|
||||
va_list args;
|
||||
Res res;
|
||||
|
||||
diagTagBegin(DiagStream(), tag);
|
||||
|
||||
va_start(args, tag);
|
||||
res = WriteF_v(DiagStream(), args);
|
||||
AVER(res == ResOK);
|
||||
va_end(args);
|
||||
|
||||
diagTagEnd(DiagStream(), tag);
|
||||
}
|
||||
|
||||
void DiagFirstF(const char *tag, ...)
|
||||
{
|
||||
va_list args;
|
||||
Res res;
|
||||
|
||||
diagTagBegin(DiagStream(), tag);
|
||||
|
||||
va_start(args, tag);
|
||||
res = WriteF_v(DiagStream(), args);
|
||||
AVER(res == ResOK);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void DiagMoreF(const char *firstformat, ...)
|
||||
{
|
||||
va_list args;
|
||||
Res res;
|
||||
|
||||
/* ISO C says there must be at least one named parameter: hence */
|
||||
/* the named firstformat. It only looks different: there is no */
|
||||
/* change from the expected WriteF protocol. (In particular, */
|
||||
/* firstformat may legally be NULL, with the variable part empty). */
|
||||
|
||||
va_start(args, firstformat);
|
||||
res = WriteF_firstformat_v(DiagStream(), firstformat, args);
|
||||
AVER(res == ResOK);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void DiagEnd(const char *tag)
|
||||
{
|
||||
diagTagEnd(DiagStream(), tag);
|
||||
}
|
||||
|
||||
|
||||
/* Test Code -- unit tests for this source file
|
||||
*
|
||||
* These are for developers to run if they modify this source file.
|
||||
* There's no point running them otherwise. RHSK.
|
||||
*/
|
||||
|
||||
static void patternOccurs_test(Bool expect, const char *patt,
|
||||
const char *text)
|
||||
{
|
||||
Count pattLen = StringLength(patt);
|
||||
Count textLen = StringLength(text);
|
||||
enum {bufLen = 100};
|
||||
char buf[bufLen];
|
||||
Index start, i;
|
||||
Count padLen;
|
||||
Bool occurs;
|
||||
|
||||
/* Call patternOccurs with this patt and text 3 times: each time */
|
||||
/* putting the text in the buffer at a different offset, to */
|
||||
/* verify that patternOccurs is not accepting matches outside the */
|
||||
/* [i..j) portion of the buffer. */
|
||||
|
||||
for(start = 0; start < 21; start += 7) {
|
||||
AVER(bufLen > (start + textLen));
|
||||
/* put text into buf at start */
|
||||
for(i = 0; i < start; i++) {
|
||||
buf[i] = 'X';
|
||||
}
|
||||
for(i = 0; i < textLen; i++) {
|
||||
(buf+start)[i] = text[i];
|
||||
}
|
||||
padLen = bufLen - (start + textLen);
|
||||
for(i = 0; i < padLen; i++) {
|
||||
(buf+start+textLen)[i] = 'X';
|
||||
}
|
||||
occurs = patternOccurs(patt, pattLen, buf, start, start+textLen);
|
||||
AVER(occurs == expect);
|
||||
}
|
||||
}
|
||||
|
||||
static void diag_test(void)
|
||||
{
|
||||
DIAG_SINGLEF(( "DIAGTEST_Tag1", "text $U.\n", (WriteFU)42, NULL ));
|
||||
|
||||
DIAG_SINGLEF(( "DIAGTEST_EmptyDiag", NULL ));
|
||||
|
||||
DIAG_FIRSTF((
|
||||
"DIAGTEST_StringEqual",
|
||||
"Fred = Fred: $U.\n",
|
||||
StringEqual("Fred", "Fred"),
|
||||
NULL
|
||||
));
|
||||
DIAG_MOREF(("Fred = Tom: $U.\n", (WriteFU)StringEqual("Fred", "Tom"), NULL));
|
||||
DIAG_MOREF(("Tom = Fred: $U.\n", (WriteFU)StringEqual("Tom", "Fred"), NULL));
|
||||
DIAG_MOREF(("0 = Fred: $U.\n", (WriteFU)StringEqual("", "Fred"), NULL));
|
||||
DIAG_MOREF(("Fred = 0: $U.\n", (WriteFU)StringEqual("Fred", ""), NULL));
|
||||
DIAG_MOREF(("0 = 0: $U.\n", (WriteFU)StringEqual("", ""), NULL));
|
||||
DIAG_MOREF(("0 = 000: $U.\n", (WriteFU)StringEqual("", "\0\0"), NULL));
|
||||
DIAG_END("DIAGTEST_StringEqual");
|
||||
|
||||
DIAG_FIRSTF(( "DIAGTEST_patternOccurs", NULL ));
|
||||
patternOccurs_test(TRUE, "Fred", "Fred");
|
||||
patternOccurs_test(TRUE, "Fred", "XFredX");
|
||||
patternOccurs_test(TRUE, "Fred", "FFred");
|
||||
patternOccurs_test(TRUE, "Fred", "FrFred");
|
||||
patternOccurs_test(TRUE, "Fred", "FreFred");
|
||||
patternOccurs_test(TRUE, "Fred", "FreFreFFred");
|
||||
patternOccurs_test(TRUE, "Fred", "FredFred");
|
||||
patternOccurs_test(TRUE, "Fred", "FFredFre");
|
||||
patternOccurs_test(TRUE, "Fred", "FrFredFr");
|
||||
patternOccurs_test(TRUE, "Fred", "FreFredF");
|
||||
patternOccurs_test(TRUE, "Fred", "FreFreFFredFre");
|
||||
patternOccurs_test(TRUE, "Fred", "FredFredF");
|
||||
patternOccurs_test(TRUE, "X", "X");
|
||||
patternOccurs_test(TRUE, "", "X");
|
||||
patternOccurs_test(TRUE, "", "Whatever");
|
||||
patternOccurs_test(FALSE, "Fred", "Tom");
|
||||
patternOccurs_test(FALSE, "X", "Tom");
|
||||
patternOccurs_test(FALSE, "X", "x");
|
||||
patternOccurs_test(FALSE, "X", "");
|
||||
patternOccurs_test(FALSE, "Whatever", "");
|
||||
patternOccurs_test(FALSE, "Fred", "Fre");
|
||||
patternOccurs_test(FALSE, "Fred", "red");
|
||||
patternOccurs_test(FALSE, "Fred", "Fxred");
|
||||
patternOccurs_test(FALSE, "Fred", "Frexd");
|
||||
DIAG_END("DIAGTEST_patternOccurs");
|
||||
|
||||
#if 0
|
||||
DIAG_FIRSTF(( "TestTag2", "text $U.\n", (WriteFU)42, NULL ));
|
||||
DIAG_MOREF(( NULL ));
|
||||
DIAG_MOREF(( "string $S.\n", (WriteFS)"fooey!", NULL ));
|
||||
DIAG_MOREF(( NULL ));
|
||||
DIAG_MOREF(( "Another string $S.\n", (WriteFS)"baloney!", NULL ));
|
||||
DIAG_END( "TestTag2" );
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* DIAG_WITH_STREAM_AND_WRITEF */
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2007 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 3. Redistributions in any form must be accompanied by information on how
|
||||
* to obtain complete source code for this software and any accompanying
|
||||
* software that uses this software. The source code must either be
|
||||
* included in the distribution or be available for no more than the cost
|
||||
* of distribution plus a nominal fee, and must be freely redistributable
|
||||
* under reasonable conditions. For an executable file, complete source
|
||||
* code means the source code for all modules it contains. It does not
|
||||
* include source code for modules or files that typically accompany the
|
||||
* major components of the operating system on which the executable file
|
||||
* runs.
|
||||
*
|
||||
* 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, FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDERS AND 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.
|
||||
*/
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/* <code/event.h> -- Event Logging Interface
|
||||
*
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* $Id$
|
||||
*
|
||||
* READERSHIP
|
||||
|
|
@ -95,7 +95,7 @@ extern Word EventKindControl;
|
|||
|
||||
#define EVENT0(name) EVENT_BEGIN(name, sizeof(EventAnyStruct)) EVENT_END(name, sizeof(EventAnyStruct))
|
||||
/* The following lines were generated with
|
||||
python -c 'for i in range(1,15): print "#define EVENT%d(name, %s) EVENT_BEGIN(name, sizeof(Event##name##Struct)) %s EVENT_END(name, sizeof(Event##name##Struct))" % (i, ", ".join(["p%d" % j for j in range(0, i)]), " ".join(["_event->f%d = (p%d);" % (j, j) for j in range(0, i)]))'
|
||||
python -c 'for i in range(1,22): print "#define EVENT%d(name, %s) EVENT_BEGIN(name, sizeof(Event##name##Struct)) %s EVENT_END(name, sizeof(Event##name##Struct))" % (i, ", ".join(["p%d" % j for j in range(0, i)]), " ".join(["_event->f%d = (p%d);" % (j, j) for j in range(0, i)]))'
|
||||
*/
|
||||
#define EVENT1(name, p0) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); EVENT_END(name, sizeof(Event##name##Struct))
|
||||
#define EVENT2(name, p0, p1) EVENT_BEGIN(name, sizeof(Event##name##Struct)) _event->f0 = (p0); _event->f1 = (p1); EVENT_END(name, sizeof(Event##name##Struct))
|
||||
|
|
@ -111,6 +111,13 @@ extern Word EventKindControl;
|
|||
#define EVENT12(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(name, sizeof(Event##name##Struct))
|
||||
#define EVENT13(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(name, sizeof(Event##name##Struct))
|
||||
#define EVENT14(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(name, sizeof(Event##name##Struct))
|
||||
#define EVENT15(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14) 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->f14 = (p14); EVENT_END(name, sizeof(Event##name##Struct))
|
||||
#define EVENT16(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15) 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->f14 = (p14); _event->f15 = (p15); EVENT_END(name, sizeof(Event##name##Struct))
|
||||
#define EVENT17(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16) 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->f14 = (p14); _event->f15 = (p15); _event->f16 = (p16); EVENT_END(name, sizeof(Event##name##Struct))
|
||||
#define EVENT18(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17) 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->f14 = (p14); _event->f15 = (p15); _event->f16 = (p16); _event->f17 = (p17); EVENT_END(name, sizeof(Event##name##Struct))
|
||||
#define EVENT19(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18) 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->f14 = (p14); _event->f15 = (p15); _event->f16 = (p16); _event->f17 = (p17); _event->f18 = (p18); EVENT_END(name, sizeof(Event##name##Struct))
|
||||
#define EVENT20(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19) 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->f14 = (p14); _event->f15 = (p15); _event->f16 = (p16); _event->f17 = (p17); _event->f18 = (p18); _event->f19 = (p19); EVENT_END(name, sizeof(Event##name##Struct))
|
||||
#define EVENT21(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20) 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->f14 = (p14); _event->f15 = (p15); _event->f16 = (p16); _event->f17 = (p17); _event->f18 = (p18); _event->f19 = (p19); _event->f20 = (p20); EVENT_END(name, sizeof(Event##name##Struct))
|
||||
|
||||
|
||||
#else /* EVENT not */
|
||||
|
|
@ -118,7 +125,7 @@ extern Word EventKindControl;
|
|||
|
||||
#define EVENT0(name) NOOP
|
||||
/* The following lines were generated with
|
||||
python -c 'for i in range(1,15): print "#define EVENT%d(name, %s) BEGIN %s END" % (i, ", ".join(["p%d" % j for j in range(0, i)]), " ".join(["UNUSED(p%d);" % j for j in range(0, i)]))'
|
||||
python -c 'for i in range(1,22): print "#define EVENT%d(name, %s) BEGIN %s END" % (i, ", ".join(["p%d" % j for j in range(0, i)]), " ".join(["UNUSED(p%d);" % j for j in range(0, i)]))'
|
||||
*/
|
||||
#define EVENT1(name, p0) BEGIN UNUSED(p0); END
|
||||
#define EVENT2(name, p0, p1) BEGIN UNUSED(p0); UNUSED(p1); END
|
||||
|
|
@ -134,6 +141,13 @@ extern Word EventKindControl;
|
|||
#define EVENT12(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 EVENT13(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 EVENT14(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
|
||||
#define EVENT15(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14) 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); UNUSED(p14); END
|
||||
#define EVENT16(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15) 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); UNUSED(p14); UNUSED(p15); END
|
||||
#define EVENT17(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16) 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); UNUSED(p14); UNUSED(p15); UNUSED(p16); END
|
||||
#define EVENT18(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17) 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); UNUSED(p14); UNUSED(p15); UNUSED(p16); UNUSED(p17); END
|
||||
#define EVENT19(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18) 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); UNUSED(p14); UNUSED(p15); UNUSED(p16); UNUSED(p17); UNUSED(p18); END
|
||||
#define EVENT20(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19) 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); UNUSED(p14); UNUSED(p15); UNUSED(p16); UNUSED(p17); UNUSED(p18); UNUSED(p19); END
|
||||
#define EVENT21(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20) 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); UNUSED(p14); UNUSED(p15); UNUSED(p16); UNUSED(p17); UNUSED(p18); UNUSED(p19); UNUSED(p20); END
|
||||
|
||||
|
||||
#endif /* EVENT */
|
||||
|
|
@ -144,7 +158,7 @@ extern Word EventKindControl;
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* <code/eventdef.h> -- Event Logging Definitions
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .source: <design/telemetry/>
|
||||
*
|
||||
|
|
@ -68,7 +68,7 @@
|
|||
*/
|
||||
|
||||
#define EventNameMAX ((size_t)19)
|
||||
#define EventCodeMAX ((EventCode)0x0078)
|
||||
#define EventCodeMAX ((EventCode)0x0082)
|
||||
|
||||
#define EVENT_LIST(EVENT, X) \
|
||||
/* 0123456789012345678 <- don't exceed without changing EventNameMAX */ \
|
||||
|
|
@ -184,11 +184,14 @@
|
|||
EVENT(X, EventClockSync , 0x0075, TRUE, Arena) \
|
||||
EVENT(X, ArenaAccess , 0x0076, TRUE, Arena) \
|
||||
EVENT(X, ArenaPoll , 0x0077, TRUE, Arena) \
|
||||
EVENT(X, ArenaSetEmergency , 0x0078, TRUE, Arena)
|
||||
|
||||
EVENT(X, ArenaSetEmergency , 0x0078, TRUE, Arena) \
|
||||
EVENT(X, VMCompact , 0x0079, TRUE, Arena) \
|
||||
EVENT(X, amcScanNailed , 0x0080, TRUE, Seg) \
|
||||
EVENT(X, AMCTraceEnd , 0x0081, TRUE, Trace) \
|
||||
EVENT(X, TraceStartPoolGen , 0x0082, TRUE, Trace)
|
||||
|
||||
|
||||
/* Remember to update EventNameMAX and EventCodeMAX in eventcom.h!
|
||||
/* Remember to update EventNameMAX and EventCodeMAX above!
|
||||
(These are checked in EventInit.) */
|
||||
|
||||
|
||||
|
|
@ -668,12 +671,62 @@
|
|||
PARAM(X, 6, W, white) /* white reference set */ \
|
||||
PARAM(X, 7, W, rate) /* segs to scan per increment */
|
||||
|
||||
#define EVENT_VMCompact_PARAMS(PARAM, X) \
|
||||
PARAM(X, 0, W, vmem0) /* pre-collection reserved size */ \
|
||||
PARAM(X, 1, W, vmem1) /* pre-compact reseved size*/ \
|
||||
PARAM(X, 2, W, vmem2) /* post-compact reserved size */
|
||||
|
||||
#define EVENT_amcScanNailed_PARAMS(PARAM, X) \
|
||||
PARAM(X, 0, W, loops) /* number of times around the loop */ \
|
||||
PARAM(X, 1, W, summary) /* summary of segment being scanned */ \
|
||||
PARAM(X, 2, W, white) /* scan state white set */ \
|
||||
PARAM(X, 3, W, unfixed) /* scan state unfixed summary */ \
|
||||
PARAM(X, 4, W, fixed) /* scan state fixed summary */ \
|
||||
PARAM(X, 5, W, refset) /* scan state refset */
|
||||
|
||||
#define EVENT_AMCTraceEnd_PARAMS(PARAM, X) \
|
||||
PARAM(X, 0, W, epoch) /* current arena epoch */ \
|
||||
PARAM(X, 1, U, why) /* reason trace started */ \
|
||||
PARAM(X, 2, W, align) /* arena alignment */ \
|
||||
PARAM(X, 3, W, large) /* AMCLargeSegPAGES */ \
|
||||
PARAM(X, 4, W, pRetMin) /* threshold for event */ \
|
||||
/* remaining parameters are copy of PageRetStruct, which see */ \
|
||||
PARAM(X, 5, W, pCond) \
|
||||
PARAM(X, 6, W, pRet) \
|
||||
PARAM(X, 7, W, pCS) \
|
||||
PARAM(X, 8, W, pRS) \
|
||||
PARAM(X, 9, W, sCM) \
|
||||
PARAM(X, 10, W, pCM) \
|
||||
PARAM(X, 11, W, sRM) \
|
||||
PARAM(X, 12, W, pRM) \
|
||||
PARAM(X, 13, W, pRM1) \
|
||||
PARAM(X, 14, W, pRMrr) \
|
||||
PARAM(X, 15, W, pRMr1) \
|
||||
PARAM(X, 16, W, sCL) \
|
||||
PARAM(X, 17, W, pCL) \
|
||||
PARAM(X, 18, W, sRL) \
|
||||
PARAM(X, 19, W, pRL) \
|
||||
PARAM(X, 20, W, pRLr)
|
||||
|
||||
#define EVENT_TraceStartPoolGen_PARAMS(PARAM, X) \
|
||||
PARAM(X, 0, P, chain) /* chain (or NULL for topGen) */ \
|
||||
PARAM(X, 1, B, top) /* 1 for topGen, 0 otherwise */ \
|
||||
PARAM(X, 2, W, index) /* index of generation in the chain */ \
|
||||
PARAM(X, 3, P, gendesc) /* generation description */ \
|
||||
PARAM(X, 4, W, capacity) /* capacity of generation */ \
|
||||
PARAM(X, 5, D, mortality) /* mortality of generation */ \
|
||||
PARAM(X, 6, W, zone) /* zone set of generation */ \
|
||||
PARAM(X, 7, P, pool) /* pool */ \
|
||||
PARAM(X, 8, W, serial) /* pool gen serial number */ \
|
||||
PARAM(X, 9, W, totalSize) /* total size of pool gen */ \
|
||||
PARAM(X, 10, W, newSizeAtCreate) /* new size of pool gen at trace create */
|
||||
|
||||
|
||||
#endif /* eventdef_h */
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* global.c: ARENA-GLOBAL INTERFACES
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001,2003 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .sources: See <design/arena/>. design.mps.thread-safety is relevant
|
||||
|
|
@ -447,24 +447,17 @@ void GlobalsPrepareToDestroy(Globals arenaGlobals)
|
|||
TraceIdMessagesDestroy(arena, ti);
|
||||
TRACE_SET_ITER_END(ti, trace, TraceSetUNIV, arena);
|
||||
|
||||
/* report dropped messages (currently in diagnostic varieties only) */
|
||||
if(arena->droppedMessages > 0) {
|
||||
/* report dropped messages */
|
||||
if(arena->droppedMessages > 0)
|
||||
EVENT1(MessagesDropped, arena->droppedMessages);
|
||||
DIAG_SINGLEF(( "GlobalsPrepareToDestroy_dropped",
|
||||
"arena->droppedMessages = $U", (WriteFU)arena->droppedMessages,
|
||||
NULL ));
|
||||
}
|
||||
|
||||
/* .message.queue.empty: Empty the queue of messages before */
|
||||
/* proceeding to finish the arena. It is important that this */
|
||||
/* is done before destroying the finalization pool as otherwise */
|
||||
/* the message queue would have dangling pointers to messages */
|
||||
/* whose memory has been unmapped. */
|
||||
if(MessagePoll(arena)) {
|
||||
if(MessagePoll(arena))
|
||||
EVENT0(MessagesExist);
|
||||
DIAG_SINGLEF(( "GlobalsPrepareToDestroy_queue",
|
||||
"Message queue not empty", NULL ));
|
||||
}
|
||||
MessageEmpty(arena);
|
||||
|
||||
/* throw away the BT used by messages */
|
||||
|
|
@ -1104,8 +1097,6 @@ void ArenaSetEmergency(Arena arena, Bool emergency)
|
|||
AVERT(Arena, arena);
|
||||
AVERT(Bool, emergency);
|
||||
|
||||
DIAG_SINGLEF(( "ArenaSetEmergency",
|
||||
"emergency: $U", (WriteFU)emergency, NULL ));
|
||||
EVENT2(ArenaSetEmergency, arena, emergency);
|
||||
|
||||
arena->emergency = emergency;
|
||||
|
|
@ -1121,7 +1112,7 @@ Bool ArenaEmergency(Arena arena)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2003, 2008 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* locus.c: LOCUS MANAGER
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* DESIGN
|
||||
*
|
||||
|
|
@ -296,12 +296,7 @@ Res ChainCondemnAuto(double *mortalityReturn, Chain chain, Trace trace)
|
|||
} while (genNewSize >= gen->capacity * (Size)1024);
|
||||
|
||||
EVENT3(ChainCondemnAuto, chain, topCondemnedGenSerial, chain->genCount);
|
||||
DIAG_SINGLEF(( "ChainCondemnAuto",
|
||||
"condemn gens [0..$U]", (WriteFU)topCondemnedGenSerial,
|
||||
" (of $U)", (WriteFU)chain->genCount,
|
||||
" of this chain $P.", (WriteFP)chain,
|
||||
NULL ));
|
||||
UNUSED(topCondemnedGenSerial); /* only used for DIAG */
|
||||
UNUSED(topCondemnedGenSerial); /* only used for EVENT */
|
||||
|
||||
/* Condemn everything in these zones. */
|
||||
if (condemnedSet != ZoneSetEMPTY) {
|
||||
|
|
@ -488,7 +483,7 @@ Bool LocusCheck(Arena arena)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ static Res WriteULongest(mps_lib_FILE *stream, ULongest w, unsigned base,
|
|||
buf[i] = pad;
|
||||
}
|
||||
|
||||
r = Stream_fputs(&buf[i], stream);
|
||||
r = mps_lib_fputs(&buf[i], stream);
|
||||
if (r == mps_lib_EOF)
|
||||
return ResIO;
|
||||
|
||||
|
|
@ -308,7 +308,7 @@ static Res WriteDouble(mps_lib_FILE *stream, double d)
|
|||
int j = 0;
|
||||
|
||||
if (F == 0.0) {
|
||||
if (Stream_fputs("0", stream) == mps_lib_EOF)
|
||||
if (mps_lib_fputs("0", stream) == mps_lib_EOF)
|
||||
return ResIO;
|
||||
return ResOK;
|
||||
}
|
||||
|
|
@ -323,7 +323,7 @@ static Res WriteDouble(mps_lib_FILE *stream, double d)
|
|||
for ( ; F >= 1.0 ; F /= 10.0) {
|
||||
E++;
|
||||
if (E > DBL_MAX_10_EXP) {
|
||||
if (Stream_fputs("Infinity", stream) == mps_lib_EOF)
|
||||
if (mps_lib_fputs("Infinity", stream) == mps_lib_EOF)
|
||||
return ResIO;
|
||||
return ResOK;
|
||||
}
|
||||
|
|
@ -410,7 +410,7 @@ static Res WriteDouble(mps_lib_FILE *stream, double d)
|
|||
}
|
||||
buf[j] = '\0'; /* arnold */
|
||||
|
||||
if (Stream_fputs(buf, stream) == mps_lib_EOF)
|
||||
if (mps_lib_fputs(buf, stream) == mps_lib_EOF)
|
||||
return ResIO;
|
||||
return ResOK;
|
||||
}
|
||||
|
|
@ -469,7 +469,7 @@ Res WriteF_firstformat_v(mps_lib_FILE *stream,
|
|||
|
||||
while(*format != '\0') {
|
||||
if (*format != '$') {
|
||||
r = Stream_fputc(*format, stream); /* Could be more efficient */
|
||||
r = mps_lib_fputc(*format, stream); /* Could be more efficient */
|
||||
if (r == mps_lib_EOF) return ResIO;
|
||||
} else {
|
||||
++format;
|
||||
|
|
@ -505,13 +505,13 @@ Res WriteF_firstformat_v(mps_lib_FILE *stream,
|
|||
|
||||
case 'S': { /* string */
|
||||
WriteFS s = va_arg(args, WriteFS);
|
||||
r = Stream_fputs((const char *)s, stream);
|
||||
r = mps_lib_fputs((const char *)s, stream);
|
||||
if (r == mps_lib_EOF) return ResIO;
|
||||
} break;
|
||||
|
||||
case 'C': { /* character */
|
||||
WriteFC c = va_arg(args, WriteFC); /* promoted */
|
||||
r = Stream_fputc((int)c, stream);
|
||||
r = mps_lib_fputc((int)c, stream);
|
||||
if (r == mps_lib_EOF) return ResIO;
|
||||
} break;
|
||||
|
||||
|
|
@ -541,7 +541,7 @@ Res WriteF_firstformat_v(mps_lib_FILE *stream,
|
|||
} break;
|
||||
|
||||
case '$': { /* dollar char */
|
||||
r = Stream_fputc('$', stream);
|
||||
r = mps_lib_fputc('$', stream);
|
||||
if (r == mps_lib_EOF) return ResIO;
|
||||
} break;
|
||||
|
||||
|
|
|
|||
111
mps/code/mpm.h
111
mps/code/mpm.h
|
|
@ -1,7 +1,7 @@
|
|||
/* mpm.h: MEMORY POOL MANAGER DEFINITIONS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001,2003 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .trans.bufferinit: The Buffer data structure has an Init field and
|
||||
|
|
@ -155,14 +155,6 @@ extern Res WriteF_v(mps_lib_FILE *stream, va_list args);
|
|||
extern Res WriteF_firstformat_v(mps_lib_FILE *stream,
|
||||
const char *firstformat, va_list args);
|
||||
|
||||
#if defined(DIAG_WITH_STREAM_AND_WRITEF)
|
||||
extern int Stream_fputc(int c, mps_lib_FILE *stream);
|
||||
extern int Stream_fputs(const char *s, mps_lib_FILE *stream);
|
||||
#else
|
||||
#define Stream_fputc mps_lib_fputc
|
||||
#define Stream_fputs mps_lib_fputs
|
||||
#endif
|
||||
|
||||
|
||||
/* Miscellaneous support -- see <code/mpm.c> */
|
||||
|
||||
|
|
@ -991,6 +983,9 @@ extern void StackProbe(Size depth);
|
|||
* STATISTIC_WRITE is inserted in WriteF arguments to output the values
|
||||
* of statistic fields.
|
||||
*
|
||||
* STATISTIC_BEGIN and STATISTIC_END can be used around a block of
|
||||
* statements.
|
||||
*
|
||||
* .statistic.whitehot: The implementation of STATISTIC for
|
||||
* non-statistical varieties passes the parameter to DISCARD to ensure
|
||||
* the parameter is syntactically an expression. The parameter is
|
||||
|
|
@ -1002,115 +997,29 @@ extern void StackProbe(Size depth);
|
|||
#define STATISTIC(gather) BEGIN (gather); END
|
||||
#define STATISTIC_STAT(gather) BEGIN gather; END
|
||||
#define STATISTIC_WRITE(format, arg) (format), (arg),
|
||||
#define STATISTIC_BEGIN BEGIN
|
||||
#define STATISTIC_END END
|
||||
|
||||
#elif defined(STATISTICS_NONE)
|
||||
|
||||
#define STATISTIC(gather) DISCARD(((gather), 0))
|
||||
#define STATISTIC_STAT DISCARD_STAT
|
||||
#define STATISTIC_WRITE(format, arg)
|
||||
#define STATISTIC_BEGIN BEGIN if (0) {
|
||||
#define STATISTIC_END } END
|
||||
|
||||
#else
|
||||
#else /* !defined(STATISTICS) && !defined(STATISTICS_NONE) */
|
||||
|
||||
#error "No statistics configured."
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* ------------ DIAG_WITH_STREAM_AND_WRITEF --------------- */
|
||||
|
||||
Bool DiagIsOn(void);
|
||||
mps_lib_FILE *DiagStream(void);
|
||||
|
||||
|
||||
/* Diag*F functions -- formatted diagnostic output
|
||||
*
|
||||
* Note: do not call these directly; use the DIAG_*F macros below.
|
||||
*/
|
||||
|
||||
extern void DiagSingleF(const char *tag, ...);
|
||||
extern void DiagFirstF(const char *tag, ...);
|
||||
extern void DiagMoreF(const char *format, ...);
|
||||
extern void DiagEnd(const char *tag);
|
||||
|
||||
|
||||
#if defined(DIAG_WITH_STREAM_AND_WRITEF)
|
||||
|
||||
/* Diagnostic Calculation and Output */
|
||||
#define DIAG_DECL(decl) decl
|
||||
#define DIAG_STREAM (DiagStream())
|
||||
#define DIAG(s) BEGIN \
|
||||
s \
|
||||
END
|
||||
|
||||
|
||||
/* DIAG_*F macros -- formatted diagnostic output
|
||||
*
|
||||
* Note: when invoking these macros, the value passed as macro
|
||||
* argument "args" might contain commas; it must therefore be
|
||||
* enclosed in parentheses. That makes these macros unclean in
|
||||
* all sorts of ways.
|
||||
*/
|
||||
|
||||
#define DIAG_WRITEF(args) DIAG( \
|
||||
if(DiagIsOn()) { \
|
||||
WriteF args; \
|
||||
} \
|
||||
)
|
||||
#define DIAG_SINGLEF(args) DIAG( \
|
||||
DiagSingleF args; \
|
||||
)
|
||||
#define DIAG_FIRSTF(args) DIAG( \
|
||||
DiagFirstF args; \
|
||||
)
|
||||
#define DIAG_MOREF(args) DIAG( \
|
||||
DiagMoreF args; \
|
||||
)
|
||||
|
||||
/* Note: extra parens *not* required when invoking DIAG_END */
|
||||
#define DIAG_END(tag) DIAG( \
|
||||
DiagEnd(tag); \
|
||||
)
|
||||
|
||||
|
||||
#else
|
||||
|
||||
/* Diagnostic Calculation and Output */
|
||||
#define DIAG_DECL(decl)
|
||||
#define DIAG(s) BEGIN END
|
||||
#define DIAG_WRITEF(args) BEGIN END
|
||||
|
||||
/* DIAG_*F macros */
|
||||
#define DIAG_SINGLEF(args) BEGIN END
|
||||
#define DIAG_FIRSTF(args) BEGIN END
|
||||
#define DIAG_MOREF(args) BEGIN END
|
||||
#define DIAG_END(tag) BEGIN END
|
||||
|
||||
#endif
|
||||
|
||||
/* ------------ DIAG_WITH_PRINTF --------------- */
|
||||
|
||||
#if defined(DIAG_WITH_PRINTF)
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define DIAG_PRINTF(args) BEGIN\
|
||||
printf args ; \
|
||||
END
|
||||
|
||||
#else
|
||||
|
||||
#define DIAG_PRINTF(args) BEGIN\
|
||||
END
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* mpm_h */
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2003, 2008 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -66,7 +66,6 @@
|
|||
#include "meter.c"
|
||||
#include "splay.c"
|
||||
#include "cbs.c"
|
||||
#include "diag.c"
|
||||
#include "ss.c"
|
||||
#include "version.c"
|
||||
#include "table.c"
|
||||
|
|
|
|||
|
|
@ -1595,24 +1595,9 @@ static Res amcScanNailed(Bool *totalReturn, ScanState ss, Pool pool,
|
|||
|
||||
refset = ScanStateSummary(ss);
|
||||
|
||||
#if 1
|
||||
/* A rare event, which might prompt a rare defect to appear. */
|
||||
DIAG_SINGLEF(( "amcScanNailed_loop",
|
||||
"scan completed, but had to loop $U times:\n", (WriteFU)loops,
|
||||
" SegSummary: $B\n", (WriteFB)SegSummary(seg),
|
||||
" ss.white: $B\n", (WriteFB)ScanStateWhite(ss),
|
||||
" ss.unfixedSummary: $B", (WriteFB)ScanStateUnfixedSummary(ss),
|
||||
"$S\n", (WriteFS)(
|
||||
(RefSetSub(ScanStateUnfixedSummary(ss), SegSummary(seg)))
|
||||
? ""
|
||||
: " <=== This would have failed .verify.segsummary!"
|
||||
),
|
||||
" ss.fixedSummary: $B\n", (WriteFB)ss->fixedSummary,
|
||||
"ScanStateSummary: $B\n", (WriteFB)refset,
|
||||
"MOVING ScanStateSummary TO fixedSummary, "
|
||||
"RESETTING unfixedSummary.\n", NULL
|
||||
));
|
||||
#endif
|
||||
EVENT6(amcScanNailed, loops, SegSummary(seg), ScanStateWhite(ss),
|
||||
ScanStateUnfixedSummary(ss), ss->fixedSummary, refset);
|
||||
|
||||
ScanStateSetSummary(ss, refset);
|
||||
}
|
||||
|
|
@ -2231,14 +2216,12 @@ static void AMCReclaim(Pool pool, Trace trace, Seg seg)
|
|||
}
|
||||
|
||||
|
||||
/* AMCTraceEnd -- emit end-of-trace diagnostics
|
||||
*
|
||||
*/
|
||||
/* AMCTraceEnd -- emit end-of-trace event */
|
||||
|
||||
static void AMCTraceEnd(Pool pool, Trace trace)
|
||||
{
|
||||
AMC amc;
|
||||
TraceId ti;
|
||||
Count pRetMin = 100;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
AVERT(Trace, trace);
|
||||
|
|
@ -2248,33 +2231,18 @@ static void AMCTraceEnd(Pool pool, Trace trace)
|
|||
ti = trace->ti;
|
||||
AVER(TraceIdCheck(ti));
|
||||
|
||||
if(amc->pageretstruct[ti].pRet >= pRetMin) {
|
||||
DIAG_SINGLEF(( "AMCTraceEnd_pageret",
|
||||
" $U", (WriteFU)ArenaEpoch(pool->arena),
|
||||
" $U", (WriteFU)trace->why,
|
||||
" $U", (WriteFU)amc->pageretstruct[ti].pCond,
|
||||
" $U", (WriteFU)amc->pageretstruct[ti].pRet, ",",
|
||||
" $U", (WriteFU)amc->pageretstruct[ti].pCS,
|
||||
" $U", (WriteFU)amc->pageretstruct[ti].pRS, ",",
|
||||
" $U", (WriteFU)amc->pageretstruct[ti].sCM,
|
||||
" $U", (WriteFU)amc->pageretstruct[ti].pCM,
|
||||
" $U", (WriteFU)amc->pageretstruct[ti].sRM,
|
||||
" $U", (WriteFU)amc->pageretstruct[ti].pRM,
|
||||
" $U", (WriteFU)amc->pageretstruct[ti].pRM1,
|
||||
" $U", (WriteFU)amc->pageretstruct[ti].pRMrr,
|
||||
" $U", (WriteFU)amc->pageretstruct[ti].pRMr1, ",",
|
||||
" $U", (WriteFU)amc->pageretstruct[ti].sCL,
|
||||
" $U", (WriteFU)amc->pageretstruct[ti].pCL,
|
||||
" $U", (WriteFU)amc->pageretstruct[ti].sRL,
|
||||
" $U", (WriteFU)amc->pageretstruct[ti].pRL,
|
||||
" $U", (WriteFU)amc->pageretstruct[ti].pRLr,
|
||||
" (page = $Ub,", (WriteFU)ArenaAlign(pool->arena),
|
||||
" Large >= $Up,", (WriteFU)AMCLargeSegPAGES,
|
||||
" pRetMin $U)", (WriteFU)pRetMin,
|
||||
NULL ));
|
||||
}
|
||||
|
||||
STATISTIC(amc->pageretstruct[ti] = pageretstruct_Zero);
|
||||
STATISTIC_BEGIN {
|
||||
Count pRetMin = 100;
|
||||
PageRetStruct *pr = &amc->pageretstruct[ti];
|
||||
if(pr->pRet >= pRetMin) {
|
||||
EVENT21(AMCTraceEnd, ArenaEpoch(pool->arena), (EventFU)trace->why,
|
||||
ArenaAlign(pool->arena), AMCLargeSegPAGES, pRetMin, pr->pCond,
|
||||
pr->pRet, pr->pCS, pr->pRS, pr->sCM, pr->pCM, pr->sRM, pr->pRM,
|
||||
pr->pRM1, pr->pRMrr, pr->pRMr1, pr->sCL, pr->pCL, pr->sRL,
|
||||
pr->pRL, pr->pRLr);
|
||||
}
|
||||
*pr = pageretstruct_Zero;
|
||||
} STATISTIC_END;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -642,9 +642,6 @@ static Res MRGInit(Pool pool, ArgList args)
|
|||
mrg->sig = MRGSig;
|
||||
|
||||
AVERT(MRG, mrg);
|
||||
DIAG_PRINTF(( "mrg->extendBy = %u, MRGGuardiansPerSeg = %u\n",
|
||||
(unsigned int) mrg->extendBy,
|
||||
(unsigned int) MRGGuardiansPerSeg(mrg) ));
|
||||
EVENT3(PoolInit, pool, PoolArena(pool), ClassOfPool(pool));
|
||||
return ResOK;
|
||||
}
|
||||
|
|
|
|||
145
mps/code/trace.c
145
mps/code/trace.c
|
|
@ -1,7 +1,7 @@
|
|||
/* trace.c: GENERIC TRACER IMPLEMENTATION
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2003, 2006, 2007 Ravenbrook Limited.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited.
|
||||
* See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
|
|
@ -18,7 +18,6 @@ Rank traceBand(Trace);
|
|||
Bool traceBandAdvance(Trace);
|
||||
Bool traceBandFirstStretch(Trace);
|
||||
void traceBandFirstStretchDone(Trace);
|
||||
DIAG_DECL( static void traceFindGrey_diag(Bool found, Rank rank); )
|
||||
|
||||
/* Types */
|
||||
|
||||
|
|
@ -1016,7 +1015,6 @@ static Bool traceFindGrey(Seg *segReturn, Rank *rankReturn,
|
|||
*segReturn = seg;
|
||||
*rankReturn = rank;
|
||||
EVENT4(TraceFindGrey, arena, ti, seg, rank);
|
||||
DIAG( traceFindGrey_diag(TRUE, rank); );
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -1025,77 +1023,12 @@ static Bool traceFindGrey(Seg *segReturn, Rank *rankReturn,
|
|||
AVER(RingIsSingle(ArenaGreyRing(arena, RankAMBIG)));
|
||||
if(!traceBandAdvance(trace)) {
|
||||
/* No grey segments for this trace. */
|
||||
DIAG( traceFindGrey_diag(FALSE, rank); );
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* diagnostic output for traceFindGrey */
|
||||
DIAG_DECL(
|
||||
static void traceFindGrey_diag(Bool found, Rank rank)
|
||||
{
|
||||
char this;
|
||||
static char prev = '.';
|
||||
static int segcount;
|
||||
static char report_array[20];
|
||||
static char *report_lim;
|
||||
int report_maxchars = sizeof(report_array) - 2; /* '.' + '\0' */
|
||||
|
||||
this = (char)(!found ? '.'
|
||||
: (rank == RankAMBIG) ? 'A'
|
||||
: (rank == RankEXACT) ? 'E'
|
||||
: (rank == RankFINAL) ? 'F'
|
||||
: (rank == RankWEAK) ? 'W'
|
||||
: '?');
|
||||
|
||||
if(prev == '.') {
|
||||
/* First seg of new trace */
|
||||
prev = this;
|
||||
segcount = 0;
|
||||
report_lim = report_array;
|
||||
}
|
||||
|
||||
if(this == prev) {
|
||||
segcount += 1;
|
||||
} else {
|
||||
/* Change of rank: add prev rank and segcount to report */
|
||||
if((report_lim - report_array) + 2 > report_maxchars) {
|
||||
/* no space to add 2 chars */
|
||||
report_array[0] = '!';
|
||||
} else {
|
||||
/* prev rank */
|
||||
*report_lim++ = prev;
|
||||
/* prev rank's segcount [0..9, a..z (x10), or *] */
|
||||
if(segcount < 10) {
|
||||
*report_lim++ = (char)('0' + segcount);
|
||||
} else if(segcount < 260) {
|
||||
*report_lim++ = (char)(('a' - 1) + (segcount / 10));
|
||||
} else {
|
||||
*report_lim++ = '*';
|
||||
}
|
||||
}
|
||||
/* begin new rank */
|
||||
prev = this;
|
||||
segcount = 1;
|
||||
}
|
||||
|
||||
if(!found) {
|
||||
/* No more grey in this trace: output report */
|
||||
AVER(this == '.');
|
||||
AVER(segcount == 1); /* single failed attempt to find a seg */
|
||||
*report_lim++ = this;
|
||||
*report_lim++ = '\0';
|
||||
DIAG_SINGLEF(( "traceFindGrey",
|
||||
"rank sequence: $S",
|
||||
(WriteFS)report_array,
|
||||
NULL ));
|
||||
}
|
||||
return;
|
||||
}
|
||||
)
|
||||
|
||||
/* ScanStateSetSummary -- set the summary of scanned references
|
||||
*
|
||||
* This function sets unfixedSummary and fixedSummary such that
|
||||
|
|
@ -1626,36 +1559,15 @@ static Res rootGrey(Root root, void *p)
|
|||
}
|
||||
|
||||
|
||||
static void TraceStartGenDesc_diag(GenDesc desc, Bool top, Index i)
|
||||
static void TraceStartPoolGen(Chain chain, GenDesc desc, Bool top, Index i)
|
||||
{
|
||||
Ring n, nn;
|
||||
|
||||
#if !defined(DIAG_WITH_STREAM_AND_WRITEF)
|
||||
UNUSED(i);
|
||||
#endif
|
||||
|
||||
if(top) {
|
||||
DIAG_WRITEF(( DIAG_STREAM,
|
||||
" GenDesc [top]",
|
||||
NULL ));
|
||||
} else {
|
||||
DIAG_WRITEF(( DIAG_STREAM,
|
||||
" GenDesc [$U]", (WriteFU)i,
|
||||
NULL ));
|
||||
}
|
||||
DIAG_WRITEF(( DIAG_STREAM,
|
||||
" $P capacity: $U KiB, mortality $D\n",
|
||||
(WriteFP)desc, (WriteFU)desc->capacity, (WriteFD)desc->mortality,
|
||||
" ZoneSet:$B\n", (WriteFB)desc->zones,
|
||||
NULL ));
|
||||
RING_FOR(n, &desc->locusRing, nn) {
|
||||
DIAG_DECL( PoolGen gen = RING_ELT(PoolGen, genRing, n); )
|
||||
DIAG_WRITEF(( DIAG_STREAM,
|
||||
" PoolGen $U ($S)",
|
||||
(WriteFU)gen->nr, (WriteFS)gen->pool->class->name,
|
||||
" totalSize $U", (WriteFU)gen->totalSize,
|
||||
" newSize $U\n", (WriteFU)gen->newSizeAtCreate,
|
||||
NULL ));
|
||||
PoolGen gen = RING_ELT(PoolGen, genRing, n);
|
||||
EVENT11(TraceStartPoolGen, chain, top, i, desc,
|
||||
desc->capacity, desc->mortality, desc->zones,
|
||||
gen->pool, gen->nr, gen->totalSize,
|
||||
gen->newSizeAtCreate);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1729,45 +1641,24 @@ Res TraceStart(Trace trace, double mortality, double finishingTime)
|
|||
} while (SegNext(&seg, arena, base));
|
||||
}
|
||||
|
||||
DIAG_FIRSTF(( "TraceStart",
|
||||
"because code $U: $S\n",
|
||||
(WriteFU)trace->why, (WriteFS)TraceStartWhyToString(trace->why),
|
||||
NULL ));
|
||||
|
||||
DIAG( ArenaDescribe(arena, DIAG_STREAM); );
|
||||
|
||||
DIAG_MOREF((
|
||||
" white set:$B\n",
|
||||
(WriteFB)trace->white,
|
||||
NULL ));
|
||||
|
||||
{
|
||||
STATISTIC_BEGIN {
|
||||
/* @@ */
|
||||
/* Iterate over all chains, all GenDescs within a chain, */
|
||||
/* (and all PoolGens within a GenDesc). */
|
||||
Ring node, nextNode;
|
||||
Index i;
|
||||
|
||||
|
||||
RING_FOR(node, &arena->chainRing, nextNode) {
|
||||
Chain chain = RING_ELT(Chain, chainRing, node);
|
||||
DIAG_WRITEF(( DIAG_STREAM,
|
||||
" Chain $P\n", (WriteFP)chain,
|
||||
NULL ));
|
||||
|
||||
for(i = 0; i < chain->genCount; ++i) {
|
||||
GenDesc desc = &chain->gens[i];
|
||||
TraceStartGenDesc_diag(desc, FALSE, i);
|
||||
TraceStartPoolGen(chain, desc, FALSE, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Now do topgen GenDesc (and all PoolGens within it). */
|
||||
DIAG_WRITEF(( DIAG_STREAM,
|
||||
" topGen\n",
|
||||
NULL ));
|
||||
TraceStartGenDesc_diag(&arena->topGen, TRUE, 0);
|
||||
}
|
||||
|
||||
DIAG_END( "TraceStart" );
|
||||
TraceStartPoolGen(NULL, &arena->topGen, TRUE, 0);
|
||||
} STATISTIC_END;
|
||||
|
||||
res = RootsIterate(ArenaGlobals(arena), rootGrey, (void *)trace);
|
||||
AVER(res == ResOK);
|
||||
|
|
@ -1790,7 +1681,7 @@ Res TraceStart(Trace trace, double mortality, double finishingTime)
|
|||
trace->rate = (trace->foundation + sSurvivors) / (unsigned long)nPolls + 1;
|
||||
}
|
||||
|
||||
/* @@ DIAG for rate of scanning here. */
|
||||
/* TODO: compute rate of scanning here. */
|
||||
|
||||
EVENT8(TraceStart, trace, mortality, finishingTime,
|
||||
trace->condemned, trace->notCondemned,
|
||||
|
|
@ -1798,9 +1689,9 @@ Res TraceStart(Trace trace, double mortality, double finishingTime)
|
|||
trace->rate);
|
||||
|
||||
STATISTIC_STAT(EVENT7(TraceStatCondemn, trace,
|
||||
trace->condemned, trace->notCondemned,
|
||||
trace->foundation, trace->rate,
|
||||
mortality, finishingTime));
|
||||
trace->condemned, trace->notCondemned,
|
||||
trace->foundation, trace->rate,
|
||||
mortality, finishingTime));
|
||||
|
||||
trace->state = TraceUNFLIPPED;
|
||||
TracePostStartMessage(trace);
|
||||
|
|
@ -2009,7 +1900,7 @@ failStart:
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2003, 2006, 2007 Ravenbrook Limited
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited
|
||||
* <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* vmix.c: VIRTUAL MEMORY MAPPING FOR UNIX (ISH)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001,2007 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: This is the implementation of the virtual memory mapping
|
||||
* interface (vm.h) for Unix-like operating systems. It was created
|
||||
|
|
@ -167,13 +167,6 @@ Res VMCreate(VM *vmReturn, Size size, void *params)
|
|||
AVERT(VM, vm);
|
||||
|
||||
EVENT3(VMCreate, vm, vm->base, vm->limit);
|
||||
DIAG_SINGLEF((
|
||||
"VM_ix_Create_ok",
|
||||
"[$W..<$W>..$W)",
|
||||
(WriteFW)vm->base,
|
||||
(WriteFW)AddrOffset(vm->base, vm->limit),
|
||||
(WriteFW)vm->limit,
|
||||
NULL ));
|
||||
|
||||
*vmReturn = vm;
|
||||
return ResOK;
|
||||
|
|
@ -193,14 +186,6 @@ void VMDestroy(VM vm)
|
|||
AVERT(VM, vm);
|
||||
AVER(vm->mapped == (Size)0);
|
||||
|
||||
DIAG_SINGLEF((
|
||||
"VM_ix_Destroy",
|
||||
"[$W..<$W>..$W)",
|
||||
(WriteFW)vm->base,
|
||||
(WriteFW)AddrOffset(vm->base, vm->limit),
|
||||
(WriteFW)vm->limit,
|
||||
NULL ));
|
||||
|
||||
/* This appears to be pretty pointless, since the descriptor */
|
||||
/* page is about to vanish completely. However, munmap might fail */
|
||||
/* for some reason, and this would ensure that it was still */
|
||||
|
|
|
|||
|
|
@ -25,14 +25,14 @@ Overview
|
|||
--------
|
||||
|
||||
Diagnostic feedback is information created by the MPS diagnostic
|
||||
system for the purpose of helping MPS programmers client-code
|
||||
system for the purpose of helping MPS programmers and client
|
||||
programmers.
|
||||
|
||||
Such a piece of information is called "a diagnostic". (See also
|
||||
`.parts`_.)
|
||||
|
||||
A diagnostic is not intended to be end-user readable (or visible), or
|
||||
machine-parseable.
|
||||
A diagnostic is not intended to be visible to end users, or readable
|
||||
by them.
|
||||
|
||||
A diagnostic is not intended to be stable from one release to the
|
||||
next: it may be modified or removed at any time.
|
||||
|
|
@ -48,203 +48,78 @@ MPS diagnostic feedback code must do these things:
|
|||
- control (for example, filter) output of diagnostics;
|
||||
- use a channel to get the diagnostic out.
|
||||
|
||||
Note: the knowledge/code/logic for constructing the human-useful
|
||||
message is kept inside normal MPS source code. This means it is always
|
||||
in-sync with changes to the MPS. This also means that any external
|
||||
utilities used to display the messages do not need to understand, or
|
||||
keep in sync with, the details of what's going inside the MPS.
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
To run the MPS and get diagnostic output from it:
|
||||
To get diagnostic output from the MPS, you must use a variety with
|
||||
diagnostics compiled-in. Currently, that means variety.cool. See
|
||||
``config.h``.
|
||||
|
||||
1. Use a variety with diagnostics compiled-in. Currently, that means
|
||||
variety.di. See ``config.h``.
|
||||
There are two mechanism for getting diagnostic output:
|
||||
|
||||
2. Check that the diagnostics you require are generated, by looking in
|
||||
MPS source for invocations of the appropriate macro (for example,
|
||||
``DIAG_SINGLEF()``).
|
||||
1. Automatically via the telemetry system. See design.mps.telemetry,
|
||||
and the "Telemetry" chapter in the manual.
|
||||
|
||||
3. Check that the diagnostics you require will be output, by looking
|
||||
at the diagnostic filter rules in ``diag.c``.
|
||||
2. Manually via the debugger. In the debugger, set break points at the
|
||||
places where you want to inspect data structures (or wait for the
|
||||
debugger to be entered via an ``abort()`` call or unhandled
|
||||
segmentation fault). Then at the debugger command prompt, run
|
||||
``Describe()`` commands of your choice. For example::
|
||||
|
||||
4. Run the MPS and client in an environment that supports the channel
|
||||
used (for example, at a command-line if using ``WriteF()``).
|
||||
(gdb) run
|
||||
Starting program: mv2test
|
||||
Reading symbols for shared libraries +............................. done
|
||||
cbs.c:94: MPS ASSERTION FAILED: !cbs->inCBS
|
||||
|
||||
|
||||
What is a diagnostic?
|
||||
.....................
|
||||
|
||||
A diagnostic has three parts:
|
||||
|
||||
1. a trigger condition, that causes this diagnostic to be emitted;
|
||||
2. a text tag (for example, "TraceStart") which is the name of this
|
||||
diagnostic; and
|
||||
3. a paragraph of human-useful text.
|
||||
|
||||
A diagnostic is emitted by the MPS at a certain point in time when a
|
||||
certain event happens.
|
||||
|
||||
Diagnostics are not nested. Every diagnostic must have a tag. Each
|
||||
diagnostic should have a unique tag (uniqueness is just to help the
|
||||
humans; the diagnostic system does not care).
|
||||
|
||||
The paragraph of text can be many lines long. It usually explains what
|
||||
event caused the diagnostic to be emitted, and commonly also includes
|
||||
the output of some ``Describe()`` methods for various relevant
|
||||
objects. (For example, the ``TraceStart`` diagnostic might call, and
|
||||
include the output generated by, the ``TraceDescribe()`` method).
|
||||
|
||||
How do I control (filter) which diagnostics I see?
|
||||
..................................................
|
||||
|
||||
All diagnostics are emitted and then filtered according to the
|
||||
"diagnostic filter rules".
|
||||
|
||||
The first level of control is filtering by tag. (For example, only
|
||||
show ``TraceStart`` diagnostics).
|
||||
|
||||
The second level of control is filtering by paragraph content. (For
|
||||
example, only show ``TraceStart`` diagnostics where the trace is
|
||||
started because a nursery generation is full).
|
||||
|
||||
The third level of control is filtering by line content. (For example,
|
||||
only show lines containing the word ``whiteSet``).
|
||||
|
||||
See ``diag.c`` for details.
|
||||
|
||||
Note: the entire filtering mechanism can be turned off, so that
|
||||
diagnostics go immediately to ``mps_lib_get_stdout(0``, with no
|
||||
buffering or filtering See impl.c.diag.filter-disable.
|
||||
Program received signal SIGABRT, Aborted.
|
||||
0x00007fff83e42d46 in __kill ()
|
||||
(gdb) frame 12
|
||||
#12 0x000000010000b1fc in MVTFree (pool=0x103ffe160, base=0x101dfd000, size=5024) at poolmv2.c:711
|
||||
711 Res res = CBSInsert(MVTCBS(mvt), base, limit);
|
||||
(gdb) p MVTDescribe(mvt, mps_lib_get_stdout())
|
||||
MVT 0000000103FFE160
|
||||
{
|
||||
minSize: 8
|
||||
meanSize: 42
|
||||
maxSize: 8192
|
||||
fragLimit: 30
|
||||
reuseSize: 16384
|
||||
fillSize: 8192
|
||||
availLimit: 1110835
|
||||
abqOverflow: FALSE
|
||||
splinter: TRUE
|
||||
splinterSeg: 0000000103FEE780
|
||||
splinterBase: 0000000101D7ABB8
|
||||
splinterLimit: 0000000101D7B000
|
||||
# ... etc ...
|
||||
}
|
||||
|
||||
|
||||
How to write a diagnostic
|
||||
-------------------------
|
||||
|
||||
Improve stateless Describe methods where possible
|
||||
.................................................
|
||||
|
||||
Where possible, don't put clever code into an event-triggered
|
||||
diagnostic: put it into a stateless ``Describe()`` method instead, and
|
||||
then call that method when emitting your diagnostic.
|
||||
|
||||
For example::
|
||||
|
||||
FooDescribe(Foo foo, mps_lib_FILE *stream)
|
||||
{
|
||||
/* show value of new "quux" field */
|
||||
WriteF(stream, "Foo: $P { quux: $U }\n", foo, foo->quux);
|
||||
}
|
||||
|
||||
FooWibble(Foo foo)
|
||||
{
|
||||
...
|
||||
DIAG_FIRSTF(( "FooWibble", "Wibbling foo $P", foo, NULL));
|
||||
DIAG( FooDescribe(foo, DIAG_STREAM); );
|
||||
DIAG_END("FooWibble");
|
||||
...
|
||||
}
|
||||
|
||||
This is much better, because other people can use your human-useful
|
||||
output in their diagnostics, or 'live' in a debugger.
|
||||
|
||||
|
||||
Use the output macros
|
||||
.....................
|
||||
|
||||
For a simple diagnostic, use ``DIAG_SINGLEF()``. This begins the tag,
|
||||
puts text into the paragraph, and ends the tag immediately.
|
||||
|
||||
For a more complex diagnostic, the first call must be
|
||||
``DIAG_FIRSTF()``, which begins a diag tag.
|
||||
|
||||
While a tag is current, you can add text to the diagnostic's paragraph
|
||||
using ``DIAG_MOREF()``, and ``WriteF( DIAG_STREAM, ... )``.
|
||||
|
||||
.. note::
|
||||
|
||||
``DIAG_STREAM`` is not a real standard C library stream. If you
|
||||
want stream-level access, you may use ``Stream_fputc()`` and
|
||||
``Stream_fputs()``.
|
||||
|
||||
End the tag by calling ``DIAG_END``.
|
||||
|
||||
|
||||
Compile away in non-diag varieties; no side effects
|
||||
...................................................
|
||||
|
||||
Wrap non-output code with the ``DIAG()`` and ``DIAG_DECL()`` macros,
|
||||
to make sure that non-diag varieties do not execute
|
||||
diagnostic-generating code.
|
||||
Wrap code with the ``STATISTIC`` and ``METER`` macros, to make sure
|
||||
that non-diagnostic varieties do not execute diagnostic-generating
|
||||
code.
|
||||
|
||||
For complex diagnostic-generating code, it may be cleaner to move it
|
||||
into a separate local function. Put ``_diag`` on the end of the function
|
||||
name (for example, ``TraceStart_diag()``).
|
||||
|
||||
Obviously, diagnostic-generating code must have no side effects.
|
||||
|
||||
|
||||
Choosing tags
|
||||
.............
|
||||
|
||||
Tags should be valid C identifiers. Unless you know of a good reason
|
||||
why not. (Not currently checked).
|
||||
|
||||
There's no formal scheme for tag naming, but make it helpful and
|
||||
informally hierarchical, for example, ``TraceBegin``, ``TraceStart``,
|
||||
``TraceEnd``, and so on, not ``BeginTrace``, ``EndTrace``.
|
||||
Diagnostic-generating code must have no side effects.
|
||||
|
||||
|
||||
Writing good paragraph text
|
||||
...........................
|
||||
|
||||
IMPORTANT: Make your diagnostics easy to understand! Other people will
|
||||
read your diagnostics! Make them clear and helpful. Do not make them
|
||||
terse and cryptic. If you use symbols, print a key in the diagnostic.
|
||||
(If you don't want to see this the screen clutter, then you can always
|
||||
add a filter rule to your personal rule set to filter it out).
|
||||
|
||||
|
||||
Maintaining helpful filter rules
|
||||
................................
|
||||
|
||||
If you add a noisy diagnostic, add a rule to the default ruleset to
|
||||
turn it off.
|
||||
Make your diagnostics easy to understand! Other people will read your
|
||||
diagnostics! Make them clear and helpful. Do not make them terse and
|
||||
cryptic. If you use symbols, print a key in the diagnostic.
|
||||
|
||||
|
||||
How the MPS diagnostic system works
|
||||
-----------------------------------
|
||||
|
||||
Channels
|
||||
........
|
||||
|
||||
The recommended channel is ``WriteF()`` to standard output.
|
||||
|
||||
Other possible of future channels might be:
|
||||
|
||||
- ``printf()``;
|
||||
- a new type (yet to be defined) of ``mps_message``;
|
||||
- squirt them into the telemetry-log-events system;
|
||||
- telnet.
|
||||
|
||||
Currently, only ``printf()`` and ``WriteF()`` are supported. See the
|
||||
``DIAG_WITH_`` macros in ``mpm.h``.
|
||||
|
||||
You can also use a debugger to call ``Describe()`` methods directly,
|
||||
from within the debugger.
|
||||
|
||||
Note: it is unfortunate that choice of channel may (for some channels)
|
||||
also dictate the form of the code that synthesises the message. (For
|
||||
example, ``WriteF()`` style parameter-expansion is not possible when
|
||||
using the ``printf()`` channel, because there is no way to get
|
||||
``WriteF()`` to produce its output into a string). This is just a
|
||||
technical hitch; logically, the code that synthesises a diagnostic
|
||||
message should not care which channel will be used to transmit it out
|
||||
of the MPS.
|
||||
|
||||
|
||||
Parts of the MPS diagnostic system
|
||||
..................................
|
||||
|
||||
|
|
@ -252,7 +127,6 @@ _`.parts`: The following facilities are considered part of the MPS
|
|||
diagnostic system:
|
||||
|
||||
- the ``Describe()`` methods.
|
||||
- the ``DIAG`` macros (``DIAG``, ``DIAG_DECL``, ``DIAG_*F``, and so on);
|
||||
- the ``STATISTIC`` macros (see ``mpm.h``);
|
||||
- the ``METER`` macros and meter subsystem.
|
||||
|
||||
|
|
@ -305,6 +179,8 @@ Document History
|
|||
|
||||
- 2013-05-23 GDR_ Converted to reStructuredText.
|
||||
|
||||
- 2013-06-05 GDR_ DIAG part of the system has been removed.
|
||||
|
||||
.. _GDR: http://www.ravenbrook.com/consultants/gdr/
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue