From 8a4548db7d2cc6f1ba0f9f8148c1e849c7d0388d Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Mon, 18 Apr 2022 00:06:32 +0200 Subject: [PATCH] Add memory statistics to struct psctl_stat. This is an incompatible ABI change. --- Makefile | 2 +- kernel/include/sortix/psctl.h | 6 ++- kernel/psctl.cpp | 13 ++++++- share/man/man7/following-development.7 | 13 +++++++ utils/ps.c | 53 +++++++++++++++++++++++++- 5 files changed, 82 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 6da60cd5..fc2b3cab 100644 --- a/Makefile +++ b/Makefile @@ -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" diff --git a/kernel/include/sortix/psctl.h b/kernel/include/sortix/psctl.h index bf4c3d94..4c0c1704 100644 --- a/kernel/include/sortix/psctl.h +++ b/kernel/include/sortix/psctl.h @@ -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) diff --git a/kernel/psctl.cpp b/kernel/psctl.cpp index f87870a2..60be3147 100644 --- a/kernel/psctl.cpp +++ b/kernel/psctl.cpp @@ -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. diff --git a/share/man/man7/following-development.7 b/share/man/man7/following-development.7 index 3c78b1f8..790cb629 100644 --- a/share/man/man7/following-development.7 +++ b/share/man/man7/following-development.7 @@ -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 diff --git a/utils/ps.c b/utils/ps.c index c45dc15e..96af0ffb 100644 --- a/utils/ps.c +++ b/utils/ps.c @@ -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 #include #include +#include #include #include #include @@ -30,6 +31,30 @@ #include #include +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.