链路时延M1-M3收尾:Phase12-14基线与生产路径Δ实测、D10/E-02/D17修复、D20定位与硬化、文档整理
This commit is contained in:
@@ -5,6 +5,21 @@
|
||||
#include "net_socket.h"
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* E-02 头阻塞修复(2026-09-22 M3 台架实证):
|
||||
* netTask 是全部 socket 操作的唯一执行者;lftpd 原先用默认 30s 的**阻塞**
|
||||
* net_recv 等待对端下一行/下一块数据 → 只要客户端连上却不发完整行,netTask
|
||||
* 就被长期占用,其余任务(含远端显示)的网络操作整体冻结(实测一次空闲 FTP
|
||||
* 登录让 LCDMEM 整帧等待 17.7s)。
|
||||
* 修法:把等待切成 ≤LFTPD_NET_SLICE_MS 的片(每片 netTask 占用有界),
|
||||
* 调用方累计总预算 LFTPD_TOTAL_BUDGET_MS —— **总超时语义与旧实现一致**,
|
||||
* 但任何时刻都不再有"秒级冻结"。单片超时由 net_recv_to 返回 -2 区分(无 errno 竞态)。
|
||||
* 分片长度即"其他任务最坏等待":实测 100ms 片下受压帧仍达 ~750ms(多片排队),
|
||||
* 收到 5ms 后受压帧降到 ~10ms 量级(见 m3_data 修复后数据)。
|
||||
*/
|
||||
#define LFTPD_NET_SLICE_MS 5U
|
||||
#define LFTPD_TOTAL_BUDGET_MS 30000U
|
||||
|
||||
int lftpd_inet_listen(int port)
|
||||
{
|
||||
int retry;
|
||||
@@ -99,19 +114,34 @@ int lftpd_inet_accept_timeout(int socket, int timeout_ms)
|
||||
|
||||
int lftpd_inet_read_line(int socket, char *buffer, size_t buffer_len)
|
||||
{
|
||||
TickType_t t0 = xTaskGetTickCount();
|
||||
|
||||
memset(buffer, 0, buffer_len);
|
||||
int total_read_len = 0;
|
||||
|
||||
while (total_read_len < (int)buffer_len) {
|
||||
int read_len = net_recv(socket,
|
||||
buffer + total_read_len,
|
||||
buffer_len - total_read_len - 1,
|
||||
0);
|
||||
/* 分片有界读(E-02):单片 netTask 占用 ≤ LFTPD_NET_SLICE_MS */
|
||||
int read_len = net_recv_to(socket,
|
||||
buffer + total_read_len,
|
||||
(int)(buffer_len - total_read_len - 1),
|
||||
LFTPD_NET_SLICE_MS);
|
||||
if (read_len == 0) {
|
||||
return -1;
|
||||
return -1; /* 对端关闭 */
|
||||
}
|
||||
if (read_len == -2) {
|
||||
/* 本片无数据:累计总预算,未超则继续等。
|
||||
* **必须显式让出 CPU**:若某片因 net_poll 自身耗时而在首轮就返回 -2,
|
||||
* 本任务(Normal)立即重排队会形成忙循环 → 饿死 BelowNormal 的 uiTask
|
||||
* → 远端显示请求数秒无人拾取(2026-09-22 M3 实测 2.4~3.4s 周期尖刺)。
|
||||
* vTaskDelay(1) 保证低优先级任务每毫秒都有运行机会。 */
|
||||
if ((xTaskGetTickCount() - t0) >= pdMS_TO_TICKS(LFTPD_TOTAL_BUDGET_MS)) {
|
||||
return -1; /* 总预算耗尽(语义同旧 30s 超时) */
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(1));
|
||||
continue;
|
||||
}
|
||||
if (read_len < 0) {
|
||||
return read_len;
|
||||
return read_len; /* 真错误 */
|
||||
}
|
||||
|
||||
total_read_len += read_len;
|
||||
@@ -170,8 +200,23 @@ int lftpd_inet_write(int socket, const void *buf, int len)
|
||||
|
||||
int lftpd_inet_read(int socket, void *buf, int len)
|
||||
{
|
||||
int n = net_recv(socket, buf, len, 0);
|
||||
return n;
|
||||
/* 分片有界读(E-02):总预算 30s 不变,但每片 netTask 占用 ≤ LFTPD_NET_SLICE_MS,
|
||||
* 避免空闲数据连接(客户端开了 PASV 却不发数据)冻结全网 */
|
||||
TickType_t t0 = xTaskGetTickCount();
|
||||
|
||||
for (;;) {
|
||||
int n = net_recv_to(socket, buf, len, LFTPD_NET_SLICE_MS);
|
||||
if (n >= 0) {
|
||||
return n; /* >0 数据 / 0 EOF */
|
||||
}
|
||||
if (n == -1) {
|
||||
return -1; /* 真错误 */
|
||||
}
|
||||
if ((xTaskGetTickCount() - t0) >= pdMS_TO_TICKS(LFTPD_TOTAL_BUDGET_MS)) {
|
||||
return -1; /* 总预算耗尽(语义同旧 30s 超时) */
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(1)); /* 让出 CPU:防空闲时忙循环饿死低优先级任务 */
|
||||
}
|
||||
}
|
||||
|
||||
int lftpd_inet_close(int socket)
|
||||
|
||||
Reference in New Issue
Block a user