Skip to content

Commit

Permalink
Add api to get per cpu usage
Browse files Browse the repository at this point in the history
Updated /proc/stat to be compatible with Linux's implementation.
  • Loading branch information
nimelehin committed Dec 10, 2020
1 parent 4af1e7e commit f71966d
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 5 deletions.
26 changes: 24 additions & 2 deletions fs/proc/root.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,30 @@ static int proc_show_version(struct proc_entry *UNUSED(entry), struct proc_data
}

static int proc_show_stat(struct proc_entry *UNUSED(entry), struct proc_data *buf) {
struct cpu_usage usage = get_cpu_usage();
proc_printf(buf, "cpu %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64"\n", usage.user_ticks, usage.nice_ticks, usage.system_ticks, usage.idle_ticks);
int ncpus = get_cpu_count();
struct cpu_usage total_usage = get_total_cpu_usage();
struct cpu_usage* per_cpu_usage = 0;
struct uptime_info uptime_info = get_uptime();
unsigned uptime = uptime_info.uptime_ticks;

proc_printf(buf, "cpu %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64" 0 0 0 0\n", total_usage.user_ticks, total_usage.nice_ticks, total_usage.system_ticks, total_usage.idle_ticks);

int err = get_per_cpu_usage(&per_cpu_usage);
if (!err) {
for (int i = 0; i < ncpus; i++) {
proc_printf(buf, "cpu%d %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64" 0 0 0 0\n", i, per_cpu_usage[i].user_ticks, per_cpu_usage[i].nice_ticks, per_cpu_usage[i].system_ticks, per_cpu_usage[i].idle_ticks);
}
free(per_cpu_usage);
}

int blocked_task_count = get_count_of_blocked_tasks();
int alive_task_count = get_count_of_alive_tasks();
proc_printf(buf, "ctxt 0\n");
proc_printf(buf, "btime %u\n", uptime);
proc_printf(buf, "processes %d\n", alive_task_count);
proc_printf(buf, "procs_running %d\n", alive_task_count - blocked_task_count);
proc_printf(buf, "procs_blocked %d\n", blocked_task_count);

return 0;
}

Expand Down
37 changes: 36 additions & 1 deletion platform/darwin.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#include <errno.h>
#include <mach/mach.h>
#include <sys/sysctl.h>
#include <sys/time.h>
#include <sys/mman.h>
#include "platform/platform.h"
#include "debug.h"

struct cpu_usage get_cpu_usage() {
struct cpu_usage get_total_cpu_usage() {
host_cpu_load_info_data_t load;
mach_msg_type_number_t fuck = HOST_CPU_LOAD_INFO_COUNT;
host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t) &load, &fuck);
Expand Down Expand Up @@ -68,3 +71,35 @@ int get_cpu_count() {
sysctlbyname("hw.ncpu", &ncpu, &size, NULL, 0);
return ncpu;
}

int get_per_cpu_usage(struct cpu_usage** cpus_usage) {
mach_msg_type_number_t info_size = sizeof(processor_cpu_load_info_t);
processor_cpu_load_info_t sys_load_data = 0;
natural_t ncpu;

int err = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &ncpu, (processor_info_array_t*)&sys_load_data, &info_size);
if (err) {
STRACE("Unable to get per cpu usage");
return err;
}

struct cpu_usage* cpus_load_data = (struct cpu_usage*)calloc(ncpu, sizeof(struct cpu_usage));
if (!cpus_load_data) {
return -ENOMEM;
}

for (natural_t i = 0; i < ncpu; i++) {
cpus_load_data[i].user_ticks = sys_load_data[i].cpu_ticks[CPU_STATE_USER];
cpus_load_data[i].system_ticks = sys_load_data[i].cpu_ticks[CPU_STATE_SYSTEM];
cpus_load_data[i].idle_ticks = sys_load_data[i].cpu_ticks[CPU_STATE_IDLE];
cpus_load_data[i].nice_ticks = sys_load_data[i].cpu_ticks[CPU_STATE_NICE];
}
*cpus_usage = cpus_load_data;

// Freeing cpu load information
if (sys_load_data) {
munmap(sys_load_data, vm_page_size);
}

return 0;
}
28 changes: 27 additions & 1 deletion platform/linux.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include <errno.h>
#include <sys/sysinfo.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "platform/platform.h"
#include "debug.h"
Expand All @@ -16,7 +18,7 @@ static void read_proc_line(const char *file, const char *name, char *buf) {
fclose(f);
}

struct cpu_usage get_cpu_usage() {
struct cpu_usage get_total_cpu_usage() {
struct cpu_usage usage = {};
char buf[1234];
read_proc_line("/proc/stat", "cpu", buf);
Expand Down Expand Up @@ -55,3 +57,27 @@ struct uptime_info get_uptime() {
int get_cpu_count() {
return get_nprocs();
}

int get_per_cpu_usage(struct cpu_usage** cpus_usage) {
char buf[1234];
char cpu_title[8];
int ncpu = get_cpu_count();
struct cpu_usage* cpus_load_data = (struct cpu_usage*)calloc(ncpu, sizeof(struct cpu_usage));
if (!cpus_load_data) {
return -ENOMEM;
}

for (int i = 0; i < ncpu; i++) {
int cpu_num;
int title_len = snprintf(cpu_title, 8, "cpu%d", i);
if (title_len > 8 || title_len < 0) {
STRACE("Can't load info of cpu %d (>10000)", i);
free(cpus_load_data);
return -ENOMEM;
}
read_proc_line("/proc/stat", cpu_title, buf);
sscanf(buf, "cpu%d %"SCNu64" %"SCNu64" %"SCNu64" %"SCNu64"\n", &cpu_num, &cpus_load_data[i].user_ticks, &cpus_load_data[i].system_ticks, &cpus_load_data[i].idle_ticks, &cpus_load_data[i].nice_ticks);
}
*cpus_usage = cpus_load_data;
return 0;
}
3 changes: 2 additions & 1 deletion platform/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ struct cpu_usage {
uint64_t idle_ticks;
uint64_t nice_ticks;
};
struct cpu_usage get_cpu_usage(void);
struct cpu_usage get_total_cpu_usage(void);
int get_per_cpu_usage(struct cpu_usage** cpus_usage);

struct mem_usage {
uint64_t total;
Expand Down

0 comments on commit f71966d

Please sign in to comment.