L3 pending化一期:阻塞recv改挂起请求+主循环节拍完成(netTask零占用),lftpd/timeSync分片协议退役
This commit is contained in:
+22
-24
@@ -25,16 +25,15 @@
|
||||
#define TIME_SYNC_PORT 8888
|
||||
|
||||
/*
|
||||
* E-02 头阻塞修复(timeSync 侧;lftpd 侧见 lftpd_inet.c):
|
||||
* E-02 头阻塞修复 + L3 pending 化(timeSync 侧;lftpd 侧见 lftpd_inet.c):
|
||||
* 旧实现用单次 30s 阻塞 net_recv(默认 NET_RECV_TIMEOUT_MS)等时间包——等待期间
|
||||
* netTask(全部 socket 操作的唯一执行者)被独占,其余任务的网络操作(远端显示 /
|
||||
* FTP)整体停摆(docs/问题记录/错误码传播审计.md E-02)。
|
||||
* 修法:等待切成 ≤TIME_SYNC_NET_SLICE_MS 的片(与 lftpd 同片长 = 其他任务最坏
|
||||
* 等待,见 docs/测试说明/链路延迟测试说明.md §8.3),调用方累计总预算
|
||||
* TIME_SYNC_TOTAL_BUDGET_MS——总超时语义与旧 30s 一致,任何时刻 netTask 占用
|
||||
* 有界;片间 vTaskDelay(1) 让出 CPU,防空闲忙循环饿死低优先级任务。
|
||||
* 2026-09-22 先落地分片有界读(5ms 片),同日 L3 pending 化后改为"挂起请求":
|
||||
* 每次等待 = 一次挂起登记(netTask 零占用,完成按主循环节拍检查),调用方
|
||||
* 单次超时 = 剩余总预算(总等待 ≤ TIME_SYNC_TOTAL_BUDGET_MS,语义与旧 30s
|
||||
* 一致);等待期间调用方在自己上下文睡任务通知,旧分片协议(片长/片间让出)退役。
|
||||
*/
|
||||
#define TIME_SYNC_NET_SLICE_MS 5U
|
||||
#define TIME_SYNC_TOTAL_BUDGET_MS 30000U
|
||||
|
||||
/*
|
||||
@@ -88,10 +87,10 @@ static int time_sync_open_listener(void) {
|
||||
* 函数功能:处理一个已建立的时间同步连接
|
||||
* 入口参数:conn_sock - 已建立的连接 Socket 描述符(单连接模式下即监听 Socket 自身)
|
||||
* 返回值:无
|
||||
* 函数说明:分片有界读取 PC 发来的时间包("TIME"+uint32 大端 本地时间),解析后
|
||||
* 写回 RTC,然后关闭连接。读取用 net_recv_to 5ms 分片(E-02):单片不
|
||||
* 长期占用 netTask,总预算 30s 与旧实现语义一致;跨片累积,容忍时间包
|
||||
* 被 TCP 分段送达
|
||||
* 函数说明:pending 读取 PC 发来的时间包("TIME"+uint32 大端 本地时间),解析后
|
||||
* 写回 RTC,然后关闭连接。每次等待 = 一次挂起请求(netTask 零占用,
|
||||
* L3 pending 化),单次超时 = 剩余总预算(≤30s,语义与旧 30s 阻塞一致);
|
||||
* 跨调用累积,容忍时间包被 TCP 分段送达
|
||||
*/
|
||||
static void time_sync_handle_conn(int conn_sock) {
|
||||
uint8_t buf[16];
|
||||
@@ -99,9 +98,16 @@ static void time_sync_handle_conn(int conn_sock) {
|
||||
TickType_t t0 = xTaskGetTickCount();
|
||||
|
||||
while (got < (int)sizeof(buf)) {
|
||||
/* 分片有界读(E-02):单片 netTask 占用 ≤ TIME_SYNC_NET_SLICE_MS */
|
||||
int n = net_recv_to(conn_sock, buf + got, (int)(sizeof(buf) - got),
|
||||
TIME_SYNC_NET_SLICE_MS);
|
||||
/* 单次预算 = 剩余总预算(L3 pending:等待期 netTask 零占用,调用方
|
||||
* 在自己上下文睡任务通知,旧片间 vTaskDelay(1) 让出退役) */
|
||||
TickType_t elapsed = xTaskGetTickCount() - t0;
|
||||
uint32_t rem = (elapsed >= (TickType_t)pdMS_TO_TICKS(TIME_SYNC_TOTAL_BUDGET_MS)) ? 0U
|
||||
: (uint32_t)((TickType_t)TIME_SYNC_TOTAL_BUDGET_MS - elapsed);
|
||||
if (rem == 0U) {
|
||||
DBG_INFO("time_sync: no TIME packet in 30s, drop conn");
|
||||
break; /* 总预算耗尽(语义同旧 30s 超时) */
|
||||
}
|
||||
int n = net_recv_to(conn_sock, buf + got, (int)(sizeof(buf) - got), rem);
|
||||
if (n > 0) {
|
||||
got += n;
|
||||
if (got >= 8) {
|
||||
@@ -112,18 +118,10 @@ static void time_sync_handle_conn(int conn_sock) {
|
||||
if (n == 0) {
|
||||
break; /* 对端关闭(EOF) */
|
||||
}
|
||||
if (n != -2) {
|
||||
break; /* 真错误 */
|
||||
if (n == -2) {
|
||||
continue; /* 本次预算等满无数据 → 下轮 rem=0 退出 */
|
||||
}
|
||||
/* 本片超时无数据:总预算未耗尽则继续等。
|
||||
* **必须显式让出 CPU**:若某片因 net_poll 自身耗时在首轮就返回 -2,
|
||||
* 本任务(Normal)立即重排队会形成忙循环 → 饿死 BelowNormal 的 uiTask
|
||||
* (lftpd 侧同因,见链路延迟测试说明.md §8.3 第 3 条) */
|
||||
if ((xTaskGetTickCount() - t0) >= pdMS_TO_TICKS(TIME_SYNC_TOTAL_BUDGET_MS)) {
|
||||
DBG_INFO("time_sync: no TIME packet in 30s, drop conn");
|
||||
break; /* 总预算耗尽(语义同旧 30s 超时) */
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(1));
|
||||
break; /* 真错误 */
|
||||
}
|
||||
|
||||
if (got >= 8) {
|
||||
|
||||
Reference in New Issue
Block a user