- sdk/meow_time32: 抽出可独立链接的 o32 time32 取时/睡眠设施(不依赖 meow_ui.a, watchdog 等独立静态组件可直接链;可选 -DMEOW_TIME32_LIBC_OVERRIDES 接管 libc 入口) - watchdog: now_ms/usleep 改走 time32(修复 held 变天文数字→每次单击都弹菜单); 阈值读 power.longpress_menu_ms/forceoff_ms(缺省 3000/8000),删除 PWR_TOGGLE_MS==PWR_MENU_MS;新增 wd_power.h 纯判定 + 宿主行为矩阵测试 - launcher: App 前台电源菜单补齐 §10.5(notif 全抑制 + 帧恢复 + SIGCONT 排空 + 标记翻回前台);show_power_menu 恢复进入前背景帧(关闭后不再停留菜单画面); 重绘挪到首轮按键采样之后;activity 标记排空窗 + 会话入口清理 + manual_off 去闩锁 - lock_screen: 电源改按下边沿 + 进场 300ms 才熄屏;电源熄屏退出也恢复底层帧; launcher 在 SIGCONT 前写 /tmp/meow_app_repaint,SDK present 消费并 dirty_full - power_menu: 菜单内强关接 power.forceoff_ms(按 longpress 抵扣),日志不再谎称 8s - 重编 meow_ui.a 并重链 meow_launcherd/ncm/files/hello/reader(picbrowser 无源码) - fw_content.conf: 同步 launcherd/watchdog 新 md5;顺带修正 M35 遗留的 nyai 失效钉值 Host: test_wd_fw 66/66、test_overlay_gate 40/40、test_meow_time64/time/repaint PASS。 真机未验证(设备关机);未刷机、未写设备。
192 lines
6.3 KiB
C
192 lines
6.3 KiB
C
/* meow_time32.c — mipsel o32 内核 time32 ABI 兜底(独立链接,不依赖 meow_ui.a)。
|
||
*
|
||
* 根因与逐项证据:sdk/CLOCK_ABI.md(M11/M16)。核心一句话:
|
||
* zig 0.17 的 musl 在 mipsel 上按 `#if defined(SYS_x_time64) && !defined(__ILP32__)`
|
||
* 守卫 time64 回退,而 zig clang 又预定义了 __ILP32__,于是「time64 入口」被编成
|
||
* 老的 time32 实现:内核只写 8 字节 {int32 sec; int32 nsec;},调用方却按 16 字节
|
||
* 结构读。本文件不猜 libc 头的结构宽度,**直接按内核 ABI 取数/睡眠**。
|
||
*
|
||
* 本 TU 不引用 SDK 符号;系统组件(watchdog 等)可单独链接它。宿主(非 mips o32)
|
||
* 自动退回 libc 的 clock_gettime/nanosleep,行为等价,宿主单测可直接编译运行。
|
||
*/
|
||
#include <errno.h>
|
||
#include <stdint.h>
|
||
#include <time.h>
|
||
#include <unistd.h>
|
||
|
||
#include "meow_time32.h"
|
||
|
||
#if defined(__mips__) && !defined(__mips64) && (__SIZEOF_LONG__ == 4)
|
||
#define MEOW_TIME32_KERNEL_ABI 1
|
||
#include <sys/syscall.h>
|
||
#else
|
||
#define MEOW_TIME32_KERNEL_ABI 0
|
||
#endif
|
||
|
||
/* ---- 纯换算 ---- */
|
||
|
||
void meow_time32_rel_from_parts(int64_t sec, int64_t nsec, struct meow_time32 *out)
|
||
{
|
||
if (sec > INT32_MAX) sec = INT32_MAX;
|
||
else if (sec < INT32_MIN) sec = INT32_MIN;
|
||
out->tv_sec = (int32_t)sec;
|
||
out->tv_nsec = (int32_t)nsec;
|
||
}
|
||
|
||
int meow_time32_abs_from_parts(int64_t sec, int64_t nsec, struct meow_time32 *out)
|
||
{
|
||
if (sec > INT32_MAX || sec < INT32_MIN) return -1;
|
||
out->tv_sec = (int32_t)sec;
|
||
out->tv_nsec = (int32_t)nsec;
|
||
return 0;
|
||
}
|
||
|
||
int meow_time32_itimerspec_from_64(const struct meow_time64_itimerspec *in,
|
||
struct meow_itimerspec32 *out)
|
||
{
|
||
struct meow_itimerspec32 t;
|
||
if (meow_time32_abs_from_parts(in->it_interval.tv_sec, in->it_interval.tv_nsec,
|
||
&t.it_interval)) return -1;
|
||
if (meow_time32_abs_from_parts(in->it_value.tv_sec, in->it_value.tv_nsec,
|
||
&t.it_value)) return -1;
|
||
*out = t;
|
||
return 0;
|
||
}
|
||
|
||
void meow_time64_itimerspec_from_32(const struct meow_itimerspec32 *in,
|
||
struct meow_time64_itimerspec *out)
|
||
{
|
||
out->it_interval.tv_sec = in->it_interval.tv_sec;
|
||
out->it_interval.tv_nsec = in->it_interval.tv_nsec;
|
||
out->it_value.tv_sec = in->it_value.tv_sec;
|
||
out->it_value.tv_nsec = in->it_value.tv_nsec;
|
||
}
|
||
|
||
uint64_t meow_time_ms_from_parts(int64_t sec, int64_t nsec)
|
||
{
|
||
return (uint64_t)sec * 1000u + (uint64_t)nsec / 1000000u;
|
||
}
|
||
|
||
/* ---- 内核取时 ---- */
|
||
|
||
int meow_time32_clock_gettime(int clk, struct meow_time32 *out)
|
||
{
|
||
if (!out) { errno = EFAULT; return -1; }
|
||
#if MEOW_TIME32_KERNEL_ABI
|
||
out->tv_sec = 0;
|
||
out->tv_nsec = 0;
|
||
if (syscall(SYS_clock_gettime32, clk, out) != 0) return -1;
|
||
return 0;
|
||
#else
|
||
struct timespec ts;
|
||
if (clock_gettime((clockid_t)clk, &ts) != 0) return -1;
|
||
out->tv_sec = (int32_t)ts.tv_sec;
|
||
out->tv_nsec = (int32_t)ts.tv_nsec;
|
||
return 0;
|
||
#endif
|
||
}
|
||
|
||
uint64_t meow_time32_monotonic_ms(void)
|
||
{
|
||
struct meow_time32 t;
|
||
if (meow_time32_clock_gettime(CLOCK_MONOTONIC, &t) != 0) return 0;
|
||
return meow_time_ms_from_parts(t.tv_sec, t.tv_nsec);
|
||
}
|
||
|
||
/* ---- 睡眠(usleep 同源受损:16 字节 time64 直接交给 time32 系统调用时 nsec 恒 0,
|
||
* 亚秒睡眠立即返回 → 轮询/退避变忙等空转)---- */
|
||
|
||
int meow_time32_sleep_us(unsigned usec)
|
||
{
|
||
#if MEOW_TIME32_KERNEL_ABI
|
||
struct meow_time32 rq, rm;
|
||
rq.tv_sec = (int32_t)(usec / 1000000u);
|
||
rq.tv_nsec = (int32_t)((usec % 1000000u) * 1000u);
|
||
for (;;) {
|
||
long r = syscall(SYS_nanosleep, &rq, &rm);
|
||
if (r == 0) return 0;
|
||
if (errno != EINTR) return -1;
|
||
rq = rm; /* 被信号打断:按剩余时间续睡 */
|
||
}
|
||
#else
|
||
struct timespec rq, rm;
|
||
rq.tv_sec = (time_t)(usec / 1000000u);
|
||
rq.tv_nsec = (long)((usec % 1000000u) * 1000u);
|
||
for (;;) {
|
||
if (nanosleep(&rq, &rm) == 0) return 0;
|
||
if (errno != EINTR) return -1;
|
||
rq = rm;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
/* ---- 可选:链接期接管 libc 取时/睡眠入口 ----
|
||
* 系统组件加 -DMEOW_TIME32_LIBC_OVERRIDES 编译本文件即可让未改写的 clock_gettime()/
|
||
* usleep() 调用点也恢复正确(静态链接时本对象的强定义覆盖 libc 归档成员)。
|
||
* 不要在同时链接 meow_ui.a(meow_ui_time.o) 的进程里启用——两者符号重复。
|
||
* 与 meow_ui_time.c 的差别:这里只接管取时 + nanosleep;futex 相对超时 / timerfd /
|
||
* clock_settime 的接管仍在 meow_ui_time.c(SDK 消费方自动获得)。 */
|
||
#if MEOW_TIME32_KERNEL_ABI && defined(MEOW_TIME32_LIBC_OVERRIDES)
|
||
|
||
static int32_t meow_time32_clamp(int64_t v)
|
||
{
|
||
if (v > INT32_MAX) return INT32_MAX;
|
||
if (v < 0) return 0;
|
||
return (int32_t)v;
|
||
}
|
||
|
||
int __clock_gettime(clockid_t clk, struct timespec *ts)
|
||
{
|
||
if (!ts) { errno = EFAULT; return -1; }
|
||
struct meow_time32 t;
|
||
if (meow_time32_clock_gettime(clk, &t) != 0) return -1;
|
||
ts->tv_sec = t.tv_sec;
|
||
ts->tv_nsec = t.tv_nsec;
|
||
return 0;
|
||
}
|
||
|
||
int __clock_gettime64(clockid_t clk, struct timespec *ts)
|
||
{
|
||
return __clock_gettime(clk, ts);
|
||
}
|
||
|
||
int __clock_nanosleep(clockid_t clk, int flags, const struct timespec *req, struct timespec *rem)
|
||
{
|
||
struct meow_time32 rq, rm;
|
||
long r;
|
||
|
||
if (clk == CLOCK_THREAD_CPUTIME_ID) return EINVAL;
|
||
if (!req) return EFAULT;
|
||
if (req->tv_nsec < 0 || req->tv_nsec >= 1000000000L) return EINVAL;
|
||
rq.tv_sec = meow_time32_clamp(req->tv_sec);
|
||
rq.tv_nsec = (int32_t)req->tv_nsec;
|
||
rm.tv_sec = 0;
|
||
rm.tv_nsec = 0;
|
||
|
||
if (clk == CLOCK_REALTIME && !flags)
|
||
r = syscall(SYS_nanosleep, &rq, rem ? &rm : 0);
|
||
else
|
||
r = syscall(SYS_clock_nanosleep_time32, clk, flags, &rq, rem ? &rm : 0);
|
||
if (r != 0) return errno;
|
||
if (rem) {
|
||
rem->tv_sec = rm.tv_sec;
|
||
rem->tv_nsec = rm.tv_nsec;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
int __clock_nanosleep_time64(clockid_t clk, int flags, const struct timespec *req,
|
||
struct timespec *rem)
|
||
{
|
||
return __clock_nanosleep(clk, flags, req, rem);
|
||
}
|
||
|
||
int __nanosleep_time64(const struct timespec *req, struct timespec *rem)
|
||
{
|
||
int r = __clock_nanosleep(CLOCK_REALTIME, 0, req, rem);
|
||
if (r) { errno = r; return -1; }
|
||
return 0;
|
||
}
|
||
|
||
#endif /* MEOW_TIME32_KERNEL_ABI && MEOW_TIME32_LIBC_OVERRIDES */
|