From c1beefce3a0d1912ceedda4515dff17a2979317c Mon Sep 17 00:00:00 2001 From: Martin Baulig Date: Sun, 21 Mar 1999 17:57:51 +0000 Subject: [PATCH] Initial revision --- kernel/sysctl/Makefile | 22 +++ kernel/sysctl/libgtop.c | 318 +++++++++++++++++++++++++++++++++++ kernel/sysctl/libgtop.h | 82 +++++++++ kernel/sysctl/libgtop_syms.c | 24 +++ kernel/sysctl/main.c | 4 + 5 files changed, 450 insertions(+) create mode 100644 kernel/sysctl/Makefile create mode 100644 kernel/sysctl/libgtop.c create mode 100644 kernel/sysctl/libgtop.h create mode 100644 kernel/sysctl/libgtop_syms.c create mode 100644 kernel/sysctl/main.c diff --git a/kernel/sysctl/Makefile b/kernel/sysctl/Makefile new file mode 100644 index 00000000..77dd277a --- /dev/null +++ b/kernel/sysctl/Makefile @@ -0,0 +1,22 @@ +# +# Makefile for the LibGTop linux sysctl interface. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definition is now in the main makefile... + +O_TARGET := kernel.o +ifeq ($(CONFIG_LIBGTOP),y) +O_OJBS := main.o libgtop.o +else +O_OBJS := main.o +endif +OX_OBJS := libgtop_syms.o + +ifeq ($(CONFIG_LIBGTOP),m) +M_OBJS := libgtop.o +endif + +include $(TOPDIR)/Rules.make diff --git a/kernel/sysctl/libgtop.c b/kernel/sysctl/libgtop.c new file mode 100644 index 00000000..e77c6af2 --- /dev/null +++ b/kernel/sysctl/libgtop.c @@ -0,0 +1,318 @@ +/* + * linux/libgtop/module.c + * Copyright (C) 1999 Martin Baulig + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +EXPORT_NO_SYMBOLS; + +static int system_ctl_handler (ctl_table *table, int *name, int nlen, + void *oldval, size_t *oldlenp, void *newval, + size_t newlen, void **context); + +static int proc_ctl_handler (ctl_table *table, int *name, int nlen, + void *oldval, size_t *oldlenp, void *newval, + size_t newlen, void **context); + +static int libgtop_sysctl_version = 1; +static int libgtop_update_expensive = 5000; + +static struct ctl_table_header *libgtop_sysctl_header = NULL; + +static libgtop_stat_t libgtop_stat; +static unsigned int libgtop_mem_timestamp = 0; +static libgtop_mem_t libgtop_mem; +static unsigned int libgtop_swap_timestamp = 0; +static libgtop_swap_t libgtop_swap; +static libgtop_proclist_t libgtop_proclist; + +static ctl_table libgtop_table[]; +static ctl_table proc_table[]; + +static ctl_table libgtop_root_table[] = { + {CTL_LIBGTOP, "libgtop", NULL, 0, 0555, libgtop_table}, + {0} +}; + +#ifdef MODULE +static +#endif +ctl_table libgtop_table[] = { + {LIBGTOP_VERSION, "version", &libgtop_sysctl_version, + sizeof (int), 0444, NULL, &proc_dointvec}, + {LIBGTOP_PROC, NULL, NULL, 0, 0555, proc_table}, + {LIBGTOP_UPDATE_EXPENSIVE, "update_expensive", + &libgtop_update_expensive, sizeof (int), 0664, NULL, &proc_dointvec}, + {LIBGTOP_STAT, NULL, &libgtop_stat, sizeof (libgtop_stat), + 0444, NULL, NULL, &system_ctl_handler}, + {LIBGTOP_MEM, NULL, &libgtop_mem, sizeof (libgtop_mem), + 0444, NULL, NULL, &system_ctl_handler}, + {LIBGTOP_SWAP, NULL, &libgtop_swap, sizeof (libgtop_swap), + 0444, NULL, NULL, &system_ctl_handler}, + {LIBGTOP_PROCLIST, NULL, &libgtop_proclist, sizeof (libgtop_proclist), + 0444, NULL, NULL, &system_ctl_handler}, + {0} +}; + +static ctl_table proc_table[] = { + {CTL_ANY, NULL, NULL, 0, 04444, NULL, NULL, &proc_ctl_handler}, + {0} +}; + +#ifdef MODULE +static void +libgtop_sysctl_register(void) +{ + static int initialized = 0; + + if (initialized == 1) + return; + + libgtop_sysctl_header = register_sysctl_table(libgtop_root_table, 1); + initialized = 1; +} + +static void +libgtop_sysctl_unregister(void) +{ + unregister_sysctl_table(libgtop_sysctl_header); +} + +int init_module(void) +{ + libgtop_sysctl_register(); + return 0; +} + +void cleanup_module(void) +{ + libgtop_sysctl_unregister(); +} + +#endif /* MODULE */ + +static int +libgtop_sysctl (ctl_table *table, int nlen, int *name) +{ + extern unsigned long total_forks; + int index, tindex, tty, which, arg; + libgtop_stat_t *lstat; + libgtop_mem_t *mem; + libgtop_swap_t *swap; + libgtop_proclist_t *proclist; + struct task_struct *tsk = NULL; + struct sysinfo i; + + switch (table->ctl_name) { + case LIBGTOP_STAT: + lstat = table->data; + lstat->cpu.total = jiffies; + lstat->cpu.user = kstat.cpu_user; + lstat->cpu.nice = kstat.cpu_nice; + lstat->cpu.sys = kstat.cpu_system; + lstat->cpu.idle = jiffies*smp_num_cpus - + (lstat->cpu.user + lstat->cpu.nice + lstat->cpu.sys); +#ifdef __SMP__ + for (i = 0; i < smp_num_cpus; i++) { + lstat->xcpu[i].user = kstat.per_cpu_user[cpu_logical_map(i)]; + lstat->xcpu[i].nice = kstat.per_cpu_nice[cpu_logical_map(i)]; + lstat->xcpu[i].sys = kstat.per_cpu_system[cpu_logical_map(i)]; + lstat->xcpu[i].idle = jiffies - + (lstat->xcpu[i].user + lstat->xcpu[i].nice + + lstat->xcpu[i].sys); + } + + lstat->ncpu = smp_num_cpus; +#else + lstat->ncpu = 0; +#endif + + lstat->frequency = HZ; + + lstat->loadavg [0] = (double) avenrun [0] / (1 << FSHIFT); + lstat->loadavg [1] = (double) avenrun [1] / (1 << FSHIFT); + lstat->loadavg [2] = (double) avenrun [2] / (1 << FSHIFT); + + lstat->pgpgin = kstat.pgpgin; + lstat->pgpgout = kstat.pgpgout; + lstat->pswpin = kstat.pswpin; + lstat->pswpout = kstat.pswpout; + + lstat->context_swtch = kstat.context_swtch; + lstat->boot_time = xtime.tv_sec - jiffies / HZ; + lstat->total_forks = total_forks; + break; + case LIBGTOP_MEM: + if (jiffies - libgtop_mem_timestamp < libgtop_update_expensive) + return 0; + libgtop_mem_timestamp = jiffies; + printk ("Time: %lu\n", jiffies); + + mem = table->data; + si_meminfo (&i); + + mem->totalram = i.totalram; + mem->freeram = i.freeram; + mem->sharedram = i.sharedram; + mem->bufferram = i.bufferram; + return 0; + case LIBGTOP_SWAP: + if (jiffies - libgtop_swap_timestamp < libgtop_update_expensive) + return 0; + libgtop_swap_timestamp = jiffies; + printk ("Time: %lu\n", jiffies); + + swap = table->data; + si_swapinfo (&i); + + swap->totalswap = i.totalswap; + swap->freeswap = i.freeswap; + return 0; + case LIBGTOP_PROCLIST: + proclist = table->data; + + if (nlen == 1) { + which = 0; + arg = 0; + } else if (nlen == 2) { + which = name [1]; + arg = 0; + } else if (nlen == 3) { + which = name [1]; + arg = name [2]; + } else { + return -EINVAL; + } + + tsk = task [0]; + read_lock (&tasklist_lock); + for (index = tindex = 0; index < nr_tasks; + index++, tsk = tsk->next_task) { + if (tsk->pid == 0) continue; + switch (which & LIBGTOP_PROCLIST_MASK) { + case LIBGTOP_PROCLIST_PID: + if (tsk->pid != arg) continue; + break; + case LIBGTOP_PROCLIST_PGRP: + if (tsk->pgrp != arg) continue; + break; + case LIBGTOP_PROCLIST_SESSION: + if (tsk->session != arg) continue; + break; + case LIBGTOP_PROCLIST_TTY: + tty = tsk->tty ? + kdev_t_to_nr (tsk->tty->device) : 0; + if (tty != arg) continue; + break; + case LIBGTOP_PROCLIST_UID: + if (tsk->uid != arg) continue; + break; + case LIBGTOP_PROCLIST_RUID: + if (tsk->euid != arg) continue; + break; + } + + if ((which & LIBGTOP_EXCLUDE_IDLE) && (tsk->state != 0)) + continue; + + if ((which & LIBGTOP_EXCLUDE_NOTTY) && (tsk->tty == NULL)) + continue; + + proclist->pids [tindex++] = tsk->pid; + } + + proclist->nr_running = nr_running; + proclist->last_pid = last_pid; + proclist->nr_tasks = tindex; + read_unlock(&tasklist_lock); + return 0; + default: + return -EINVAL; + } + + return 0; +} + +static int +system_ctl_handler (ctl_table *table, int *name, int nlen, + void *oldval, size_t *oldlenp, void *newval, + size_t newlen, void **context) +{ + int ret, len, len_name; + + if (!table->data || !table->maxlen) + return -ENOTDIR; + + if (!oldval || !oldlenp || get_user(len, oldlenp)) + return -EFAULT; + + if (!name || !nlen || get_user(len_name, name)) + return -EFAULT; + + if (len != table->maxlen) + return -EFAULT; + + ret = libgtop_sysctl (table, nlen, name); + if (ret) return ret; + + if(copy_to_user(oldval, table->data, len)) + return -EFAULT; + + return 1; +} + +static int +proc_ctl_handler (ctl_table *table, int *name, int nlen, + void *oldval, size_t *oldlenp, void *newval, + size_t newlen, void **context) +{ + int ret, len; + + printk ("proc_ctl_handler: %p - %p - %d - (%p,%p) - (%p,%d) - %p\n", + table, name, nlen, oldval, oldlenp, newval, newlen, context); + + if (!name || !nlen || get_user(len, name)) + return -EFAULT; + + printk ("FUNCTION: %d - %d - %p\n", table->ctl_name, + *name, table->de); + + if (!table->data || !table->maxlen) + return -ENOTDIR; + + if (!oldval || !oldlenp || get_user(len, oldlenp)) + return -EFAULT; + + if (len != table->maxlen) + return -EFAULT; + + return -ENOSYS; +} diff --git a/kernel/sysctl/libgtop.h b/kernel/sysctl/libgtop.h new file mode 100644 index 00000000..f860e546 --- /dev/null +++ b/kernel/sysctl/libgtop.h @@ -0,0 +1,82 @@ +#ifndef _LINUX_LIBGTOP_H +#define _LINUX_LIBGTOP_H 1 + +#include + +enum { + LIBGTOP_VERSION = 1, + LIBGTOP_PROC, + LIBGTOP_UPDATE_EXPENSIVE, + LIBGTOP_STAT, + LIBGTOP_MEM, + LIBGTOP_SWAP, + LIBGTOP_PROCLIST +}; + +enum { + LIBGTOP_PROCLIST_ALL = 0, + LIBGTOP_PROCLIST_PID, + LIBGTOP_PROCLIST_PGRP, + LIBGTOP_PROCLIST_SESSION, + LIBGTOP_PROCLIST_TTY, + LIBGTOP_PROCLIST_UID, + LIBGTOP_PROCLIST_RUID +}; + +#define LIBGTOP_PROCLIST_MASK 15 + +#define LIBGTOP_EXCLUDE_IDLE 0x1000 +#define LIBGTOP_EXCLUDE_SYSTEM 0x2000 +#define LIBGTOP_EXCLUDE_NOTTY 0x4000 + +typedef struct libgtop_stat libgtop_stat_t; + +typedef struct libgtop_cpu libgtop_cpu_t; +typedef struct libgtop_mem libgtop_mem_t; +typedef struct libgtop_swap libgtop_swap_t; +typedef struct libgtop_proclist libgtop_proclist_t; + +struct libgtop_cpu +{ + unsigned long total; /* Total CPU Time */ + unsigned long user; /* CPU Time in User Mode */ + unsigned long nice; /* CPU Time in User Mode (nice) */ + unsigned long sys; /* CPU Time in System Mode */ + unsigned long idle; /* CPU Time in the Idle Task */ +}; + +struct libgtop_mem +{ + unsigned long totalram; /* Total usable main memory size */ + unsigned long freeram; /* Available memory size */ + unsigned long sharedram; /* Amount of shared memory */ + unsigned long bufferram; /* Memory used by buffers */ +}; + +struct libgtop_swap +{ + unsigned long totalswap; /* Total swap space size */ + unsigned long freeswap; /* swap space still available */ +}; + +struct libgtop_proclist +{ + int nr_running, nr_tasks, last_pid; + unsigned pids [NR_TASKS]; +}; + +struct libgtop_stat +{ + int ncpu; /* Number of CPUs */ + unsigned long frequency; /* Tick frequency (HZ) */ + libgtop_cpu_t cpu; /* CPU statistics */ + libgtop_cpu_t xcpu [NR_CPUS]; /* SMP per-CPU statistics */ + double loadavg [3]; /* Load average */ + unsigned long total_forks; /* Total # of forks */ + unsigned int context_swtch; /* Total # of context switches */ + unsigned long boot_time; /* Boot time (seconds s. epoch) */ + unsigned int pgpgin, pgpgout; /* # of pages paged in/out */ + unsigned int pswpin, pswpout; /* # of swap pgs brought in/out */ +}; + +#endif diff --git a/kernel/sysctl/libgtop_syms.c b/kernel/sysctl/libgtop_syms.c new file mode 100644 index 00000000..874dadcd --- /dev/null +++ b/kernel/sysctl/libgtop_syms.c @@ -0,0 +1,24 @@ +/* + * linux/libgtop/libgtop_syms.c + * Copyright (C) 1999 Martin Baulig + */ + +#include +#include + +#include + +#include +#include +#include + +extern unsigned long total_forks; + +EXPORT_SYMBOL(task); +EXPORT_SYMBOL(avenrun); +EXPORT_SYMBOL(nr_running); +EXPORT_SYMBOL(nr_tasks); +EXPORT_SYMBOL(last_pid); +EXPORT_SYMBOL(total_forks); +EXPORT_SYMBOL(si_swapinfo); + diff --git a/kernel/sysctl/main.c b/kernel/sysctl/main.c new file mode 100644 index 00000000..6d391eb4 --- /dev/null +++ b/kernel/sysctl/main.c @@ -0,0 +1,4 @@ +/* + * linux/libgtop/main.c + * Copyright (C) 1999 Martin Baulig + */