Add memory statistics to struct psctl_stat.

This is an incompatible ABI change.
This commit is contained in:
Jonas 'Sortie' Termansen 2022-04-18 00:06:32 +02:00
parent 2cd7361294
commit 8a4548db7d
5 changed files with 82 additions and 5 deletions

View File

@ -225,7 +225,7 @@ sysroot-system: sysroot-fsh sysroot-base-headers
echo 'ID=sortix' && \
echo 'VERSION_ID="$(VERSION)"' && \
echo 'PRETTY_NAME="Sortix $(VERSION)"' && \
echo 'SORTIX_ABI=1.4' && \
echo 'SORTIX_ABI=2.0' && \
true) > "$(SYSROOT)/etc/sortix-release"
echo /etc/sortix-release >> "$(SYSROOT)/tix/manifest/system"
ln -sf sortix-release "$(SYSROOT)/etc/os-release"

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2016 Jonas 'Sortie' Termansen.
* Copyright (c) 2015, 2016, 2022 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -88,6 +88,10 @@ struct psctl_stat
int status;
int nice;
struct tmns tmns;
size_t pss;
size_t rss;
size_t uss;
size_t vms;
};
#define PSCTL_PROGRAM_PATH __PSCTL(psctl_program_path, 4)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2016 Jonas 'Sortie' Termansen.
* Copyright (c) 2015, 2016, 2022 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -127,6 +127,17 @@ int sys_psctl(pid_t pid, int request, void* ptr)
kthread_mutex_lock(&process->nicelock);
psst.nice = process->nice;
kthread_mutex_unlock(&process->nicelock);
kthread_mutex_lock(&process->segment_lock);
// TODO: Cache these.
for ( size_t i = 0; i < process->segments_used; i++ )
{
const struct segment* segment = &process->segments[i];
psst.pss += segment->size;
psst.rss += segment->size;
psst.uss += segment->size;
psst.vms += segment->size;
}
kthread_mutex_unlock(&process->segment_lock);
// Note: It is safe to access the clocks in this manner as each of them
// are locked by disabling interrupts. This is perhaps not
// SMP-ready, but it will do for now.

View File

@ -69,6 +69,19 @@ releasing Sortix x.y, foo." to allow the maintainer to easily
.Xr grep 1
for it after a release.
.Sh CHANGES
.Ss Add memory statistics to struct psctl_stat
The
.Xr psctl 2
now provides per-process memory statistics in
.Vt struct psctl_stat
via the new members
.Fa pss ,
.Fa rss ,
.Fa uss ,
and
.Fa vms .
.Pp
This is an incompatible ABI change.
.Ss Add memusage(2)
The
.Xr memusage 2

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2016 Jonas 'Sortie' Termansen.
* Copyright (c) 2015, 2016, 2022, 2023 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -22,6 +22,7 @@
#include <err.h>
#include <errno.h>
#include <locale.h>
#include <memusage.h>
#include <psctl.h>
#include <pwd.h>
#include <stdbool.h>
@ -30,6 +31,30 @@
#include <string.h>
#include <unistd.h>
static char* format_bytes_amount(uintmax_t num_bytes, int unit, bool raw)
{
uintmax_t value = num_bytes;
uintmax_t value_fraction = 0;
uintmax_t exponent = 1024;
char suffixes[] = { 'B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' };
size_t num_suffixes = sizeof(suffixes) / sizeof(suffixes[0]);
size_t suffix_index = 0;
while ( (unit < 0 ? exponent <= value : (int) suffix_index < unit) &&
suffix_index + 1 < num_suffixes )
{
value_fraction = value % exponent;
value /= exponent;
suffix_index++;
}
char suffix_char = raw ? 0 : suffixes[suffix_index];
char value_fraction_char = '0' + (value_fraction / (1024 / 10 + 1)) % 10;
char decimals[3] = {suffix_index ? '.' : 0, value_fraction_char, 0};
char* result;
if ( asprintf(&result, "%ju%s%c", value, decimals, suffix_char) < 0 )
return NULL;
return result;
}
static char* get_program_path_of_pid(pid_t pid)
{
struct psctl_program_path ctl;
@ -103,6 +128,7 @@ int main(int argc, char* argv[])
bool select_all = false;
bool show_full = false;
bool show_long = false;
bool show_memory = false;
const char* argv0 = argv[0];
for ( int i = 1; i < argc; i++ )
@ -126,12 +152,15 @@ int main(int argc, char* argv[])
//case 'g': break;
//case 'G': break;
case 'l': show_long = true; break;
case 'm': show_long = true; break;
//case 'n': break;
//case 'o': break;
//case 'p': break;
//case 't': break;
//case 'u': break;
//case 'U': break;
// TODO: -o or some better more standard design for this.
case 'v': show_memory = true; break;
default:
fprintf(stderr, "%s: unknown option -- '%c'\n", argv0, c);
help(stderr, argv0);
@ -155,6 +184,11 @@ int main(int argc, char* argv[])
if ( 1 < argc )
errx(1, "extra operand: %s", argv[1]);
size_t total_counter = MEMUSAGE_TOTAL;
size_t total_memory;
if ( show_memory && memusage(&total_counter, &total_memory, 1) < 0 )
err(1, "memusage");
if ( show_full || show_long )
printf("UID\t");
printf("PID\t");
@ -167,7 +201,12 @@ int main(int argc, char* argv[])
if ( show_long )
printf("NI\t");
printf("TTY\t");
printf("TIME\t ");
printf("TIME\t ");
if ( show_memory )
{
printf("%%MEM\t");
printf("VMS\t");
}
printf("CMD\n");
pid_t pid = 0;
while ( true )
@ -215,6 +254,16 @@ int main(int argc, char* argv[])
int minutes = (time / 60) % 60;
int seconds = (time / 1) % 60;
printf("%02i:%02i:%02i ", hours, minutes, seconds);
if ( show_memory )
{
unsigned percent = ((uintmax_t) psst.vms * 100) / total_memory;
printf("%3u%%\t", percent);
char* usage = format_bytes_amount(psst.vms, -1, false);
if ( !usage )
err(1, "malloc");
printf("%s\t", usage);
free(usage);
}
char* program_path = get_program_path_of_pid(pid);
// TODO: Strip special characters from the process name lest an attacker
// do things to the user's terminal.