From 7af1b2bc11f58827732bea8d78e9eeedbd585e5c Mon Sep 17 00:00:00 2001 From: Jan Lentfer Date: Fri, 4 Dec 2009 22:21:59 +0100 Subject: [PATCH] top - Import DragonFly specific patches for 3.8beta1. * fix commands.c renice function to prevent segfault on wrong number of parameters. --- contrib/top/commands.c | 1 + contrib/top/display.c | 108 +++++++ contrib/top/top.c | 9 +- contrib/top/top.h | 3 + usr.bin/top/Makefile | 33 +-- usr.bin/top/config.h | 263 ++++++++++++++++++ usr.bin/top/{machine.c => m_dragonfly.c} | 132 ++++----- usr.bin/top/top.local.1 | 7 +- usr.bin/top/top.x | 463 +++++++++++++++++++++++++++++++ 9 files changed, 908 insertions(+), 111 deletions(-) create mode 100644 usr.bin/top/config.h rename usr.bin/top/{machine.c => m_dragonfly.c} (90%) create mode 100644 usr.bin/top/top.x diff --git a/contrib/top/commands.c b/contrib/top/commands.c index e93fb54646..7320daf799 100644 --- a/contrib/top/commands.c +++ b/contrib/top/commands.c @@ -508,6 +508,7 @@ renice_procs(char *str) if ((str = next_field(str)) == NULL) { message_error(" remice: no processes specified"); + return; } #ifdef HAVE_SETPRIORITY diff --git a/contrib/top/display.c b/contrib/top/display.c index 2330ca422e..4d1bc7ecfb 100644 --- a/contrib/top/display.c +++ b/contrib/top/display.c @@ -758,6 +758,18 @@ display_init(struct statics *statics) /* certain things may influence the screen layout, so look at those first */ + /* More than one core will shif the parts of the display down */ + if (enable_ncpus != 0 && n_cpus > 1) + { + /* adjust screen placements */ + y_mem = y_mem + n_cpus -1; + y_swap = y_swap + n_cpus -1; + y_message = y_message + n_cpus -1; + y_header = y_header + n_cpus -1; + y_idlecursor = y_idlecursor + n_cpus -1; + y_procs = y_procs + n_cpus -1; + } + /* a kernel line shifts parts of the display down */ kernel_names = statics->kernel_names; if ((num_kernel = string_count(kernel_names)) > 0) @@ -1135,6 +1147,7 @@ i_cpustates(int *states) char *thisname; int *colp; int color = 0; + int cpu; #ifdef ENABLE_COLOR int *cidx = cpustate_cidx; #endif @@ -1144,6 +1157,41 @@ i_cpustates(int *states) colp = cpustate_columns; /* print tag */ + if (enable_ncpus !=0 && n_cpus > 1) { + for (cpu = 0; cpu < n_cpus; ++cpu) { + int y_pos = y_cpustates; + y_pos = y_pos + cpu; + colp = cpustate_columns; + names = cpustate_names; + display_write(0, y_cpustates+cpu, 0, 0, cpustates_tag()); + + /* now walk thru the names and print the line */ + while ((thisname = *names++) != NULL) { + if (*thisname != '\0') { + /* retrieve the value and remember it */ + value = *states; + +#ifdef ENABLE_COLOR + /* determine color number to use */ + color = color_test(*cidx++, value/10); +#endif + /* if percentage is >= 1000, print it as 100% */ + display_fmt(x_cpustates + *colp, y_pos, + color, 0, + (value >= 1000 ? "%4.0f%% %s%s" : "%4.1f%% %s%s"), + ((float)value)/10., + thisname, + *names != NULL ? ", " : ""); + + } + /* increment */ + colp++; + states++; + } + /* copy over values into "last" array */ + memcpy(lcpustates, states, num_cpustates * sizeof(int)); + } + } else { display_write(0, y_cpustates, 0, 0, cpustates_tag()); /* now walk thru the names and print the line */ @@ -1175,6 +1223,8 @@ i_cpustates(int *states) /* copy over values into "last" array */ memcpy(lcpustates, states, num_cpustates * sizeof(int)); + } + } void @@ -1187,10 +1237,46 @@ u_cpustates(int *states) int *lp; int *colp; int color = 0; + int cpu; #ifdef ENABLE_COLOR int *cidx = cpustate_cidx; #endif + + if (enable_ncpus != 0 && n_cpus > 1 ) { + for (cpu = 0; cpu < n_cpus; ++cpu) { + lp = lcpustates; + int y_pos = y_cpustates; + y_pos = y_pos + cpu; + colp = cpustate_columns; + char **names = cpustate_names; + /* we could be much more optimal about this */ + while ((thisname = *names++) != NULL) { + if (*thisname != '\0') { + /* yes, change it */ + /* retrieve value and remember it */ + value = *states; + +#ifdef ENABLE_COLOR + /* determine color number to use */ + color = color_test(*cidx, value/10); +#endif + /* if percentage is >= 1000, print it as 100% */ + display_fmt(x_cpustates + *colp, y_pos, color, 0, + (value >= 1000 ? "%4.0f" : "%4.1f"), + ((double)value)/10.); + +#ifdef ENABLE_COLOR + cidx++; +#endif + } + /* increment and move on */ + lp++; + states++; + colp++; + } + } + } else { lp = lcpustates; colp = cpustate_columns; @@ -1229,6 +1315,7 @@ u_cpustates(int *states) states++; colp++; } + } } void @@ -1239,8 +1326,28 @@ z_cpustates() register char **names = cpustate_names; register char *thisname; register int *lp; + int cpu; /* print tag */ + if (enable_ncpus != 0 && n_cpus > 1) { + for (cpu = 0; cpu < n_cpus; ++cpu) { + display_write(0, y_cpustates + cpu, 0, 0, cpustates_tag()); + char **names = cpustate_names; + i = 0; + while ((thisname = *names++) != NULL) { + if (*thisname != '\0') { + display_fmt(-1, -1, 0, 0, "%s %% %s", i++ == 0 ? "" : ", ", + thisname); + } + } + /* fill the "last" array with all -1s, to insure correct updating */ + lp = lcpustates; + i = num_cpustates; + while (--i >= 0) { + *lp++ = -1; + } + } + } else { display_write(0, y_cpustates, 0, 0, cpustates_tag()); while ((thisname = *names++) != NULL) @@ -1259,6 +1366,7 @@ z_cpustates() { *lp++ = -1; } + } } /* diff --git a/contrib/top/top.c b/contrib/top/top.c index a9dccd8121..8d879401a7 100644 --- a/contrib/top/top.c +++ b/contrib/top/top.c @@ -333,9 +333,9 @@ do_arguments(globalstate *gstate, int ac, char **av) optind = 1; #ifdef HAVE_GETOPT_LONG - while ((i = getopt_long(ac, av, "CDSITabcinqtuvs:d:U:o:m:", longopts, NULL)) != -1) + while ((i = getopt_long(ac, av, "CDSIMTabcinqtuvs:d:U:o:m:", longopts, NULL)) != -1) #else - while ((i = getopt(ac, av, "CDSITabcinqtuvs:d:U:o:m:")) != EOF) + while ((i = getopt(ac, av, "CDSIMTabcinqtuvs:d:U:o:m:")) != EOF) #endif { switch(i) @@ -426,6 +426,11 @@ do_arguments(globalstate *gstate, int ac, char **av) gstate->pselect.idle = !gstate->pselect.idle; break; + case 'M': + enable_ncpus = 1; + break; + + #ifdef ENABLE_COLOR case 'T': gstate->show_tags = 1; diff --git a/contrib/top/top.h b/contrib/top/top.h index 24b1abbd0a..c50046af4f 100644 --- a/contrib/top/top.h +++ b/contrib/top/top.h @@ -77,4 +77,7 @@ struct ext_decl { void gettime(struct timeval *); void quit(int); +int n_cpus; +int enable_ncpus; + #endif /* _TOP_H_ */ diff --git a/usr.bin/top/Makefile b/usr.bin/top/Makefile index 1ceadc70ee..d1ca989acb 100644 --- a/usr.bin/top/Makefile +++ b/usr.bin/top/Makefile @@ -5,22 +5,19 @@ PROG= top TOPDIR= ${.CURDIR}/../../contrib/top .PATH: ${TOPDIR} -CFLAGS+= -DHAVE_GETOPT -DHAVE_STRERROR -I${.CURDIR} -I${.OBJDIR} \ +CFLAGS+= -g -DHAVE_GETOPT -DHAVE_STRERROR -I${.CURDIR} -I${.OBJDIR} \ -I${TOPDIR} -I. -DORDER - -# -# The table size should be a prime number approximately twice as -# large as the number of lines in /etc/passwd. The default number -# is 20011, use /etc/make.conf to override this. -# -.if defined(TOP_TABLE_SIZE) -CFLAGS+= -D"Table_size=${TOP_TABLE_SIZE}" +.if ${MACHINE_ARCH} == "i386" +CFLAGS+=-D_ENABLEX32 +.endif +.if ${MACHINE_ARCH} == "x86_64" +CFLAGS+=-D_ENABLEX64 .endif -SRCS= commands.c display.c machine.c screen.c top.c \ - username.c utils.c version.c top.local.h +SRCS= commands.c getopt.c screen.c username.c version.c \ + color.c display.c hash.c m_dragonfly.c top.c utils.c -CLEANFILES+= top.local.h top.x top.1 +CLEANFILES+= top.x top.1 DPADD= ${LIBTERMCAP} ${LIBM} ${LIBKVM} ${LIBKINFO} LDADD= -ltermcap -lm -lkvm -lkinfo BINGRP= kmem @@ -29,16 +26,6 @@ BINMODE=2555 top.1: top.x top.local.1 cat ${.ALLSRC} > top.1 -.SUFFIXES: .X .x .H .h - -.X.x .H.h: - @${ECHO} Making ${.TARGET} from ${.IMPSRC} - @sed -e's,%LoadMax%,5.0,g' \ - -e's,%TableSize%,20011,g' \ - -e's,%NominalTopn%,18,g' \ - -e's,%topn%,-1,g' \ - -e's,%delay%,2,g' \ - -e's,%random%,1,g' \ - ${.IMPSRC} > ${.TARGET} +WARNS?= 1 .include diff --git a/usr.bin/top/config.h b/usr.bin/top/config.h new file mode 100644 index 0000000000..32e6647776 --- /dev/null +++ b/usr.bin/top/config.h @@ -0,0 +1,263 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Support for debugging output */ +/* #undef DEBUG */ + +/* Default delay */ +#define DEFAULT_DELAY 5 + +/* Default number of processes to display */ +#define DEFAULT_TOPN 30 + +/* Enable color */ +#define ENABLE_COLOR 1 + +/* Enable dual architecture */ +/* #undef ENABLE_DUALARCH */ + +/* Enable kill and renice */ +#define ENABLE_KILL 1 + +/* Supports C99 style variadic macros */ +#define HAVE_C99_VARIADIC_MACROS 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_CURSES_H 1 + +/* Define to 1 if you have the declaration of `sys_errlist', and to 0 if you + don't. */ +#define HAVE_DECL_SYS_ERRLIST 1 + +/* Define to 1 if you have the declaration of `sys_signame', and to 0 if you + don't. */ +#define HAVE_DECL_SYS_SIGNAME 1 + +/* Define to 1 if you have the declaration of `tgetent', and to 0 if you + don't. */ +#define HAVE_DECL_TGETENT 1 + +/* Define to 1 if you have the declaration of `tgetflag', and to 0 if you + don't. */ +#define HAVE_DECL_TGETFLAG 1 + +/* Define to 1 if you have the declaration of `tgetnum', and to 0 if you + don't. */ +#define HAVE_DECL_TGETNUM 1 + +/* Define to 1 if you have the declaration of `tgetstr', and to 0 if you + don't. */ +#define HAVE_DECL_TGETSTR 1 + +/* Define to 1 if you have the declaration of `tgoto', and to 0 if you don't. + */ +#define HAVE_DECL_TGOTO 1 + +/* Define to 1 if you have the declaration of `tputs', and to 0 if you don't. + */ +#define HAVE_DECL_TPUTS 1 + +/* Platform module */ +/* #undef HAVE_FORMAT_PROCESS_HEADER */ + +/* Define to 1 if you have the `getopt' function. */ +#define HAVE_GETOPT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_GETOPT_H 1 + +/* Define to 1 if you have the `getopt_long' function. */ +#define HAVE_GETOPT_LONG 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Supports gnu style variadic macros */ +#define HAVE_GNU_VARIADIC_MACROS 1 + +/* Define to 1 if the system has the type `id_t'. */ +#define HAVE_ID_T 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `elf' library (-lelf). */ +/* #undef HAVE_LIBELF */ + +/* Define to 1 if you have the `kstat' library (-lkstat). */ +/* #undef HAVE_LIBKSTAT */ + +/* Define to 1 if you have the `kvm' library (-lkvm). */ +#define HAVE_LIBKVM 1 + +/* Define to 1 if you have the `m' library (-lm). */ +#define HAVE_LIBM 1 + +/* Define to 1 if you have the `mach' library (-lmach). */ +/* #undef HAVE_LIBMACH */ + +/* Define to 1 if you have the `mas' library (-lmas). */ +/* #undef HAVE_LIBMAS */ + +/* Define to 1 if you have the `perfstat' library (-lperfstat). */ +/* #undef HAVE_LIBPERFSTAT */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if the system has the type `lwpid_t'. */ +#define HAVE_LWPID_T 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MATH_H 1 + +/* Define to 1 if you have the `memcpy' function. */ +#define HAVE_MEMCPY 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if the system has the type `pid_t'. */ +#define HAVE_PID_T 1 + +/* Define to 1 if you have the `setbuffer' function. */ +#define HAVE_SETBUFFER 1 + +/* Define to 1 if you have the `setpriority' function. */ +#define HAVE_SETPRIORITY 1 + +/* Define to 1 if you have the `setvbuf' function. */ +#define HAVE_SETVBUF 1 + +/* Define to 1 if you have the `sigaction' function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the `sighold' function. */ +/* #undef HAVE_SIGHOLD */ + +/* Define to 1 if you have the `sigprocmask' function. */ +#define HAVE_SIGPROCMASK 1 + +/* Define to 1 if you have the `sigrelse' function. */ +/* #undef HAVE_SIGRELSE */ + +/* Define to 1 if you have the `snprintf' function. */ +#define HAVE_SNPRINTF 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDARG_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `sysconf' function. */ +#define HAVE_SYSCONF 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYSEXITS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UTSNAME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMCAP_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERM_H 1 + +/* Define to 1 if the system has the type `time_t'. */ +#define HAVE_TIME_T 1 + +/* Define to 1 if the system has the type `uid_t'. */ +#define HAVE_UID_T 1 + +/* Define to 1 if you have the `uname' function. */ +#define HAVE_UNAME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vsnprintf' function. */ +#define HAVE_VSNPRINTF 1 + +/* Platform module */ +#define MODULE "dragonfly" + +/* Default number of processes to display on non-terminals when topn is all */ +#define NOMINAL_TOPN 40 + +/* Define the major OS revision number. */ +#define OSMAJOR 2 + +/* Define the OS revision. */ +#define OSREV 251DEVELOPMENT + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "top" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "top 3.8beta1" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "top" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "3.8beta1" + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define as the type for the argument to the putc function of tputs ('int' or + 'char') */ +#define TPUTS_PUTC_ARGTYPE int + +/* Define the system hardware platform */ +#ifdef _ENABLEX64 +#define UNAME_HARDWARE "x86_64" +#endif + +#ifdef _ENABLEX32 +#define UNAME_HARDWARE "i386" +#endif + +/* Include code that utilizes extensions */ +/* #undef WITH_EXT */ diff --git a/usr.bin/top/machine.c b/usr.bin/top/m_dragonfly.c similarity index 90% rename from usr.bin/top/machine.c rename to usr.bin/top/m_dragonfly.c index 19e082c2b3..4ee538b0b0 100644 --- a/usr.bin/top/machine.c +++ b/usr.bin/top/m_dragonfly.c @@ -1,7 +1,7 @@ /* * top - a top users display for Unix * - * SYNOPSIS: For FreeBSD-2.x and later + * SYNOPSIS: For DragonFly 2.x and later * * DESCRIPTION: * Originally written for BSD4.4 system by Christos Zoulas. @@ -9,16 +9,15 @@ * Order support hacked in from top-3.5beta6/machine/m_aix41.c * by Monte Mitzelfelt (for latest top see http://www.groupsys.com/topinfo/) * - * This is the machine-dependent module for FreeBSD 2.2 - * Works for: - * FreeBSD 2.2.x, 3.x, 4.x, and probably FreeBSD 2.1.x + * This is the machine-dependent module for DragonFly 2.5.1 + * Should work for: + * DragonFly 2.x and above * * LIBS: -lkvm * - * AUTHOR: Christos Zoulas - * Steven Wallace - * Wolfram Schneider - * Hiten Pandya + * AUTHOR: Jan Lentfer + * This module has been put together from different sources and is based on the + * work of many other people, e.g. Matthew Dillon, Simon Schubert, Jordan Gordeev. * * $FreeBSD: src/usr.bin/top/machine.c,v 1.29.2.2 2001/07/31 20:27:05 tmm Exp $ * $DragonFly: src/usr.bin/top/machine.c,v 1.26 2008/10/16 01:52:33 swildner Exp $ @@ -70,6 +69,8 @@ static int smpmode; static int namelength; static int cmdlength; +int n_cpus = 0; + /* * needs to be a global symbol, so wrapper can be * modified accordingly. @@ -142,7 +143,7 @@ static struct kinfo_cputime *cp_time, *cp_old; /* these are for detailing the process states */ int process_states[6]; -const char *procstatenames[] = { +char *procstatenames[] = { "", " starting, ", " running, ", " sleeping, ", " stopped, ", " zombie, ", NULL @@ -151,20 +152,20 @@ const char *procstatenames[] = { /* these are for detailing the cpu states */ #define CPU_STATES 5 int *cpu_states; -const char *cpustatenames[CPU_STATES + 1] = { +char *cpustatenames[CPU_STATES + 1] = { "user", "nice", "system", "interrupt", "idle", NULL }; /* these are for detailing the memory statistics */ -int memory_stats[7]; -const char *memorynames[] = { +long memory_stats[7]; +char *memorynames[] = { "K Active, ", "K Inact, ", "K Wired, ", "K Cache, ", "K Buf, ", "K Free", NULL }; -int swap_stats[7]; -const char *swapnames[] = { +long swap_stats[7]; +char *swapnames[] = { /* 0 1 2 3 4 5 */ "K Total, ", "K Used, ", "K Free, ", "% Inuse, ", "K In, ", "K Out", NULL @@ -187,12 +188,22 @@ static int pageshift; /* log base 2 of the pagesize */ #define pagetok(size) ((size) << pageshift) -#ifdef ORDER /* sorting orders. first is default */ -const char *ordernames[] = { +char *ordernames[] = { "cpu", "size", "res", "time", "pri", "thr", NULL }; -#endif + +/* compare routines */ +int proc_compare(), compare_size(), compare_res(), compare_time(), compare_prio(), compare_thr(); + +int (*proc_compares[])() = { + proc_compare, + compare_size, + compare_res, + compare_time, + compare_prio, + NULL +}; static void cputime_percentages(int out[CPU_STATES], struct kinfo_cputime *new, @@ -237,11 +248,21 @@ machine_init(struct statics *statics) int pagesize; size_t modelen; struct passwd *pw; + struct timeval boottime; if (n_cpus < 1) { if (kinfo_get_cpus(&n_cpus)) err(1, "kinfo_get_cpus failed"); } + + /* get boot time */ + modelen = sizeof(boottime); + if (sysctlbyname("kern.boottime", &boottime, &modelen, NULL, 0) == -1) { + + /* we have no boottime to report */ + boottime.tv_sec = -1; + } + modelen = sizeof(smpmode); if ((sysctlbyname("machdep.smp_active", &smpmode, &modelen, NULL, 0) < 0 && sysctlbyname("smp.smp_active", &smpmode, &modelen, NULL, 0) < 0) || @@ -290,17 +311,16 @@ machine_init(struct statics *statics) statics->procstate_names = procstatenames; statics->cpustate_names = cpustatenames; statics->memory_names = memorynames; + statics->boottime = boottime.tv_sec; statics->swap_names = swapnames; -#ifdef ORDER statics->order_names = ordernames; -#endif /* all done! */ return(0); } char * -format_header(const char *uname_field) +format_header(char *uname_field) { static char Header[128]; @@ -324,9 +344,6 @@ extern struct timeval timeout; void get_system_info(struct system_info *si) { - int mib[2]; - struct timeval boottime; - size_t bt_size; size_t len; int cpu; @@ -429,26 +446,13 @@ get_system_info(struct system_info *si) } else { si->last_pid = -1; } - - /* - * Print how long system has been up. - * (Found by looking getting "boottime" from the kernel) - */ - mib[0] = CTL_KERN; - mib[1] = KERN_BOOTTIME; - bt_size = sizeof(boottime); - if (sysctl(mib, 2, &boottime, &bt_size, NULL, 0) != -1 && - boottime.tv_sec != 0) { - si->boottime = boottime; - } else { - si->boottime.tv_sec = -1; - } } + static struct handle handle; caddr_t get_process_info(struct system_info *si, struct process_select *sel, - int (*compare)(const void *, const void *)) + int compare_index) { int i; int total_procs; @@ -458,11 +462,8 @@ caddr_t get_process_info(struct system_info *si, struct process_select *sel, /* these are copied out of sel for speed */ int show_idle; - int show_self; int show_system; - int show_only_threads; int show_uid; - int show_command; pbase = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc); @@ -478,12 +479,8 @@ caddr_t get_process_info(struct system_info *si, struct process_select *sel, /* set up flags which define what we are going to select */ show_idle = sel->idle; - show_self = sel->self; show_system = sel->system; - show_threads = sel->threads || sel->only_threads; - show_only_threads = sel->only_threads; show_uid = sel->uid != -1; - show_command = sel->command != NULL; /* count up process states and get pointers to interesting procs */ total_procs = 0; @@ -499,17 +496,14 @@ caddr_t get_process_info(struct system_info *si, struct process_select *sel, * processes---these get ignored unless show_sysprocs is set. */ if ((show_threads && (LP(pp, pid) == -1)) || - (!show_only_threads && (PP(pp, stat) != 0 && - (show_self != PP(pp, pid)) && - (show_system || ((PP(pp, flags) & P_SYSTEM) == 0))))) + (show_system || ((PP(pp, flags) & P_SYSTEM) == 0))) { total_procs++; process_states[(unsigned char) PP(pp, stat)]++; if ((show_threads && (LP(pp, pid) == -1)) || - (!show_only_threads && PP(pp, stat) != SZOMB && (show_idle || (LP(pp, pctcpu) != 0) || (LP(pp, stat) == LSRUN)) && - (!show_uid || PP(pp, ruid) == (uid_t)sel->uid))) + (!show_uid || PP(pp, ruid) == (uid_t)sel->uid)) { *prefp++ = pp; active_procs++; @@ -517,11 +511,8 @@ caddr_t get_process_info(struct system_info *si, struct process_select *sel, } } - /* if requested, sort the "interesting" processes */ - if (compare != NULL) - { - qsort((char *)pref, active_procs, sizeof(struct kinfo_proc *), compare); - } + qsort((char *)pref, active_procs, sizeof(struct kinfo_proc *), + proc_compares[compare_index]); /* remember active and total counts */ si->p_total = total_procs; @@ -536,7 +527,7 @@ caddr_t get_process_info(struct system_info *si, struct process_select *sel, char fmt[128]; /* static area where result is built */ char * -format_next_process(caddr_t xhandle, char *(*get_userid)(long)) +format_next_process(caddr_t xhandle, char *(*get_userid)(int)) { struct kinfo_proc *pp; long cputime; @@ -642,8 +633,8 @@ format_next_process(caddr_t xhandle, char *(*get_userid)(long)) (int)((show_threads && (LP(pp, pid) == -1)) ? LP(pp, tdprio) : LP(pp, prio)), (int)xnice, - format_k2(PROCSIZE(pp)), - format_k2(pagetok(VP(pp, rssize))), + format_k(PROCSIZE(pp)), + format_k(pagetok(VP(pp, rssize))), status, (int)(smpmode ? LP(pp, cpuid) : 0), format_time(cputime), @@ -745,11 +736,7 @@ static unsigned char sorted_state[] = /* compare_cpu - the comparison function for sorting by cpu percentage */ int -#ifdef ORDER -compare_cpu(const void *arg1, const void *arg2) -#else proc_compare(const void *arg1, const void *arg2) -#endif { const struct proc *const*pp1 = arg1; const struct proc *const*pp2 = arg2; @@ -773,24 +760,6 @@ proc_compare(const void *arg1, const void *arg2) return(result); } -#ifdef ORDER -/* compare routines */ -int compare_size(const void *, const void *); -int compare_res(const void *, const void *); -int compare_time(const void *, const void *); -int compare_prio(const void *, const void *); -int compare_thr(const void *, const void *); - -int (*proc_compares[])(const void *, const void *) = { - compare_cpu, - compare_size, - compare_res, - compare_time, - compare_prio, - compare_thr, - NULL -}; - /* compare_size - the comparison function for sorting by total memory usage */ int @@ -929,9 +898,6 @@ compare_thr(const void *arg1, const void *arg2) return(result); } - -#endif - /* * proc_owner(pid) - returns the uid that owns process "pid", or -1 if * the process does not exist. diff --git a/usr.bin/top/top.local.1 b/usr.bin/top/top.local.1 index 5436d177db..07b38caf2c 100644 --- a/usr.bin/top/top.local.1 +++ b/usr.bin/top/top.local.1 @@ -1,7 +1,8 @@ .\" $DragonFly: src/usr.bin/top/top.local.1,v 1.4 2008/03/27 19:37:15 corecode Exp $ -.SH "DragonFly NOTES" - -.SH DESCRIPTION OF MEMORY +.SH DragonFly NOTES +.SS EXTRA OPTIONS +-M : Enable Multi-CPU display +.SS DESCRIPTION OF MEMORY Mem: 9220K Active, 1032K Inact, 3284K Wired, 1MB Cache, 2M Buf, 1320K Free Swap: 91M Total, 79M Free, 13% Inuse, 80K In, 104 K Out diff --git a/usr.bin/top/top.x b/usr.bin/top/top.x new file mode 100644 index 0000000000..a54604b8b4 --- /dev/null +++ b/usr.bin/top/top.x @@ -0,0 +1,463 @@ +.\" NOTE: changes to the manual page for "top" should be made in the +.\" file "top.1.in" and NOT in the file "top.1". +.nr N 30 +.nr D 5 +.nr L 1 +.nr K 1 +.TH TOP 1 Local +.UC 4 +.SH NAME +top \- display and update information about the top cpu processes +.SH SYNOPSIS +.B top +[ +.B \-CISTabcinqtuv +] [ +.BI \-d count +] [ +.BI \-m mode +] [ +.BI \-o field +] [ +.BI \-s time +] [ +.BI \-U username +] [ +.I number +] +.SH DESCRIPTION +.\" This defines appropriate quote strings for nroff and troff +.ds lq \&" +.ds rq \&" +.if t .ds lq `` +.if t .ds rq '' +.\" Just in case these number registers aren't set yet... +.if \nN==0 .nr N 10 +.if \nD==0 .nr D 5 +.I Top +displays the top +.if !\nN==-1 \nN +processes on the system and periodically updates this information. +.if \nN==-1 \ +\{\ +If standard output is an intelligent terminal (see below) then +as many processes as will fit on the terminal screen are displayed +by default. Otherwise, a good number of them are shown (around 20). +.\} +Raw cpu percentage is used to rank the processes. If +.I number +is given, then the top +.I number +processes will be displayed instead of the default. +.PP +.I Top +makes a distinction between terminals that support advanced capabilities +and those that do not. This +distinction affects the choice of defaults for certain options. In the +remainder of this document, an \*(lqintelligent\*(rq terminal is one that +supports cursor addressing, clear screen, and clear to end of line. +Conversely, a \*(lqdumb\*(rq terminal is one that does not support such +features. If the output of +.I top +is redirected to a file, it acts as if it were being run on a dumb +terminal. +.SH OPTIONS +.if \nL==0 Long options are not available on this system. +.TP +.B "\-C, \-\-color" +Turn off the use of color in the display. +.TP +.B "\-I, \-\-idle-procs" +Do not display idle processes. +By default, top displays both active and idle processes. +.TP +.B "\-S, \-\-system-procs" +Show system processes in the display. Normally, system processes such as +the pager and the swapper are not shown. This option makes them visible. +.TP +.B "\-T, \-\-tag-names" +List all available color tags and the current set of tests used for +color highlighting, then exit. +.TP +.B "\-a, \-\-all" +Show all processes for as long as possible. This is shorthand for +\*(lq-d all all\*(rq. This option is especially handy in batch mode. +.TP +.B "\-b, \-n, \-\-batch" +Use \*(lqbatch\*(rq mode. In this mode, all input from the terminal is +ignored. Interrupt characters (such as ^C and ^\e) still have an effect. +This is the default on a dumb terminal, or when the output is not a terminal. +.TP +.B "\-c, \-\-full-commands" +Show the full command line for each process. Default is to show just the +command name. This option is not supported on all platforms. +.TP +.B "\-i, \-\-interactive" +Use \*(lqinteractive\*(rq mode. In this mode, any input is immediately +read for processing. See the section on \*(lqInteractive Mode\*(rq +for an explanation of +which keys perform what functions. After the command is processed, the +screen will immediately be updated, even if the command was not +understood. This mode is the default when standard output is an +intelligent terminal. +.TP +.B "\-q, \-\-quick" +Renice +.I top +to -20 so that it will run faster. This can be used when the system is +being very sluggish to improve the possibility of discovering the problem. +This option can only be used by root. +.TP +.B "\-t, \-\-threads" +Show individual threads on separate lines. By default, on systems +which support threading, each process is shown with a count of the number +of threads. This option shows each thread on a separate line. This option +is not supported on all platforms. +.TP +.B "\-u, \-\-uids" +Do not take the time to map uid numbers to usernames. Normally, +.I top +will read as much of the file \*(lq/etc/passwd\*(rq as is necessary to map +all the user id numbers it encounters into login names. This option +disables all that, while possibly decreasing execution time. The uid +numbers are displayed instead of the names. +.TP +.B "\-v, \-\-version" +Write version number information to stderr then exit immediately. +No other processing takes place when this option is used. To see current +revision information while top is running, use the help command \*(lq?\*(rq. +.TP +.B "\-d \fIcount\fP, \-\-displays \fIcount\fP" +Show only +.I count +displays, then exit. A display is considered to be one update of the +screen. This option allows the user to select the number of displays he +wants to see before +.I top +automatically exits. Any proper prefix of the words \*(lqinfinity\*(rq, +\*(lqmaximum\*(rq, +or +\*(lqall\*(rq can be used to indicate an infinite number of displays. +The default for intelligent terminals is infinity. +The default for dumb terminals is 1. +.TP +.B "\-m \fImode\fP, \-\-mode=\fImode\fP" +Start the display in an alternate mode. Some platforms support multiple +process displays to show additional process information. The value +\fImode\fP is a number indicating which mode to display. The default is +0. On platforms that do not have multiple display modes this option has +no effect. +.TP +.B "\-o \fIfield\fP, \-\-sort-order=\fIfield\fP" +Sort the process display area on the specified field. The field name is +the name of the column as seen in the output, but in lower case. Likely +values are \*(lqcpu\*(rq, \*(lqsize\*(rq, \*(lqres\*(rq, and \*(lqtime\*(rq, +but may vary on different operating systems. Note that +not all operating systems support this option. +.TP +.B "\-s \fItime\fP, \-\-delay=\fItime\fP" +Set the delay between screen updates to +.I time +seconds. The default delay between updates is \nD seconds. +.TP +.B "\-U \fIusername\fP, \-\-user=\fIusername\fP" +Show only those processes owned by +.IR username . +This option currently only accepts usernames and will not understand +uid numbers. +.PP +Both +.I count +and +.I number +fields can be specified as \*(lqinfinite\*(rq, indicating that they can +stretch as far as possible. This is accomplished by using any proper +prefix of the keywords +\*(lqinfinity\*(rq, +\*(lqmaximum\*(rq, +or +\*(lqall\*(rq. +The default for +.I count +on an intelligent terminal is, in fact, +\fBinfinity\fP. +.PP +The environment variable +.B TOP +is examined for options before the command line is scanned. This enables +a user to set his or her own defaults. The number of processes to display +can also be specified in the environment variable +.BR TOP . +The options +.BR \-C , +.BR \-I , +.BR \-S , +and +.B \-u +are actually toggles. A second specification of any of these options +will negate the first. Thus a user who has the environment variable +.B TOP +set to \*(lq\-I\*(rq may use the command \*(lqtop \-I\*(rq to see idle processes. +.SH "INTERACTIVE MODE" +When +.I top +is running in \*(lqinteractive mode\*(rq, it reads commands from the +terminal and acts upon them accordingly. In this mode, the terminal is +put in \*(lqCBREAK\*(rq, so that a character will be +processed as soon as it is typed. Almost always, a key will be +pressed when +.I top +is between displays; that is, while it is waiting for +.I time +seconds to elapse. If this is the case, the command will be +processed and the display will be updated immediately thereafter +(reflecting any changes that the command may have specified). This +happens even if the command was incorrect. If a key is pressed while +.I top +is in the middle of updating the display, it will finish the update and +then process the command. Some commands require additional information, +and the user will be prompted accordingly. While typing this information +in, the user's erase and kill keys (as set up by the command +.IR stty ) +are recognized, and a newline terminates the input. Note that a control-L +(^L) always redraws the current screen and a space forces an immediate +update to the screen using new data. +.PP +These commands are currently recognized: +.TP +.I "\fBh\fP\ or\ \fB?\fP" +Display a summary of the commands (help screen). Version information +is included in this display. +.TP +.B C +Toggle the use of color in the display. +.TP +.B c +Display only processes whose commands match the specified string. An empty +string will display all processes. This command is not supported on all +platforms. +.TP +.B d +Change the number of displays to show (prompt for new number). +Remember that the next display counts as one, so typing +.B d1 +will make +.I top +show one final display and then immediately exit. +.TP +.B f +Toggle the display of the full command line. +.TP +.B H +Toggle the display of threads on separate lines. By default, on systems +which support threading, each process is shown with a count of the number +of threads. This command shows each thread on a separate line. This command +is not supported on all platforms. +.TP +.B i +(or +.BR I ) +Toggle the display of idle processes. +.if \nK==1 \{\ +.TP +.B k +Send a signal (\*(lqkill\*(rq by default) to a list of processes. This +acts similarly to the command +.IR kill (1)). +.\} +.TP +.B M +Sort display by memory usage. Shorthand for \*(lqo size\*(rq. +.TP +.B m +Change to a different process display mode. Some systems provide multiple +display modes for the process display which shows different information. +This command toggles between the available modes. This command is not +supported on all platforms. +.TP +.B N +Sort by process id. Shorthand for \*(lqo pid\*(rq. +.TP +.B n or # +Change the number of processes to display (prompt for new number). +.TP +.B o +Change the order in which the display is sorted. This command is not +available on all systems. The sort key names vary fron system to system +but usually include: \*(lqcpu\*(rq, \*(lqres\*(rq, \*(lqsize\*(rq, +\*(lqtime\*(rq. The default is cpu. +.TP +.B P +Sort by CPU usage. Shorthand for \*(lqo cpu\*(rq. +.TP +.B q +Quit +.IR top. +.if \nK==1 \{\ +.TP +.B r +Change the priority (the \*(lqnice\*(rq) of a list of processes. +This acts similarly to the command +.IR renice (8)). +.\} +.TP +.B s +Change the number of seconds to delay between displays +(prompt for new number). +.TP +.B T +Sort by CPU time. Shorthand for \*(lqo time\*(rq. +.TP +.B U +Toggle between displaying usernames and uids. +.TP +.B u +Display only processes owned by a specific username (prompt for username). +If the username specified is simply \*(lq+\*(rq, then processes belonging +to all users will be displayed. +.SH "THE DISPLAY" +The actual display varies depending on the specific variant of Unix +that the machine is running. This description may not exactly match +what is seen by top running on this particular machine. Differences +are listed at the end of this manual entry. +.PP +The top lines of the display show general information +about the state of the system. The first line shows +(on some systems) the last process id assigned to a process, +the three load averages, +the system uptime, and the current time. +The second line displays the total number of processes followed +by a breakdown of processes per state. Examples of states common +to Unix systems are sleeping, running, starting, stopped, and zombie. +The next line displays a percentage of time spent in each of the +processor states (typically user, nice, system, idle, and iowait). +These percentages show the processor activity during the time since +the last update. For multi-processor systems, this information is +a summation of time across all processors. The next line shows +kernel-related activity (not available on all systems). The numbers +shown on this line are per-second rates sampled since the last update. +The exact +information displayed varies between systems, but some examples are: +context switches, interrupts, traps, forks, and page faults. The last +one or two lines show a summary of memory and swap activity. These lines +vary between systems. +.PP +The remainder of the screen displays information about individual +processes. This display is similar in spirit to +.IR ps (1) +but it is not exactly the same. The columns displayed by top will +differ slightly between operating systems. Generally, the following +fields are displayed: +.TP +.B PID +The process id. +.TP +.B USERNAME +Username of the process's owner (if +.B \-u +is specified, a UID column will be substituted for USERNAME). +.TP +.B THR +The number of threads in the processes (this column may also +be labeled NLWP). +.TP +.B PRI +Current priority of the process. +.TP +.B NICE +Nice amount in the range \-20 to 20, as established by the use of +the command +.IR nice . +.TP +.B SIZE +Total size of the process (text, data, and stack) given in kilobytes. +.TP +.B RES +Resident memory: current amount of process memory that resides in physical +memory, given in kilobytes. +.TP +.B STATE +Current state (typically one of \*(lqsleep\*(rq, +\*(lqrun\*(rq, \*(lqidl\*(rq, \*(lqzomb\*(rq, or \*(lqstop\*(rq). +.TP +.B TIME +Number of system and user cpu seconds that the process has used. +.TP +.B CPU +Percentage of available cpu time used by this process. +.TP +.B COMMAND +Name of the command that the process is currently running. +.SH COLOR +Top supports the use of ANSI color in its output. By default, color is +available but not used. The environment variable +.B TOPCOLORS +specifies colors to use and conditions for which they should be used. +At the present time, only numbers in the summay display area can be +colored. In a future version it will be possible to highlight numbers +in the process display area as well. The environment variable is the +only way to specify color: there is no equivalent command line option. +Note that the environment variable +.B TOPCOLOURS +is also understood. The British spelling takes precedence. The use of +color only works on terminals that understand and process ANSI color +escape sequences. +.PP +The environment variable is a sequence of color specifications, separated +by colons. Each specification takes the form tag=min,max#code where +.I tag +is the name of the value to check, +.I min +and +.I max +specify a range for the value, and +.I code +is an ANSI color code. Multiple color codes can be listed and separated +with semi-colons. A missing +.I min +implies the lowest possible value (usually 0) +and a missing +.I max +implies infinity. The comma must always be present. When specifying numbers +for load averages, they should be multiplied by 100. +For example, the specification +.B 1min=500,1000#31 +indicates that a 1 minute load average between +5 and 10 should be displayed in red. Color attributes can be combined. +For example, the specification +.B 5min=1000,#37;41 +indicates that a 5 minute load average higher than 10 should be displayed +with white characters on a red background. A special tag named +.I header +is used to control the color of the header for process display. It should +be specified with no lower and upper limits, specifically +.B header=,# +followed by the ANSI color code. +.PP +You can see a list of color codes recognized by this installation of top +with the +.B \-T +option. This will also show the current set of tests used for +color highligting, as specified in the environment. +.SH AUTHOR +William LeFebvre +.SH ENVIRONMENT +.DT +TOP user-configurable defaults for options. +TOPCOLORS color specification +.SH BUGS +As with +.IR ps (1), +things can change while +.I top +is collecting information for an update. The picture it gives is only a +close approximation to reality. +.SH "SEE ALSO" +kill(1), +ps(1), +stty(1), +mem(4), +renice(8) +.SH COPYRIGHT +Copyright (C) 1984-2007 William LeFebvre. For additional licensing +information, see http://www.unixtop.org/license/ -- 2.15.1