[psutils][top] Add -j <jobid> to top
Add the ability to specify a job id. top will then only
print the tasks that belong to that job.
ZX-650 #done
Test: Tested manually with a known jobid, and an invalid
jobid.
Change-Id: Ibab099f5a467f96def453562663c0d508c18859a
diff --git a/system/uapp/psutils/top.c b/system/uapp/psutils/top.c
index 65b494f..f2dd5cd 100644
--- a/system/uapp/psutils/top.c
+++ b/system/uapp/psutils/top.c
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include <pretty/sizes.h>
+#include <task-utils/get.h>
#include <task-utils/walker.h>
#include <zircon/listnode.h>
#include <zircon/status.h>
@@ -207,6 +208,7 @@
fprintf(f, " -a Print all threads, even if inactive\n");
fprintf(f, " -c <count> Print the first count threads (default infinity)\n");
fprintf(f, " -d <delay> Delay in seconds (default 1 second)\n");
+ fprintf(f, " -j <jobid> Show only threads that belong to a given jobid\n");
fprintf(f, " -n <times> Run this many times and then exit\n");
fprintf(f, " -o <sort field> Sort by different fields (default is time)\n");
fprintf(f, " -r Print raw time in nanoseconds\n");
@@ -216,6 +218,8 @@
}
int main(int argc, char** argv) {
+ zx_handle_t target_job = ZX_HANDLE_INVALID;
+
int num_loops = -1;
for (int i = 1; i < argc; ++i) {
const char* arg = argv[i];
@@ -275,6 +279,26 @@
i++;
} else if (!strcmp(arg, "-r")) {
raw_time = true;
+ } else if (!strcmp(arg, "-j")) {
+ if (i + 1 >= argc) {
+ fprintf(stderr, "Bad job field\n");
+ print_help(stderr);
+ return 1;
+ }
+ int jobid = atoi(argv[i + 1]);
+ zx_obj_type_t type;
+ zx_status_t status = get_task_by_koid(jobid, &type, &target_job);
+ if (status != ZX_OK) {
+ fprintf(stderr, "ERROR: get_task_by_koid failed: %s (%d)\n",
+ zx_status_get_string(status), status);
+ return 1;
+ }
+ if (type != ZX_OBJ_TYPE_JOB) {
+ fprintf(stderr, "ERROR: object with koid %d is not a job\n",
+ jobid);
+ return 1;
+ }
+ i++;
} else {
fprintf(stderr, "Unknown option: %s\n", arg);
print_help(stderr);
@@ -296,13 +320,18 @@
e->scanned = false;
}
- // iterate the entire job tree
- zx_status_t status =
- walk_root_job_tree(NULL, process_callback, thread_callback, NULL);
+ // If we have a target job, only walk the target subtree. Otherwise walk from root.
+ zx_status_t status;
+ if (target_job != ZX_HANDLE_INVALID) {
+ status = walk_job_tree(target_job, NULL, process_callback, thread_callback, NULL);
+ } else {
+ status = walk_root_job_tree(NULL, process_callback, thread_callback, NULL);
+ }
if (status != ZX_OK) {
- fprintf(stderr, "WARNING: walk_root_job_tree failed: %s (%d)\n",
+ fprintf(stderr, "WARNING: walking the job tree failed: %s (%d)\n",
zx_status_get_string(status), status);
ret = 1;
+ goto finish;
}
// remove every entry that hasn't been scanned this pass
@@ -336,13 +365,19 @@
char c;
int err;
while ((err = read(STDIN_FILENO, &c, 1)) > 0) {
- if (c == 0x3)
- return 0;
+ if (c == 0x3) {
+ ret = 0;
+ goto finish;
+ }
}
}
zx_nanosleep(next_deadline);
}
+finish:
+ if (target_job != ZX_HANDLE_INVALID) {
+ zx_handle_close(target_job);
+ }
return ret;
}