summaryrefslogtreecommitdiff
path: root/components/dfs/dfs_v2/filesystems/procfs/proc_stat.c
blob: 9b8a6a80c9eea001694ea6ac934da66cb0e4f63f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*
 * Copyright (c) 2006-2023, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 */

#include "proc.h"
#include "procfs.h"

#include <rthw.h>
#include <rtdbg.h>

#include <fcntl.h>
#include <errno.h>

#include <dfs_dentry.h>

#ifdef RT_USING_SMART
#include "lwp_pid.h"
#ifdef RT_USING_MUSLLIBC
#include "lwp.h"
#endif
#endif

#ifdef RT_USING_SMART
struct stat_process_count
{
    int total;
    int running;
};

static int stat_process_count(pid_t pid, void *arg)
{
    struct stat_process_count *count = (struct stat_process_count *)arg;
    struct rt_lwp *lwp = lwp_from_pid_locked(pid);

    if (!lwp)
    {
        return 0;
    }
    count->total++;
#ifdef RT_USING_MUSLLIBC
    {
        rt_list_t *node = lwp->t_grp.next;

        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)
            {
                count->running++;
                break;
            }
            node = node->next;
        }
    }
#endif
    return 0;
}
#endif

static void *seq_start(struct dfs_seq_file *seq, off_t *index)
{
    off_t i = *index; // seq->index

    return NULL + (i == 0);
}

static void seq_stop(struct dfs_seq_file *seq, void *data)
{
}

static void *seq_next(struct dfs_seq_file *seq, void *data, off_t *index)
{
    /* data: The return value of the start or next*/
    off_t i = *index + 1; // seq->index

    *index = i;

    return NULL;
}

static int seq_show(struct dfs_seq_file *seq, void *data)
{
    int i;
    rt_cpu_t pcpu;
    rt_uint64_t user_total = 0;
    rt_uint64_t system_total = 0;
    rt_uint64_t idle_total = 0;

    for (i = 0; i < RT_CPUS_NR; i++)
    {
        pcpu = rt_cpu_index(i);
        user_total = user_total + pcpu->cpu_stat.user;
        system_total = system_total + pcpu->cpu_stat.system;
        idle_total = idle_total + pcpu->cpu_stat.idle;
    }
    dfs_seq_printf(seq, "cpu  %llu 0 %llu %llu 0 0 0 0 0 0\n", user_total, system_total, idle_total);

    for (i = 0; i < RT_CPUS_NR; i++)
    {
        pcpu = rt_cpu_index(i);
        dfs_seq_printf(seq, "cpu%d ", i);
        dfs_seq_printf(seq, "%llu ", pcpu->cpu_stat.user);//user
        dfs_seq_printf(seq, "0 ");//nice
        dfs_seq_printf(seq, "%llu ", pcpu->cpu_stat.system);//system
        dfs_seq_printf(seq, "%llu ", pcpu->cpu_stat.idle);//idle
        dfs_seq_printf(seq, "0 ");//iowait
        dfs_seq_printf(seq, "0 ");//irq
        dfs_seq_printf(seq, "0 ");//softirq
        dfs_seq_printf(seq, "0 0 0\n");//steal,guest,guest_nice
    }

#ifdef RT_USING_SMART
    {
        struct stat_process_count process_count = { 0, 0 };
        lwp_pid_for_each(stat_process_count, &process_count);
        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");
    }
#endif

    return 0;
}

static const struct dfs_seq_ops seq_ops = {
    .start = seq_start,
    .stop = seq_stop,
    .next = seq_next,
    .show = seq_show,
};

rt_weak const struct dfs_seq_ops *stat_get_seq_ops(void)
{
    return &seq_ops;
}

static int proc_open(struct dfs_file *file)
{
    return dfs_seq_open(file, stat_get_seq_ops());
}

static int proc_close(struct dfs_file *file)
{
    return dfs_seq_release(file);
}

static const struct dfs_file_ops file_ops = {
    .open = proc_open,
    .read = dfs_seq_read,
    .lseek = dfs_seq_lseek,
    .close = proc_close,
};

int proc_stat_init(void)
{
    struct proc_dentry *dentry = proc_create_data("stat", 0, NULL, &file_ops, NULL);
    proc_release(dentry);

    return 0;
}
INIT_ENV_EXPORT(proc_stat_init);