mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-10-01 08:27:30 +08:00
[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:
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user