MMgr v1.0.0
Zero-heap memory manager in C11. One borrowed buffer, carved by asserted offset.
Loading...
Searching...
No Matches
praet_procurator.h
Go to the documentation of this file.
1/* MMgr - Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2 * SPDX-License-Identifier: AGPL-3.0-or-later OR LicenseRef-Commercial OR LicenseRef-Educational
3 *
4 * Every use falls under AGPL-3.0-or-later unless you hold explicit permission, which is either a
5 * negotiated commercial licensing contract or an educator's license issued to you personally.
6 */
7/**
8 * @file praet_procurator.h
9 * @brief Which states and transitions a run actually reached.
10 * @author dstroy0 (Douglas Quigg) <dquigg123@gmail.com>
11 * @date 2026-09-01
12 *
13 * @note The examination arm. The correctness arm says every case passed, and that says nothing about
14 * which of the machine's states and transitions any case walked through. A four state core with
15 * eight statuses has more paths than a suite this size can cover by accident, and so the ones it
16 * misses are worth knowing before any of it reaches a part.
17 * @note Reports and does not gate. A transition nothing reached is a hole in the cases, and whether it
18 * is worth filling is a reading of the report and not a build failure. The optimization arm is
19 * this same instrument carrying timings.
20 * @note Off unless PRAET_PROCURATOR is 1, and every entry is then a macro expanding to nothing. A
21 * build that did not ask for it carries no counter and no call.
22 * @note Declared here and defined in the suite. The one function that writes a flag word calls these,
23 * and the counters and the table they print belong to a run of the suite, at
24 * test/integration/test_praet_correctness/praet_procurator.c.
25 * @warning A build setting PRAET_PROCURATOR to 1 links against those definitions and fails to link
26 * without them. A shipping image has no reason to set it.
27 * @warning Not a knob praet_iudex.h asks about. Every knob there describes the image a
28 * caller ships; this describes a run of the suite, the harness's business and not
29 * the caller's.
30 */
31#ifndef MMGR_PRAET_PROCURATOR_H
32#define MMGR_PRAET_PROCURATOR_H
33
35
36/**
37 * @brief Whether a run records the work it did, on top of the states it reached.
38 *
39 * @note The optimization arm, and it is the examination arm carrying more counters. It records
40 * work: entries called, channels walked, times the poll short circuited, times the port was
41 * asked anything, and the bytes of state a context costs.
42 * @note No times, and none deliberately. A count of work is the same on every run of one build, and so it
43 * is a fact a host can state. What that work costs is a property of a part, and a number taken
44 * here would be a number about this machine dressed as a number about the library.
45 * @note Reports and does not gate, the same as the examination arm. A count that grew is worth reading
46 * and is not a build failure, because whether it matters is measured somewhere else.
47 */
48#ifndef PRAET_OPTIMIZE
49#define PRAET_OPTIMIZE 0
50#endif
51
52#if (PRAET_OPTIMIZE != 0) && (PRAET_OPTIMIZE != 1)
53#error "PRAET_OPTIMIZE must be 0 or 1."
54#endif
55
56/**
57 * @brief Whether a run records the states and transitions it reached.
58 *
59 * @note Turned on by PRAET_OPTIMIZE as well, since the work counts are read beside the states they
60 * were spent reaching and a report with one half missing says less than either half alone.
61 */
62#ifndef PRAET_PROCURATOR
63#if PRAET_OPTIMIZE
64#define PRAET_PROCURATOR 1
65#else
66#define PRAET_PROCURATOR 0
67#endif
68#endif
69
70#if (PRAET_PROCURATOR != 0) && (PRAET_PROCURATOR != 1)
71#error "PRAET_PROCURATOR must be 0 or 1."
72#endif
73
74#if PRAET_OPTIMIZE && !PRAET_PROCURATOR
75#error "PRAET_OPTIMIZE needs PRAET_PROCURATOR, which it turns on by itself unless something set it to 0."
76#endif
77
78#if PRAET_PROCURATOR
79
80EMBED_BEGIN_DECLS
81
82/**
83 * @brief Records one channel's flag word changing.
84 *
85 * @param[in] channel Channel whose word changed.
86 * @param[in] was The word before.
87 * @param[in] now The word after.
88 * @note Called from the one function that writes a flag word, and that leaves the record complete,
89 * including the sites nobody remembered to instrument.
90 * @note Records the core transition as a pair, and every status bit that came on or went off. A word
91 * that changed only its region descriptor records neither, and nothing here reads the region.
92 */
93void praet_procurator_transitus(embed_word channel, uint32_t was, uint32_t now);
94
95/**
96 * @brief Prints what the run reached, as a table.
97 *
98 * @note Written to stdout, because this is a report a person reads and not a result anything asserts
99 * on. A suite that fails still prints it, which is when it is most worth having.
100 * @note Prints the work the run did as well, where PRAET_OPTIMIZE is on.
101 */
102void praet_procurator_report(void);
103
104EMBED_END_DECLS
105
106#else
107
108/**
109 * @brief Expands to nothing where PRAET_PROCURATOR is 0.
110 *
111 * @param channel_ Channel whose word changed, discarded.
112 * @param was_ The word before, discarded.
113 * @param now_ The word after, discarded.
114 * @note Casts each argument to void, which keeps a build without the instrument from warning about the values
115 * it was handed.
116 */
117#define praet_procurator_transitus(channel_, was_, now_) ((void)(channel_), (void)(was_), (void)(now_))
118
119/**
120 * @brief Expands to nothing where PRAET_PROCURATOR is 0.
121 */
122#define praet_procurator_report() ((void)0)
123
124#endif
125
126#if PRAET_OPTIMIZE
127
128EMBED_BEGIN_DECLS
129
130/**
131 * @brief The pieces of work an optimization run counts.
132 *
133 * @note One id per entry a caller can reach, plus the two things the poll does that are worth telling
134 * apart. Dense from zero, because the counters are an array indexed by these.
135 */
136typedef enum
137{
138 PRAET_OPUS_ADNECTERE = 0, /**< praet_ordo_adnectere ran. */
139 PRAET_OPUS_SEPARARE = 1, /**< praet_ordo_separare ran. */
140 PRAET_OPUS_RELATIO = 2, /**< praet_ordo_relatio ran. */
141 PRAET_OPUS_EFFICERE = 3, /**< praet_ordo_efficere ran. */
142 PRAET_OPUS_COMPLETED = 4, /**< praet_ordo_completed ran. */
143 PRAET_OPUS_RESOLVE = 5, /**< praet_ordo_resolve ran. */
144 PRAET_OPUS_POLL = 6, /**< praet_ordo_poll ran. */
145 PRAET_OPUS_POLL_SHORT = 7, /**< A poll that found nothing to do and returned. */
146 PRAET_OPUS_POLL_WALK = 8, /**< A poll that walked every channel. */
147 PRAET_OPUS_ALVEUS = 9, /**< One channel visited inside a walk. */
148 PRAET_OPUS_PROGRESS = 10, /**< The port was asked how far a channel had got. */
149 PRAET_OPUS_KINDS = 11 /**< How many kinds there are, as the counters are sized by. */
150} PraetOpus;
151
152/**
153 * @brief Counts one piece of work.
154 *
155 * @param[in] kind What was done, as a PraetOpus.
156 */
157void praet_procurator_opus(unsigned kind);
158
159EMBED_END_DECLS
160
161#else
162
163/**
164 * @brief Expands to nothing where PRAET_OPTIMIZE is 0.
165 *
166 * @param kind_ What was done, discarded.
167 */
168#define praet_procurator_opus(kind_) ((void)0)
169
170#endif
171
172#endif
#define praet_procurator_transitus(channel_, was_, now_)
Expands to nothing where PRAET_PROCURATOR is 0.
#define praet_procurator_report()
Expands to nothing where PRAET_PROCURATOR is 0.
#define praet_procurator_opus(kind_)
Expands to nothing where PRAET_OPTIMIZE is 0.
Every bit of the channel flag word, and the assertions that keep the map from drifting.