[dfs][procfs] Fix Linux-compatible procfs fields

Grow maps without a 256 VMA cap, skip RSS walks for maps, report
matching status text, real RSS/statm, MemAvailable after page-pool
free pages, load averages plus last PID, cumulative processes, RV32
cpuinfo, and per-character mount escaping.
This commit is contained in:
bernard
2026-08-30 20:49:24 +08:00
committed by Rbb666
parent 04b19b35e3
commit 5dcbc0dec9
8 changed files with 279 additions and 49 deletions
@@ -76,7 +76,11 @@ static int seq_show(struct dfs_seq_file *seq, void *data)
dfs_seq_printf(seq, "CPU revision\t: %lu\n", (unsigned long)revision);
#elif defined(__riscv)
dfs_seq_puts(seq, "model name\t: RISC-V Generic\n");
#if defined(__riscv_xlen) && (__riscv_xlen == 32)
dfs_seq_puts(seq, "isa\t\t: rv32\n");
#else
dfs_seq_puts(seq, "isa\t\t: rv64\n");
#endif
#else
dfs_seq_puts(seq, "model name\t: RT-Thread Generic CPU\n");
#endif
@@ -19,10 +19,8 @@
#include <dfs_dentry.h>
#ifdef RT_USING_SMART
#include "lwp_pid.h"
#ifdef RT_USING_MUSLLIBC
#include "lwp.h"
#endif
#include "lwp_pid.h"
#endif
#ifdef RT_USING_SMART
@@ -32,6 +30,18 @@ struct loadavg_count
int runnable;
};
/* Fixed-point load averages, 11 bits of fraction like Linux FSHIFT. */
#define PROC_LOAD_FSHIFT 11
#define PROC_LOAD_FIXED_1 (1UL << PROC_LOAD_FSHIFT)
#define PROC_LOAD_EXP_1 1884UL /* 1 / exp(5s / 60s) * 2048 */
#define PROC_LOAD_EXP_5 2014UL /* 1 / exp(5s / 300s) * 2048 */
#define PROC_LOAD_EXP_15 2037UL /* 1 / exp(5s / 900s) * 2048 */
static unsigned long load_1 = 0;
static unsigned long load_5 = 0;
static unsigned long load_15 = 0;
static rt_tick_t load_last_tick = 0;
static int loadavg_count_pid(pid_t pid, void *arg)
{
struct loadavg_count *count = (struct loadavg_count *)arg;
@@ -42,7 +52,6 @@ static int loadavg_count_pid(pid_t pid, void *arg)
return 0;
}
count->total++;
#ifdef RT_USING_MUSLLIBC
{
rt_list_t *node;
@@ -50,7 +59,9 @@ static int loadavg_count_pid(pid_t pid, void *arg)
while (node != &lwp->t_grp)
{
rt_thread_t thread = rt_list_entry(node, struct rt_thread, sibling);
if (RT_SCHED_CTX(thread).stat == RT_THREAD_RUNNING)
int stat = RT_SCHED_CTX(thread).stat & RT_THREAD_STAT_MASK;
if (stat == RT_THREAD_RUNNING || stat == RT_THREAD_READY)
{
count->runnable++;
break;
@@ -58,18 +69,62 @@ static int loadavg_count_pid(pid_t pid, void *arg)
node = node->next;
}
}
#endif
return 0;
}
static void loadavg_fold(unsigned long active)
{
load_1 = load_1 * PROC_LOAD_EXP_1 / PROC_LOAD_FIXED_1 +
active * (PROC_LOAD_FIXED_1 - PROC_LOAD_EXP_1) / PROC_LOAD_FIXED_1;
load_5 = load_5 * PROC_LOAD_EXP_5 / PROC_LOAD_FIXED_1 +
active * (PROC_LOAD_FIXED_1 - PROC_LOAD_EXP_5) / PROC_LOAD_FIXED_1;
load_15 = load_15 * PROC_LOAD_EXP_15 / PROC_LOAD_FIXED_1 +
active * (PROC_LOAD_FIXED_1 - PROC_LOAD_EXP_15) / PROC_LOAD_FIXED_1;
}
static void loadavg_update(unsigned long active)
{
rt_tick_t now = rt_tick_get();
rt_tick_t period = RT_TICK_PER_SECOND * 5;
if (load_last_tick == 0)
{
load_1 = load_5 = load_15 = active;
load_last_tick = now;
return;
}
while ((rt_tick_t)(now - load_last_tick) >= period)
{
loadavg_fold(active);
load_last_tick += period;
}
}
static void loadavg_print(struct dfs_seq_file *seq, unsigned long load)
{
unsigned long integer = load >> PROC_LOAD_FSHIFT;
unsigned long frac = ((load & (PROC_LOAD_FIXED_1 - 1)) * 100) >> PROC_LOAD_FSHIFT;
dfs_seq_printf(seq, "%lu.%02lu", integer, frac);
}
#endif
static int single_show(struct dfs_seq_file *seq, void *data)
{
RT_UNUSED(data);
#ifdef RT_USING_SMART
struct loadavg_count count = { 0, 0 };
lwp_pid_for_each(loadavg_count_pid, &count);
dfs_seq_printf(seq, "0.00 0.00 0.00 %d/%d 0\n", count.runnable, count.total);
loadavg_update(((unsigned long)count.runnable) << PROC_LOAD_FSHIFT);
loadavg_print(seq, load_1);
dfs_seq_puts(seq, " ");
loadavg_print(seq, load_5);
dfs_seq_puts(seq, " ");
loadavg_print(seq, load_15);
dfs_seq_printf(seq, " %d/%d %d\n", count.runnable, count.total,
(int)lwp_pid_get_last());
#else
dfs_seq_puts(seq, "0.00 0.00 0.00 0/0 0\n");
#endif
@@ -35,12 +35,12 @@ static int single_show(struct dfs_seq_file *seq, void *data)
total_freed = total_freed + total - used;
dfs_seq_printf(seq, "%-16s%8lu kB\n", "MemMaxUsed:", (unsigned long)(max_used / 1024));
dfs_seq_printf(seq, "%-16s%8lu kB\n", "MemAvailable:", (unsigned long)((total - used) / 1024));
rt_page_get_info(&total, &freed);
total_sum = total_sum + total * RT_MM_PAGE_SIZE;
total_freed = total_freed + freed * RT_MM_PAGE_SIZE;
dfs_seq_printf(seq, "%-16s%8lu kB\n", "MemAvailable:", (unsigned long)(total_freed / 1024));
dfs_seq_printf(seq, "%-16s%8lu kB\n", "MemTotal:", (unsigned long)(total_sum / 1024));
dfs_seq_printf(seq, "%-16s%8lu kB\n", "MemFree:", (unsigned long)(total_freed / 1024));
dfs_seq_printf(seq, "%-16s%8lu kB\n", "Buffers:", 0UL);
@@ -29,35 +29,43 @@ static void mnt_escape(const char *source, char *target, rt_size_t target_size)
return;
}
while (*cursor != '\0' && offset + 4 < target_size)
while (*cursor != '\0')
{
const char *escape = RT_NULL;
rt_size_t need = 1;
if (*cursor == ' ')
{
target[offset++] = '\\';
target[offset++] = '0';
target[offset++] = '4';
target[offset++] = '0';
escape = "\\040";
need = 4;
}
else if (*cursor == '\t')
{
target[offset++] = '\\';
target[offset++] = '0';
target[offset++] = '1';
target[offset++] = '1';
escape = "\\011";
need = 4;
}
else if (*cursor == '\n')
{
target[offset++] = '\\';
target[offset++] = '0';
target[offset++] = '1';
target[offset++] = '2';
escape = "\\012";
need = 4;
}
else if (*cursor == '\\')
{
target[offset++] = '\\';
target[offset++] = '1';
target[offset++] = '3';
target[offset++] = '4';
escape = "\\134";
need = 4;
}
if (offset + need >= target_size)
{
break;
}
if (escape)
{
target[offset++] = escape[0];
target[offset++] = escape[1];
target[offset++] = escape[2];
target[offset++] = escape[3];
}
else
{
File diff suppressed because it is too large Load Diff
@@ -118,7 +118,7 @@ static int seq_show(struct dfs_seq_file *seq, void *data)
{
struct stat_process_count process_count = { 0, 0 };
lwp_pid_for_each(stat_process_count, &process_count);
dfs_seq_printf(seq, "processes %d\n", process_count.total);
dfs_seq_printf(seq, "processes %lu\n", lwp_pid_get_create_count());
dfs_seq_printf(seq, "procs_running %d\n", process_count.running);
dfs_seq_puts(seq, "procs_blocked 0\n");
}
+24
View File
@@ -68,6 +68,7 @@ static struct lwp_avl_struct *lwp_pid_free_head = RT_NULL;
static int lwp_pid_ary_alloced = 0;
static struct lwp_avl_struct *lwp_pid_root = RT_NULL;
static pid_t current_pid = 0;
static unsigned long lwp_create_count = 0;
static struct rt_mutex pid_mtx;
static struct rt_wqueue _pid_emptyq;
@@ -166,6 +167,28 @@ static int _before_cb(struct lwp_avl_struct *node, void *data)
return param->cb(pid, param->data);
}
unsigned long lwp_pid_get_create_count(void)
{
unsigned long count;
lwp_pid_lock_take();
count = lwp_create_count;
lwp_pid_lock_release();
return count;
}
pid_t lwp_pid_get_last(void)
{
pid_t pid;
lwp_pid_lock_take();
pid = current_pid;
lwp_pid_lock_release();
return pid;
}
/**
* @brief Iterate over all process IDs
*
@@ -694,6 +717,7 @@ rt_lwp_t lwp_create(rt_base_t flags)
{
new_lwp->pid = pid;
lwp_pid_set_lwp_locked(pid, new_lwp);
lwp_create_count++;
}
lwp_pid_lock_release();
}
+2
View File
@@ -28,6 +28,8 @@ struct lwp_avl_struct *lwp_get_pid_ary(void);
int lwp_pid_init(void);
int lwp_pid_wait_for_empty(int wait_flags, rt_tick_t to);
int lwp_pid_for_each(int (*cb)(pid_t pid, void *data), void *data);
unsigned long lwp_pid_get_create_count(void);
pid_t lwp_pid_get_last(void);
void lwp_pid_put(struct rt_lwp *lwp);
void lwp_pid_rollback(struct rt_lwp *lwp);
void lwp_pid_lock_take(void);