git.cappig.dev / apheleiaOS.git master

1
#include "internal.h"
2
3
bool sched_proc_snapshot(pid_t pid, sched_proc_snapshot_t *out) {
4
    if (!out || pid < 0 || !sched_state.procs.all_list) {
5
        return false;
6
    }
7
8
    u64 hz = arch_timer_hz();
9
10
    bool found = false;
11
    unsigned long flags = sched_lock_save();
12
    sched_thread_t *thread = pid_get(pid);
13
14
    if (!thread) {
15
        ll_foreach(node, sched_state.procs.all_list) {
16
            sched_thread_t *candidate = node->data;
17
18
            if (!candidate || candidate->pid != pid) {
19
                continue;
20
            }
21
22
            thread = candidate;
23
            pid_set(thread);
24
25
            break;
26
        }
27
    }
28
29
    if (thread) {
30
        out->pid = thread->pid;
31
        out->ppid = thread->ppid;
32
        out->pgid = thread->pgid;
33
        out->sid = thread->sid;
34
        out->uid = thread->uid;
35
        out->gid = thread->gid;
36
        out->umask = thread->umask & 0777;
37
        out->signal_pending = __atomic_load_n(&thread->signal_pending, __ATOMIC_ACQUIRE);
38
        out->signal_mask = __atomic_load_n(&thread->signal_mask, __ATOMIC_ACQUIRE);
39
        out->state = thread_get_state(thread);
40
        out->core_id = -1;
41
        out->tty_index = thread->tty_index;
42
43
        for (size_t i = 0; i < MAX_CORES; i++) {
44
            if (sched_state.cpus.cpu[i].current == thread) {
45
                out->core_id = (int)i;
46
                break;
47
            }
48
        }
49
50
        u64 cpu_ticks = __atomic_load_n(&thread->cpu_time_ticks, __ATOMIC_RELAXED);
51
        u64 user_ticks = __atomic_load_n(&thread->user_ticks, __ATOMIC_RELAXED);
52
        u64 sys_ticks = __atomic_load_n(&thread->sys_ticks, __ATOMIC_RELAXED);
53
54
        u64 child_cpu_ticks = __atomic_load_n(&thread->child_cpu_time_ticks, __ATOMIC_RELAXED);
55
        u64 child_user_ticks = __atomic_load_n(&thread->child_user_ticks, __ATOMIC_RELAXED);
56
        u64 child_sys_ticks = __atomic_load_n(&thread->child_sys_ticks, __ATOMIC_RELAXED);
57
58
        out->cpu_time_ms = hz ? ((cpu_ticks * 1000ULL) / hz) : 0;
59
        out->user_time_ms = hz ? ((user_ticks * 1000ULL) / hz) : 0;
60
        out->sys_time_ms = hz ? ((sys_ticks * 1000ULL) / hz) : 0;
61
62
        out->child_cpu_time_ms = hz ? ((child_cpu_ticks * 1000ULL) / hz) : 0;
63
        out->child_user_time_ms = hz ? ((child_user_ticks * 1000ULL) / hz) : 0;
64
        out->child_sys_time_ms = hz ? ((child_sys_ticks * 1000ULL) / hz) : 0;
65
        out->vm_kib = sched_user_mem_kib(thread);
66
67
        memset(out->name, 0, sizeof(out->name));
68
        strncpy(out->name, thread->name, sizeof(out->name) - 1);
69
70
        found = true;
71
    }
72
73
    sched_lock_restore(flags);
74
75
    return found;
76
}
77
78
void sched_cpu_usage_snapshot(u64 *busy_ticks_out, u64 *total_ticks_out) {
79
    if (busy_ticks_out) {
80
        *busy_ticks_out = __atomic_load_n(&sched_state.usage.busy_ticks, __ATOMIC_RELAXED);
81
    }
82
83
    if (total_ticks_out) {
84
        *total_ticks_out = __atomic_load_n(&sched_state.usage.total_ticks, __ATOMIC_RELAXED);
85
    }
86
}
87
88
void sched_cpu_usage_snapshot_core(size_t core_id, u64 *busy_ticks_out, u64 *total_ticks_out) {
89
    if (core_id >= MAX_CORES) {
90
        if (busy_ticks_out) {
91
            *busy_ticks_out = 0;
92
        }
93
94
        if (total_ticks_out) {
95
            *total_ticks_out = 0;
96
        }
97
98
        return;
99
    }
100
101
    if (busy_ticks_out) {
102
        *busy_ticks_out = __atomic_load_n(&sched_state.usage.core_busy_ticks[core_id], __ATOMIC_RELAXED);
103
    }
104
105
    if (total_ticks_out) {
106
        *total_ticks_out = __atomic_load_n(&sched_state.usage.core_total_ticks[core_id], __ATOMIC_RELAXED);
107
    }
108
}
109
110
void sched_metrics_snapshot(sched_metrics_snapshot_t *out) {
111
    if (!out) {
112
        return;
113
    }
114
115
    out->sched_switch_count = __atomic_load_n(&sched_state.metrics.switch_count, __ATOMIC_RELAXED);
116
    out->syscall_count = __atomic_load_n(&sched_state.metrics.syscall_count, __ATOMIC_RELAXED);
117
    out->sched_migrations = __atomic_load_n(&sched_state.metrics.migrations, __ATOMIC_RELAXED);
118
    out->sched_steals = __atomic_load_n(&sched_state.metrics.steals, __ATOMIC_RELAXED);
119
    out->sched_wake_ipi = __atomic_load_n(&sched_state.metrics.wake_ipi, __ATOMIC_RELAXED);
120
    out->sched_runqueue_max = __atomic_load_n(&sched_state.metrics.runqueue_max, __ATOMIC_RELAXED);
121
    out->sched_balance_runs = __atomic_load_n(&sched_state.metrics.balance_runs, __ATOMIC_RELAXED);
122
    out->wait_timeout_count = __atomic_load_n(&sched_state.metrics.wait_timeout_count, __ATOMIC_RELAXED);
123
}
124
125
void sched_metrics_record_syscall(void) {
126
    __atomic_fetch_add(&sched_state.metrics.syscall_count, 1, __ATOMIC_RELAXED);
127
}
128
129
int sched_getgroups_pid(
130
    pid_t pid,
131
    gid_t *primary_gid_out,
132
    gid_t *groups_out,
133
    size_t max_groups,
134
    size_t *group_count_out
135
) {
136
    if (pid <= 0 || !group_count_out || !sched_state.procs.all_list) {
137
        return -EINVAL;
138
    }
139
140
    unsigned long flags = sched_lock_save();
141
    sched_thread_t *thread = find_thread(pid);
142
143
    if (!thread) {
144
        sched_lock_restore(flags);
145
        return -ESRCH;
146
    }
147
148
    if (primary_gid_out) {
149
        *primary_gid_out = thread->gid;
150
    }
151
152
    *group_count_out = thread->group_count;
153
154
    if (groups_out && max_groups) {
155
        size_t copy_count = thread->group_count < max_groups ? thread->group_count : max_groups;
156
157
        for (size_t i = 0; i < copy_count; i++) {
158
            groups_out[i] = thread->groups[i];
159
        }
160
    }
161
162
    sched_lock_restore(flags);
163
164
    return 0;
165
}
166
167
bool sched_proc_cwd(pid_t pid, char *out, size_t out_len) {
168
    if (!out || !out_len || pid <= 0 || !sched_state.procs.all_list) {
169
        return false;
170
    }
171
172
    bool found = false;
173
    unsigned long flags = sched_lock_save();
174
    sched_thread_t *thread = find_thread(pid);
175
176
    if (thread) {
177
        size_t len = strnlen(thread->cwd, sizeof(thread->cwd));
178
179
        if (len + 1 <= out_len) {
180
            memcpy(out, thread->cwd, len);
181
            out[len] = '\0';
182
            found = true;
183
        }
184
    }
185
186
    sched_lock_restore(flags);
187
188
    return found;
189
}
190
191
int sched_signal_send_pgrp(pid_t pgid, int signum) {
192
    if (!sched_state.procs.all_list || pgid <= 0) {
193
        return -1;
194
    }
195
196
    int count = 0;
197
    unsigned long flags = sched_lock_save();
198
199
    ll_foreach(node, sched_state.procs.all_list) {
200
        sched_thread_t *thread = node->data;
201
202
        if (!thread || thread->pgid != pgid) {
203
            continue;
204
        }
205
206
        if (sched_signal_send_thread(thread, signum) >= 0) {
207
            count++;
208
        }
209
    }
210
211
    sched_lock_restore(flags);
212
213
    return count ? count : -1;
214
}
215
216
int sched_signal_pgrp_as(pid_t pgid, int signum, const sched_thread_t *sender) {
217
    if (!sched_state.procs.all_list || pgid <= 0) {
218
        return -ESRCH;
219
    }
220
221
    if (signum < 0 || signum >= NSIG) {
222
        return -EINVAL;
223
    }
224
225
    uid_t uid = sender ? sender->uid : 0;
226
    bool root = uid == 0;
227
    bool denied = false;
228
    int count = 0;
229
230
    unsigned long flags = sched_lock_save();
231
232
    ll_foreach(node, sched_state.procs.all_list) {
233
        sched_thread_t *thread = node->data;
234
235
        if (!thread || thread->pgid != pgid) {
236
            continue;
237
        }
238
239
        if (!root && uid != thread->uid) {
240
            denied = true;
241
            continue;
242
        }
243
244
        if (!signum || sched_signal_send_thread(thread, signum) >= 0) {
245
            count++;
246
        }
247
    }
248
249
    sched_lock_restore(flags);
250
251
    if (count) {
252
        return count;
253
    }
254
255
    return denied ? -EPERM : -ESRCH;
256
}