kernel: more sensible idle tracking

This commit is contained in:
K. Lange 2021-09-05 11:35:38 +09:00
parent 780aa1b534
commit bafc85f675
4 changed files with 73 additions and 46 deletions

View File

@ -35,7 +35,27 @@ static int show_cpu = 0;
static int collect_commandline = 0;
static int cpu_count = 1;
static int widths[] = {3,3,4,3,3,4,4};
enum header_columns {
COLUMN_PID,
COLUMN_TID,
COLUMN_USER,
COLUMN_VSZ,
COLUMN_SHM,
COLUMN_MEM,
COLUMN_CPUA,
COLUMN_CPU
};
static int widths[] = {
[COLUMN_PID] = 3,
[COLUMN_TID] = 3,
[COLUMN_USER] = 4,
[COLUMN_VSZ] = 3,
[COLUMN_SHM] = 3,
[COLUMN_MEM] = 4,
[COLUMN_CPUA] = 4,
[COLUMN_CPU] = 4,
};
struct process {
int uid;
@ -45,6 +65,7 @@ struct process {
int vsz;
int shm;
int cpu;
int cpua;
char * process;
char * command_line;
};
@ -72,7 +93,7 @@ struct process * process_entry(struct dirent *dent) {
FILE * f;
char line[LINE_LEN];
int pid = 0, uid = 0, tgid = 0, mem = 0, shm = 0, vsz = 0, cpu = 0;
int pid = 0, uid = 0, tgid = 0, mem = 0, shm = 0, vsz = 0, cpu = 0, cpua = 0;
char name[100];
sprintf(tmp, "/proc/%s/status", dent->d_name);
@ -108,10 +129,11 @@ struct process * process_entry(struct dirent *dent) {
mem = atoi(tab);
} else if (strstr(line, "CpuPermille:") == line) {
cpu = strtoul(tab, &tab, 10);
cpu += strtoul(tab, &tab, 10);
cpu += strtoul(tab, &tab, 10);
cpu += strtoul(tab, &tab, 10);
cpu /= 4;
cpua = cpua;
cpua += strtoul(tab, &tab, 10);
cpua += strtoul(tab, &tab, 10);
cpua += strtoul(tab, &tab, 10);
cpua /= 4;
}
}
@ -128,6 +150,7 @@ struct process * process_entry(struct dirent *dent) {
struct process * parent = process_from_pid(tgid);
if (parent) {
parent->cpu += cpu;
parent->cpua += cpua;
}
return NULL;
}
@ -141,6 +164,7 @@ struct process * process_entry(struct dirent *dent) {
out->shm = shm;
out->vsz = vsz;
out->cpu = cpu;
out->cpua = cpua;
out->process = strdup(name);
out->command_line = NULL;
@ -149,12 +173,16 @@ struct process * process_entry(struct dirent *dent) {
char garbage[1024];
int len;
if ((len = sprintf(garbage, "%d", out->pid)) > widths[0]) widths[0] = len;
if ((len = sprintf(garbage, "%d", out->tid)) > widths[1]) widths[1] = len;
if ((len = sprintf(garbage, "%d", out->vsz)) > widths[3]) widths[3] = len;
if ((len = sprintf(garbage, "%d", out->shm)) > widths[4]) widths[4] = len;
if ((len = sprintf(garbage, "%d.%01d", out->mem / 10, out->mem % 10)) > widths[5]) widths[5] = len;
if ((len = sprintf(garbage, "%d.%01d", out->cpu / 10, out->cpu % 10)) > widths[6]) widths[6] = len;
#define DEC(col, member) if ((len = sprintf(garbage, "%d", out-> member)) > widths[col]) widths[col] = len;
#define PCT(col, member) if ((len = sprintf(garbage, "%d.%01d", out-> member / 10, out-> member % 10)) > widths[col]) widths[col] = len;
DEC(COLUMN_PID, pid);
DEC(COLUMN_TID, tid);
DEC(COLUMN_VSZ, vsz);
DEC(COLUMN_SHM, shm);
PCT(COLUMN_MEM, mem);
PCT(COLUMN_CPU, cpu);
PCT(COLUMN_CPUA, cpua);
struct passwd * p = getpwuid(out->uid);
if (p) {
@ -189,21 +217,19 @@ struct process * process_entry(struct dirent *dent) {
void print_header(void) {
printf("\033[7m");
if (show_username) {
printf("%-*s ", widths[2], "USER");
}
printf("%*s ", widths[0], "PID");
if (show_threads) {
printf("%*s ", widths[1], "TID");
}
if (show_cpu) {
printf("%*s ", widths[6], "%CPU");
}
if (show_mem) {
printf("%*s ", widths[5], "%MEM");
printf("%*s ", widths[3], "VSZ");
printf("%*s ", widths[4], "SHM");
}
#define HEADER(col, title) printf("%*s ", widths[col], title)
HEADER(COLUMN_USER, "USER");
HEADER(COLUMN_PID, "PID");
if (show_threads) HEADER(COLUMN_TID, "TID");
HEADER(COLUMN_CPU, "%CPU");
HEADER(COLUMN_CPUA, "ACPU");
HEADER(COLUMN_MEM, "%MEM");
HEADER(COLUMN_VSZ, "VSZ");
HEADER(COLUMN_SHM, "SHM");
printf("CMD\033[K\033[0m\n");
}
@ -228,6 +254,8 @@ void print_entry(struct process * out, int width) {
sprintf(tmp, "%*d.%01d", widths[6]-2, out->cpu / 10, out->cpu % 10);
used += printf("%*s ", widths[6], tmp);
printf("\033[0m");
sprintf(tmp, "%*d.%01d", widths[6]-2, out->cpua / 10, out->cpua % 10);
used += printf("%*s ", widths[6], tmp);
}
if (show_mem) {
char tmp[10];
@ -305,7 +333,7 @@ static void print_meter(const char * title, const char * label, int width, int f
}
static void get_cpu_info(int cpus[]) {
FILE * f = fopen("/proc/smp","r");
FILE * f = fopen("/proc/idle","r");
char buf[4096];
fread(buf, 4096, 1, f);

View File

@ -172,8 +172,6 @@ struct ProcessorLocal {
int cpu_id;
union PML * current_pml;
int idle_time;
struct regs * interrupt_registers;
#ifdef __x86_64__

View File

@ -1340,25 +1340,24 @@ process_t * spawn_worker_thread(void (*entrypoint)(void * argp), const char * na
return proc;
}
static void update_one_process(uint64_t clock_ticks, uint64_t perf_scale, process_t * proc) {
proc->usage[3] = proc->usage[2];
proc->usage[2] = proc->usage[1];
proc->usage[1] = proc->usage[0];
proc->usage[0] = (1000 * (proc->time_total - proc->time_prev)) / (clock_ticks * perf_scale);
proc->time_prev = proc->time_total;
}
void update_process_usage(uint64_t clock_ticks, uint64_t perf_scale) {
spin_lock(tree_lock);
foreach(lnode, process_list) {
process_t * proc = lnode->value;
proc->usage[3] = proc->usage[2];
proc->usage[2] = proc->usage[1];
proc->usage[1] = proc->usage[0];
proc->usage[0] = (1000 * (proc->time_total - proc->time_prev)) / (clock_ticks * perf_scale);
proc->time_prev = proc->time_total;
update_one_process(clock_ticks, perf_scale, proc);
}
spin_unlock(tree_lock);
/* Now use idle tasks to calculator processor activity? */
for (int i = 0; i < processor_count; ++i) {
process_t * proc = processor_local_data[i].kernel_idle_task;
proc->usage[3] = proc->usage[2];
proc->usage[2] = proc->usage[1];
proc->usage[1] = proc->usage[0];
proc->usage[0] = (1000 * (proc->time_total - proc->time_prev)) / (clock_ticks * perf_scale);
proc->time_prev = proc->time_total;
processor_local_data[i].idle_time = (proc->usage[0] + proc->usage[1] + proc->usage[2] + proc->usage[3]) / 4;
update_one_process(clock_ticks, perf_scale, proc);
}
}

View File

@ -648,15 +648,17 @@ static ssize_t pci_func(fs_node_t *node, off_t offset, size_t size, uint8_t *buf
}
#endif
static ssize_t smp_func(fs_node_t *node, off_t offset, size_t size, uint8_t *buffer) {
static ssize_t idle_func(fs_node_t *node, off_t offset, size_t size, uint8_t *buffer) {
char * buf = malloc(4096);
unsigned int soffset = 0;
for (int i = 0; i < processor_count; ++i) {
soffset += snprintf(&buf[soffset], 100, "%d: %d %d\n",
soffset += snprintf(&buf[soffset], 100, "%d: %4d %4d %d %4d\n",
i,
processor_local_data[i].current_process->id,
processor_local_data[i].idle_time
processor_local_data[i].kernel_idle_task->usage[0],
processor_local_data[i].kernel_idle_task->usage[1],
processor_local_data[i].kernel_idle_task->usage[2],
processor_local_data[i].kernel_idle_task->usage[3]
);
}
@ -683,7 +685,7 @@ static struct procfs_entry std_entries[] = {
{-8, "modules", modules_func},
{-9, "filesystems", filesystems_func},
{-10,"loader", loader_func},
{-11,"smp", smp_func},
{-11,"idle", idle_func},
#ifdef __x86_64__
{-12,"irq", irq_func},
{-13,"pat", pat_func},