/*
* pg_top - a top PostgreSQL users display for Unix
*
* SYNOPSIS: 2.x with thread eliding
*
* DESCRIPTION:
* This is the machine-dependent module for Linux 2.x that elides threads
* from the output.
*
* CFLAGS: -DHAVE_GETOPT -DHAVE_STRERROR -DORDER
*
* TERMCAP: -lcurses
*
* AUTHOR: Richard Henderson <rth@tamu.edu>
* Order support added by Alexey Klimkin <kad@klon.tme.mcst.ru>
* Ported to 2.4 by William LeFebvre
* Thread eliding by William LeFebvre
*/
#include "config.h"
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <dirent.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/vfs.h>
#include <sys/param.h> /* for HZ */
#include <asm/page.h> /* for PAGE_SHIFT */
#if 0
#include <linux/proc_fs.h> /* for PROC_SUPER_MAGIC */
#else
#define PROC_SUPER_MAGIC 0x9fa0
#endif
#include "pg_top.h"
#include "machine.h"
#include "utils.h"
#define PROCFS "/proc"
extern char *myname;
/*=PROCESS INFORMATION==================================================*/
struct top_proc
{
pid_t pid;
pid_t ppid;
uid_t uid;
char *name;
int pri,
nice;
unsigned long size,
rss; /* in k */
int state;
unsigned long time;
unsigned long start_time;
unsigned long otime;
unsigned long start_code;
unsigned long end_code;
unsigned long start_stack;
unsigned int threads;
double pcpu,
wcpu;
struct top_proc *next;
};
/*=STATE IDENT STRINGS==================================================*/
#define NPROCSTATES 7
static char *state_abbrev[NPROCSTATES + 1] =
{
"", "run", "sleep", "disk", "zomb", "stop", "swap",
NULL
};
static char *procstatenames[NPROCSTATES + 1] =
{
"", " running, ", " sleeping, ", " uninterruptable, ",
" zombie, ", " stopped, ", " swapping, ",
NULL
};
#define NCPUSTATES 4
static char *cpustatenames[NCPUSTATES + 1] =
{
"user", "nice", "system", "idle",
NULL
};
#define MEMUSED 0
#define MEMFREE 1
#define MEMSHARED 2
#define MEMBUFFERS 3
#define MEMCACHED 4
#define NMEMSTATS 5
static char *memorynames[NMEMSTATS + 1] =
{
"K used, ", "K free, ", "K shared, ", "K buffers, ", "K cached",
NULL
};
#define SWAPUSED 0
#define SWAPFREE 1
#define SWAPCACHED 2
#define NSWAPSTATS 3
static char *swapnames[NSWAPSTATS + 1] =
{
"K used, ", "K free, ", "K cached",
NULL
};
static char fmt_header[] =
" PID X THR PRI NICE SIZE RES STATE TIME CPU COMMAND";
/* these are names given to allowed sorting orders -- first is default */
char *ordernames[] = {
"cpu", "size", "res", "time", "command", NULL
};
/* forward definitions for comparison functions */
int compare_cpu();
int compare_size();
int compare_res();
int compare_time();
int compare_cmd();
int (*proc_compares[]) () =
{
compare_cpu,
compare_size,
compare_res,
compare_time,
compare_cmd,
NULL
};
/*=SYSTEM STATE INFO====================================================*/
/* these are for calculating cpu state percentages */
static long cp_time[NCPUSTATES];
static long cp_old[NCPUSTATES];
static long cp_diff[NCPUSTATES];
/* for calculating the exponential average */
static struct timeval lasttime;
/* these are for keeping track of processes */
#define HASH_SIZE (1003)
#define INITIAL_ACTIVE_SIZE (256)
#define PROCBLOCK_SIZE (32)
static struct top_proc *ptable[HASH_SIZE];
static struct top_proc **pactive;
static struct top_proc **nextactive;
static unsigned int activesize = 0;
static time_t boottime = -1;
/* these are for passing data back to the machine independant portion */
static int cpu_states[NCPUSTATES];
static int process_states[NPROCSTATES];
static long memory_stats[NMEMSTATS];
static long swap_stats[NSWAPSTATS];
/* usefull macros */
#define bytetok(x) (((x) + 512) >> 10)
#define pagetok(x) ((x) << (PAGE_SHIFT - 10))
#define HASH(x) (((x) * 1686629713U) % HASH_SIZE)
/*======================================================================*/
static inline char *
skip_ws(const