cgtop.c revision 39883f622f392d8579f4428fc5a789a102efbb10
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster This file is part of systemd.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Copyright 2012 Lennart Poettering
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster systemd is free software; you can redistribute it and/or modify it
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster under the terms of the GNU Lesser General Public License as published by
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster the Free Software Foundation; either version 2.1 of the License, or
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster (at your option) any later version.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster systemd is distributed in the hope that it will be useful, but
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster WITHOUT ANY WARRANTY; without even the implied warranty of
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Lesser General Public License for more details.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster You should have received a copy of the GNU Lesser General Public License
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster along with systemd; If not, see <http://www.gnu.org/licenses/>.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostertypedef struct Group {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic unsigned arg_iterations = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic bool arg_batch = false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic enum {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic enum {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while ((g = hashmap_steal_first(h)))
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic int process(const char *controller, const char *path, Hashmap *a, Hashmap *b, unsigned iteration) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (r < 0) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster g->cpu_valid = g->memory_valid = g->io_valid = g->n_tasks_valid = false;
fclose(f);
if (g->n_tasks_valid)
g->n_tasks = n;
g->n_tasks_valid = true;
r = read_one_line_file(p, &v);
free(p);
free(v);
uint64_t x, y;
g->cpu_fraction = (double) y / (double) x;
g->cpu_valid = true;
r = read_one_line_file(p, &v);
free(p);
free(v);
if (g->memory > 0)
g->memory_valid = true;
free(p);
return -errno;
uint64_t k, *q;
q = &rd;
q = ≀
r = safe_atou64(l, &k);
fclose(f);
g->io_valid = true;
static int refresh_one(
const char *controller,
const char *path,
Hashmap *a,
Hashmap *b,
unsigned iteration,
unsigned depth) {
assert(a);
if (r == -ENOENT)
char *fn, *p;
goto finish;
r = -ENOMEM;
goto finish;
free(p);
goto finish;
closedir(d);
assert(a);
if (r != -ENOENT)
if (r != -ENOENT)
if (r != -ENOENT)
if (r != -ENOENT)
static int group_compare(const void*a, const void *b) {
} else if (x->cpu_valid)
else if (y->cpu_valid)
} else if (x->n_tasks_valid)
else if (y->n_tasks_valid)
} else if (x->memory_valid)
else if (y->memory_valid)
} else if (x->io_valid)
else if (y->io_valid)
Iterator i;
Group *g;
signed path_columns;
assert(a);
if (on_tty())
HASHMAP_FOREACH(g, a, i)
array[n++] = g;
if (on_tty()) {
g = array[j];
free(p);
if (g->n_tasks_valid)
if (g->cpu_valid)
printf(" %*s", maxtcpu, format_timespan(buffer, sizeof(buffer), (nsec_t) (g->cpu_usage / NSEC_PER_USEC), 0));
if (g->memory_valid)
if (g->io_valid) {
static int help(void) {
return help();
case ARG_VERSION:
case ARG_CPU_TYPE:
if (optarg) {
return -EINVAL;
case ARG_DEPTH:
return -EINVAL;
if (r < 0 || arg_delay <= 0) {
return -EINVAL;
return -EINVAL;
arg_batch = true;
return -EINVAL;
return -EINVAL;
unsigned iteration = 0;
log_open();
goto finish;
r = log_oom();
goto finish;
if (!on_tty())
while (!quit) {
Hashmap *c;
usec_t t;
char key;
char h[FORMAT_TIMESPAN_MAX];
goto finish;
last_refresh = t;
immediate_refresh = false;
r = display(b);
goto finish;
if (arg_batch) {
if (r == -ETIMEDOUT)
goto finish;
if (arg_batch)
switch (key) {
immediate_refresh = true;
quit = true;
"\t<" ON "p" OFF "> By path; <" ON "t" OFF "> By tasks; <" ON "c" OFF "> By CPU; <" ON "m" OFF "> By memory; <" ON "i" OFF "> By I/O\n"
"\t<" ON "+" OFF "> Increase delay; <" ON "-" OFF "> Decrease delay; <" ON "%%" OFF "> Toggle time\n"
return EXIT_FAILURE;
return EXIT_SUCCESS;