Files
MeowOS-For-R3P2/patch_v2/meow_launcherd/mf_logsig.h
T
AskaEth 0d6c56100f fix(m52): r1 评审 P2-1 class 缺失 WARN 去刷屏 + 两个 nit(snprintf clamp / 恒真断言)
P2-1(必修):`multi_font: class %s font %s missing, fallback global` 与上一轮修掉的
enabled 行同在 meow_font_reload_multifont() 里、被 main_menu.c:1385 每 2s 调一次;
命中「某个 font.class_* 非空但文件缺失/不可读」时最多 6 行/2s(3 行/s),比 enabled
行凶 6 倍,会让「空转 60s 日志不增长」在 class 缺失形态下失效。
改法:循环内只记「本轮缺失类别位图」,循环外经新纯函数 mf_missing_warn_mask() 做跃迁
判定(缺失集合不变 → 静默;新类别缺失 → 1 条;恢复后再缺失 → 再 1 条)。回退行为不变
(缺失类别照旧回退全局),日志文本/参数不变。另加 _Static_assert 钉住类别数 ≤32(位图宽度)。

nit:wd_log() 的 snprintf 返回值显式 clamp(原「buf≤511+前缀≤23<544」是隐式不变量);
test_wd_fw 的 "scan finds self" 原断言带 `|| np > 0` 恒真、等于没测 → 改为真查表断言
getpid() 在 wd_rg_pid[] 中且 comm 非空、并与 /proc/self/stat 的 pid/ppid 交叉核对。

验证:test_wd_fw 128 pass/0 fail(原 124,+4 来自强化后的自扫断言);
test_mf_logsig 21 pass/0 fail(原 13,+8 为 P2-1 验收:单类缺失 60s@2s 只 1 条、
缺失集合变化再 1 条、恢复后再缺失再 1 条);launcher 宿主测试 ALL PASS;
三处交叉编译 0 warning(watchdog 100,116 B/25f76950、launcherd 902,044 B/75629078、
audiod 68,732 B/ebb9a7ac 未变=bind hunk 未动)。
2026-11-12 08:02:22 +08:00

78 lines
3.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* mf_logsig.h — 多字体配置的「日志跃迁签名」(纯函数,宿主可单测)。
*
* 为什么需要它(M52):meow_font_reload_multifont() 由 launcher 主循环的 hotplug 轮询
* 每 2s 调一次(main_menu.c),而多字体配置在绝大多数周期里毫无变化。旧实现无条件打
* `multi_font: enabled, %d distinct fonts (global=%s)`,真机 meow_20261111_154540.log
* 6603 行里 5297 行是它(80%,~291KB/406KB),把事故现场唯一的信号淹没了。
*
* 修法不是删日志(首次启用/用户改字体必须留痕),而是把它绑到**配置签名**上:签名变了
* 才打。签名覆盖所有能改变多字体行为的输入 ——
* on(display.multi_font)、全局字体 png(font.file → 生效档)、6 个 font.class_* 的
* 解析后绝对路径、distinct(实际驻留套数)、truncated(超预算截断)。
* 因此「字体集合或 global font 变化」必然换签名,纯粹的时间流逝不会。
*/
#ifndef MF_LOGSIG_H
#define MF_LOGSIG_H
#include <stdint.h>
#include <stdio.h>
#define MF_LOGSIG_SEED 14695981039346656037ULL /* FNV-1a 64 offset basis */
#define MF_LOGSIG_PRIME 1099511628211ULL
/* 把一段字符串折进签名。字段之间补分隔符,防 ("ab","c") 与 ("a","bc") 撞同一值。
* NULL 与 "" 视为同一(配置项为空 = 该类别用全局字体)。 */
static inline uint64_t mf_logsig_mix(uint64_t h, const char *s)
{
if (!s) s = "";
while (*s) {
h ^= (uint64_t)(unsigned char)*s++;
h *= MF_LOGSIG_PRIME;
}
h ^= 0x1f; /* 字段分隔(0x1f = US,不会出现在路径里) */
h *= MF_LOGSIG_PRIME;
return h;
}
/* 多字体配置签名。ncls = 类别数(MEOW_FCLS_COUNT=6),cpng[c] 可为 NULL。
* distinct < 0 表示 config 失败(此时 distinct 无意义,用 -1 编码「失败」)。 */
static inline uint64_t mf_logsig(int on, const char *gpng,
const char *const *cpng, int ncls,
int distinct, int truncated)
{
char num[24];
uint64_t h = MF_LOGSIG_SEED;
snprintf(num, sizeof num, "%d", on ? 1 : 0);
h = mf_logsig_mix(h, num);
h = mf_logsig_mix(h, gpng);
for (int c = 0; c < ncls; c++)
h = mf_logsig_mix(h, (cpng && cpng[c]) ? cpng[c] : "");
snprintf(num, sizeof num, "%d:%d", distinct, truncated ? 1 : 0);
h = mf_logsig_mix(h, num);
return h;
}
/* 日志门控:首次(*valid=0)或签名变化 → 返回 1 并记下;同一签名重复调用 → 0。
* 调用方持有 *last / *valid(文件级静态),因此这就是「只在跃迁时打日志」的全部判定。 */
static inline int mf_logsig_changed(uint64_t *last, int *valid, uint64_t sig)
{
if (*valid && sig == *last) return 0;
*last = sig;
*valid = 1;
return 1;
}
/* 「class 字体缺失」WARN 的跃迁门控(r1 评审 P2-1)。
* mask = 本轮「配置了但缺失/不可读」的类别位图(bit c = MEOW_FCLS_* 第 c 类)。
* 返回 mask 里**上一次没报过**的那些位(本轮该打 WARN 的类别),并把 *logged 更新为 mask。
* 于是:缺失集合不变 → 返回 0(静默);新类别变缺失 → 只返回新增位;
* 某类恢复后再次缺失 → 会重新返回(不是一次性闩锁)。 */
static inline unsigned mf_missing_warn_mask(unsigned *logged, unsigned mask)
{
unsigned fresh = mask & ~(*logged);
*logged = mask;
return fresh;
}
#endif /* MF_LOGSIG_H */