health: build the instrumentation only when asked for

The counters, the phase hooks in idle() and the "health" command are now
behind HEALTH, set from the command line with HEALTH=1. Without it the
hooks are empty macros and the command does not exist, so a default build
carries none of it: on SWTGW218AS that is 1065 bytes of bank 2, 101 of the
common segment and 28 of xdata, plus seven banked calls per main-loop pass.

It is a developer's tool. Reading the dump takes knowing the main loop, and
a user who needs it for a report can build with the flag on, which is how
the kernel treats its lock and latency instrumentation as well.
This commit is contained in:
d00f authored and DrDoof committed 2026-09-21 22:25:32 +02:00
1 parent 2f872ea08e
commit fa0eb91586
5 files changed
+31 -2

No files matched your search

+4
View File
@@ -19,6 +19,10 @@ ifeq ($(MACHINE),)
else else
CC_FLAGS += -DMACHINE_$(MACHINE) CC_FLAGS += -DMACHINE_$(MACHINE)
endif endif
# Health instrumentation and the "health" console command: HEALTH=1 gmake ...
ifneq ($(HEALTH),)
CC_FLAGS += -DHEALTH
endif
ifeq ($(CI),1) ifeq ($(CI),1)
CC_FLAGS += --Werror CC_FLAGS += --Werror
+4
View File
@@ -1849,8 +1849,10 @@ void cmd_parser(void) __banked
} }
} else if (cmd_compare(0, "stp")) { } else if (cmd_compare(0, "stp")) {
stp_parse(); stp_parse();
#ifdef HEALTH
} else if (cmd_compare(0, "health")) { } else if (cmd_compare(0, "health")) {
health_show(); health_show();
#endif
} else if (cmd_compare(0, "pvid")) { } else if (cmd_compare(0, "pvid")) {
if (cmd_words_len == 3 && cmd_parse_port_separator(cmd_words_b[1]) != 0 if (cmd_words_len == 3 && cmd_parse_port_separator(cmd_words_b[1]) != 0
&& atoi_short(cmd_words_b[2]) && atoi_results_short && atoi_results_short <= 4094) && atoi_short(cmd_words_b[2]) && atoi_results_short && atoi_results_short <= 4094)
@@ -2050,6 +2052,7 @@ void execute_commands(__xdata uint8_t *p) __banked {
}; };
} }
#ifdef HEALTH
/* /*
* Health instrumentation. The counters live in xdata and are fed from the * Health instrumentation. The counters live in xdata and are fed from the
* main loop through the banked entry points below; the "health" command * main loop through the banked entry points below; the "health" command
@@ -2205,3 +2208,4 @@ void health_show(void) __banked
print_short(management_vlan); print_short(management_vlan);
write_char('\n'); write_char('\n');
} }
#endif
+11 -1
View File
@@ -9,7 +9,10 @@ extern __xdata uint8_t cmd_buffer[CMD_BUF_SIZE];
extern __xdata uint8_t cmd_available; extern __xdata uint8_t cmd_available;
extern __xdata uint8_t err_status; extern __xdata uint8_t err_status;
/* Phase ids of the health instrumentation, in main-loop order */ /* Health instrumentation, built with HEALTH=1. Without it the hooks below
* compile to nothing and the "health" command does not exist. */
#ifdef HEALTH
/* Phase ids, in main-loop order */
#define HEALTH_PH_LINK 0 #define HEALTH_PH_LINK 0
#define HEALTH_PH_SFP 1 #define HEALTH_PH_SFP 1
#define HEALTH_PH_RX 2 #define HEALTH_PH_RX 2
@@ -19,11 +22,18 @@ extern __xdata uint8_t err_status;
#define HEALTH_PHASES 6 #define HEALTH_PHASES 6
extern __xdata uint16_t health_rx_frames; extern __xdata uint16_t health_rx_frames;
#define health_rx_frame() health_rx_frames++
void health_loop_start(void) __banked; /* once per idle() pass, resets the phase baseline */ void health_loop_start(void) __banked; /* once per idle() pass, resets the phase baseline */
void health_phase(uint8_t id) __banked; /* after each phase; accounts ticks since last checkpoint */ void health_phase(uint8_t id) __banked; /* after each phase; accounts ticks since last checkpoint */
void health_stack_paint(void) __banked; /* paint the unused stack area once at boot */ void health_stack_paint(void) __banked; /* paint the unused stack area once at boot */
void health_show(void) __banked; /* "health" CLI dump */ void health_show(void) __banked; /* "health" CLI dump */
#else
#define health_rx_frame()
#define health_loop_start()
#define health_phase(id)
#define health_stack_paint()
#endif
void cmd_tokenize(void) __banked; void cmd_tokenize(void) __banked;
void cmd_parser(void) __banked; void cmd_parser(void) __banked;
+11
View File
@@ -20,6 +20,17 @@ tcp st 00 tmr 00 rtx 00 rto 00 len 0x0000 mss 0x05b4
httpd left 0x0000 entry 00 stp 01 mvlan 0x0002 httpd left 0x0000 entry 00 stp 01 mvlan 0x0002
``` ```
The instrumentation is not part of a default build. It costs about 1.1 kB
of bank 2, a few bytes of xdata and seven banked calls per main-loop pass,
which is nothing a user needs unless they are chasing a problem, so it is
switched on at build time:
```
make MACHINE=SWTGW218AS HEALTH=1
```
Without it the hooks compile to nothing and `health` is not a command.
All figures are raw hex. The counters are cumulative: take two dumps a known All figures are raw hex. The counters are cumulative: take two dumps a known
time apart and the differences give the rates. time apart and the differences give the rates.
+1 -1
View File
@@ -1004,7 +1004,7 @@ void handle_rx(void)
REG_SET(RTL837X_REG_NIC_RXCMD, 1); REG_SET(RTL837X_REG_NIC_RXCMD, 1);
return; return;
} }
health_rx_frames++; health_rx_frame();
#ifdef RXTXDBG #ifdef RXTXDBG
print_string("\n<< "); print_string("\n<< ");