This allows top to show Cpu0 to CpuN idle stats when you press 1. TESTED: on UP and SMP gnumach with debian hurd-i386.
--- procfs/rootdir.c | 63 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/procfs/rootdir.c b/procfs/rootdir.c index 14f254d6..56e19067 100644 --- a/procfs/rootdir.c +++ b/procfs/rootdir.c @@ -84,12 +84,13 @@ get_boottime (struct ps_context *pc, struct timeval *tv) return err; } -/* We get the idle time by querying the kernel's idle thread. */ +/* We get the idle time for cpu_number by querying the kernel's idle threads. */ static error_t -get_idletime (struct ps_context *pc, struct timeval *tv) +get_idletime (struct ps_context *pc, struct timeval *tv, int cpu_number) { struct proc_stat *ps, *pst; thread_basic_info_t tbi; + thread_sched_info_t tsi; error_t err; int i; @@ -97,7 +98,7 @@ get_idletime (struct ps_context *pc, struct timeval *tv) if (err) return err; - pst = NULL, tbi = NULL; + pst = NULL, tbi = NULL, tsi = NULL; err = proc_stat_set_flags (ps, PSTAT_NUM_THREADS); if (err || !(proc_stat_flags (ps) & PSTAT_NUM_THREADS)) @@ -106,13 +107,15 @@ get_idletime (struct ps_context *pc, struct timeval *tv) goto out; } - /* Look for the idle thread */ - for (i=0; !tbi || !(tbi->flags & TH_FLAGS_IDLE); i++) + /* Look for the idle thread for cpu_number */ + for (i=0; !tbi || !tsi + || !(tbi->flags & TH_FLAGS_IDLE) + || !(tsi->last_processor == cpu_number); i++) { if (pst) _proc_stat_free (pst); - pst = NULL, tbi = NULL; + pst = NULL, tbi = NULL, tsi = NULL; if (i >= proc_stat_num_threads (ps)) { err = ESRCH; @@ -128,6 +131,12 @@ get_idletime (struct ps_context *pc, struct timeval *tv) continue; tbi = proc_stat_thread_basic_info (pst); + + err = proc_stat_set_flags (pst, PSTAT_THREAD_SCHED); + if (err || ! (proc_stat_flags (pst) & PSTAT_THREAD_SCHED)) + continue; + + tsi = proc_stat_thread_sched_info (pst); } /* We found it! */ @@ -192,7 +201,7 @@ rootdir_gc_uptime (void *hook, char **contents, ssize_t *contents_len) if (err) return err; - err = get_idletime (hook, &idletime); + err = get_idletime (hook, &idletime, 0); if (err) return err; @@ -216,8 +225,15 @@ rootdir_gc_stat (void *hook, char **contents, ssize_t *contents_len) struct timeval boottime, time, idletime; struct vm_statistics vmstats; unsigned long up_ticks, idle_ticks; + int i; + FILE *m; + host_basic_info_t basic; error_t err; + err = ps_host_basic_info (&basic); + if (err) + return EIO; + err = gettimeofday (&time, NULL); if (err < 0) return errno; @@ -226,7 +242,7 @@ rootdir_gc_stat (void *hook, char **contents, ssize_t *contents_len) if (err) return err; - err = get_idletime (hook, &idletime); + err = get_idletime (hook, &idletime, 0); if (err) return err; @@ -234,22 +250,43 @@ rootdir_gc_stat (void *hook, char **contents, ssize_t *contents_len) if (err) return EIO; + m = open_memstream (contents, (size_t *) contents_len); + if (m == NULL) + { + err = ENOMEM; + goto out; + } + timersub (&time, &boottime, &time); up_ticks = opt_clk_tck * (time.tv_sec * 1000000. + time.tv_usec) / 1000000.; idle_ticks = opt_clk_tck * (idletime.tv_sec * 1000000. + idletime.tv_usec) / 1000000.; - *contents_len = asprintf (contents, + fprintf (m, "cpu %lu 0 0 %lu 0 0 0 0 0\n" - "cpu0 %lu 0 0 %lu 0 0 0 0 0\n" + "cpu0 %lu 0 0 %lu 0 0 0 0 0\n", + up_ticks - idle_ticks, idle_ticks, + up_ticks - idle_ticks, idle_ticks); + + for (i = 1; i < basic->avail_cpus; i++) + { + err = get_idletime (hook, &idletime, i); + idle_ticks = opt_clk_tck * (idletime.tv_sec * 1000000. + idletime.tv_usec) / 1000000.; + fprintf (m, + "cpu%d %lu 0 0 %lu 0 0 0 0 0\n", + i, up_ticks - idle_ticks, idle_ticks); + } + + fprintf (m, "intr 0\n" "page %d %d\n" "btime %lu\n", - up_ticks - idle_ticks, idle_ticks, - up_ticks - idle_ticks, idle_ticks, vmstats.pageins, vmstats.pageouts, boottime.tv_sec); - return 0; + out: + if (m) + fclose (m); + return err; } static error_t -- 2.45.2