diff options
author | Martin Baulig <martin@src.gnome.org> | 1998-07-21 17:16:23 +0000 |
---|---|---|
committer | Martin Baulig <martin@src.gnome.org> | 1998-07-21 17:16:23 +0000 |
commit | fc2d1f07c3f831266c0536aa5348d0f39238adad (patch) | |
tree | fdf5dea390bf4a0b7c9e9dd158ffa34d08d82294 | |
parent | 694ad7adb743e7ce071ebcf81ab1eea260204689 (diff) | |
download | libgtop-fc2d1f07c3f831266c0536aa5348d0f39238adad.tar.gz |
Initial revision
-rw-r--r-- | kernel/table21/Makefile | 16 | ||||
-rw-r--r-- | kernel/table21/README | 21 | ||||
-rw-r--r-- | kernel/table21/main.c | 61 | ||||
-rw-r--r-- | kernel/table21/module.c | 524 | ||||
-rw-r--r-- | kernel/table21/table.h | 166 | ||||
-rw-r--r-- | kernel/table21/version.h | 1 |
6 files changed, 789 insertions, 0 deletions
diff --git a/kernel/table21/Makefile b/kernel/table21/Makefile new file mode 100644 index 00000000..7d30495b --- /dev/null +++ b/kernel/table21/Makefile @@ -0,0 +1,16 @@ +# +# Makefile for the linux system information tables. +# +# 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 := table.o +OX_OBJS := main.o + +M_TARGET := module.o +MX_OBJS := module.o + +include $(TOPDIR)/Rules.make diff --git a/kernel/table21/README b/kernel/table21/README new file mode 100644 index 00000000..88d26bec --- /dev/null +++ b/kernel/table21/README @@ -0,0 +1,21 @@ +This is a new system call `table ()' for the Linux table. It is faster +than reading from /proc and can be used to fetch all information required +for libgtop until whe have some other function (extended sysctl, ...) in +standard kernels. + +I didn't want to change sysctl or some other function myself cause this may +cause other applications relying upon those function to fail. This is +something for the ``real'' kernel gurus ... + +To use this new system call for libgtop, do the following: + +* Copy this directory to /usr/src/linux/table +* Make /usr/src/linux/include/linux/table.h symlink to /usr/src/linux/table/table.h +* Apply the patch `kernel.patch' to the kernel, compile, install and reboot +* Recompile libgtop (remove `config.cache' and run the `autogen.sh' again). + +If you want to change and/or add something - feel free to do so ! + +Have fun, + +Martin diff --git a/kernel/table21/main.c b/kernel/table21/main.c new file mode 100644 index 00000000..e6d1882b --- /dev/null +++ b/kernel/table21/main.c @@ -0,0 +1,61 @@ +/* + * linux/table/table_impl.c + * Copyright (C) 1998 Martin Baulig + */ + +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/kernel_stat.h> +#include <linux/tty.h> +#include <linux/user.h> +#include <linux/a.out.h> +#include <linux/string.h> +#include <linux/mman.h> +#include <linux/proc_fs.h> +#include <linux/ioport.h> +#include <linux/config.h> +#include <linux/mm.h> +#include <linux/pagemap.h> +#include <linux/swap.h> +#include <linux/slab.h> +#include <linux/smp.h> +#include <linux/signal.h> + +#include <asm/uaccess.h> +#include <asm/pgtable.h> +#include <asm/io.h> + +#include <linux/module.h> +#include <linux/table.h> + +#include "version.h" + +extern void scheduling_functions_start_here(void); +extern void scheduling_functions_end_here(void); + +int (*table_function_ptr) (int, union table *, const void *) = 0; + +EXPORT_SYMBOL(table_function_ptr); + +EXPORT_SYMBOL(nr_running); +EXPORT_SYMBOL(pidhash); +EXPORT_SYMBOL(task); +EXPORT_SYMBOL(si_swapinfo); +EXPORT_SYMBOL(scheduling_functions_start_here); +EXPORT_SYMBOL(scheduling_functions_end_here); +EXPORT_SYMBOL(avenrun); +EXPORT_SYMBOL(nr_tasks); +EXPORT_SYMBOL(last_pid); +EXPORT_SYMBOL(page_cache_size); +EXPORT_SYMBOL(init_mm); + +asmlinkage int +sys_table (int type, union table *buf, const void *param) +{ + if (table_function_ptr == 0) + return -ENOSYS; + + return (*table_function_ptr) (type, buf, param); +} diff --git a/kernel/table21/module.c b/kernel/table21/module.c new file mode 100644 index 00000000..b23fb053 --- /dev/null +++ b/kernel/table21/module.c @@ -0,0 +1,524 @@ +/* + * linux/table/table_impl.c + * Copyright (C) 1998 Martin Baulig + */ + +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/kernel_stat.h> +#include <linux/tty.h> +#include <linux/user.h> +#include <linux/a.out.h> +#include <linux/string.h> +#include <linux/mman.h> +#include <linux/proc_fs.h> +#include <linux/ioport.h> +#include <linux/config.h> +#include <linux/mm.h> +#include <linux/pagemap.h> +#include <linux/swap.h> +#include <linux/slab.h> +#include <linux/smp.h> +#include <linux/signal.h> + +#include <asm/uaccess.h> +#include <asm/pgtable.h> +#include <asm/io.h> + +#include <linux/module.h> +#include <linux/table.h> + +#include "version.h" + +extern int (*table_function_ptr) (int, union table *, const void *); + +int table_fkt (int, union table *, const void *); + +EXPORT_NO_SYMBOLS; + +int +init_module(void) +{ + printk ("init_module () = %p\n", table_fkt); + table_function_ptr = table_fkt; + return 0; +} + +void +cleanup_module(void) +{ + table_function_ptr = 0; +} + +#define LOAD_INT(x) ((x) >> FSHIFT) +#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) + +#ifdef CONFIG_DEBUG_MALLOC +int get_malloc(char * buffer); +#endif + +static void collect_sigign_sigcatch(struct task_struct *p, sigset_t *ign, + sigset_t *catch) +{ + struct k_sigaction *k; + int i; + + sigemptyset(ign); + sigemptyset(catch); + + if (p->sig) { + k = p->sig->action; + for (i = 1; i <= _NSIG; ++i, ++k) { + if (k->sa.sa_handler == SIG_IGN) + sigaddset(ign, i); + else if (k->sa.sa_handler != SIG_DFL) + sigaddset(catch, i); + } + } +} + +/* + * These bracket the sleeping functions.. + */ +extern void scheduling_functions_start_here(void); +extern void scheduling_functions_end_here(void); +#define first_sched ((unsigned long) scheduling_functions_start_here) +#define last_sched ((unsigned long) scheduling_functions_end_here) + +static unsigned long get_wchan(struct task_struct *p) +{ + if (!p || p == current || p->state == TASK_RUNNING) + return 0; +#if defined(__i386__) + { + unsigned long ebp, eip; + unsigned long stack_page; + int count = 0; + + stack_page = 4096 + (unsigned long)p; + if (!stack_page) + return 0; + ebp = p->tss.ebp; + do { + if (ebp < stack_page || ebp >= 4092+stack_page) + return 0; + eip = *(unsigned long *) (ebp+4); + if (eip < first_sched || eip >= last_sched) + return eip; + ebp = *(unsigned long *) ebp; + } while (count++ < 16); + } +#elif defined(__alpha__) + /* + * This one depends on the frame size of schedule(). Do a + * "disass schedule" in gdb to find the frame size. Also, the + * code assumes that sleep_on() follows immediately after + * interruptible_sleep_on() and that add_timer() follows + * immediately after interruptible_sleep(). Ugly, isn't it? + * Maybe adding a wchan field to task_struct would be better, + * after all... + */ + { + unsigned long schedule_frame; + unsigned long pc; + + pc = thread_saved_pc(&p->tss); + if (pc >= first_sched && pc < last_sched) { + schedule_frame = ((unsigned long *)p->tss.ksp)[6]; + return ((unsigned long *)schedule_frame)[12]; + } + return pc; + } +#elif defined(__mc68000__) + { + unsigned long fp, pc; + unsigned long stack_page; + int count = 0; + extern int sys_pause (void); + + stack_page = p->kernel_stack_page; + if (!stack_page) + return 0; + fp = ((struct switch_stack *)p->tss.ksp)->a6; + do { + if (fp < stack_page || fp >= 4088+stack_page) + return 0; + pc = ((unsigned long *)fp)[1]; + /* FIXME: This depends on the order of these functions. */ + if (pc < first_sched || pc >= last_sched) + return pc; + fp = *(unsigned long *) fp; + } while (count++ < 16); + } +#elif defined(__powerpc__) + return (p->tss.wchan); +#elif defined (CONFIG_ARM) + { + unsigned long fp, lr; + unsigned long stack_page; + int count = 0; + + stack_page = 4096 + (unsigned long)p; + fp = get_css_fp (&p->tss); + do { + if (fp < stack_page || fp > 4092+stack_page) + return 0; + lr = pc_pointer (((unsigned long *)fp)[-1]); + if (lr < first_sched || lr > last_sched) + return lr; + fp = *(unsigned long *) (fp - 12); + } while (count ++ < 16); + } +#endif + return 0; +} + +#if defined(__i386__) +# define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019]) +# define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022]) +#elif defined(__alpha__) + /* + * See arch/alpha/kernel/ptrace.c for details. + */ +# define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \ + + (long)&((struct pt_regs *)0)->reg) +# define KSTK_EIP(tsk) \ + (*(unsigned long *)(PT_REG(pc) + PAGE_SIZE + (unsigned long)(tsk))) +# define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->tss.usp) +#elif defined(CONFIG_ARM) +# define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022]) +# define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1020]) +#elif defined(__mc68000__) +#define KSTK_EIP(tsk) \ + ({ \ + unsigned long eip = 0; \ + if ((tsk)->tss.esp0 > PAGE_SIZE && \ + MAP_NR((tsk)->tss.esp0) < max_mapnr) \ + eip = ((struct pt_regs *) (tsk)->tss.esp0)->pc; \ + eip; }) +#define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->tss.usp) +#elif defined(__powerpc__) +#define KSTK_EIP(tsk) ((tsk)->tss.regs->nip) +#define KSTK_ESP(tsk) ((tsk)->tss.regs->gpr[1]) +#elif defined (__sparc_v9__) +# define KSTK_EIP(tsk) ((tsk)->tss.kregs->tpc) +# define KSTK_ESP(tsk) ((tsk)->tss.kregs->u_regs[UREG_FP]) +#elif defined(__sparc__) +# define KSTK_EIP(tsk) ((tsk)->tss.kregs->pc) +# define KSTK_ESP(tsk) ((tsk)->tss.kregs->u_regs[UREG_FP]) +#endif + +/* Gcc optimizes away "strlen(x)" for constant x */ +#define ADDBUF(buffer, string) \ +do { memcpy(buffer, string, strlen(string)); \ + buffer += strlen(string); } while (0) + +static inline void statm_pte_range(pmd_t * pmd, unsigned long address, unsigned long size, + int * pages, int * shared, int * dirty, int * total) +{ + pte_t * pte; + unsigned long end; + + if (pmd_none(*pmd)) + return; + if (pmd_bad(*pmd)) { + printk("statm_pte_range: bad pmd (%08lx)\n", pmd_val(*pmd)); + pmd_clear(pmd); + return; + } + pte = pte_offset(pmd, address); + address &= ~PMD_MASK; + end = address + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + do { + pte_t page = *pte; + + address += PAGE_SIZE; + pte++; + if (pte_none(page)) + continue; + ++*total; + if (!pte_present(page)) + continue; + ++*pages; + if (pte_dirty(page)) + ++*dirty; + if (MAP_NR(pte_page(page)) >= max_mapnr) + continue; + if (atomic_read(&mem_map[MAP_NR(pte_page(page))].count) > 1) + ++*shared; + } while (address < end); +} + +static inline void statm_pmd_range(pgd_t * pgd, unsigned long address, unsigned long size, + int * pages, int * shared, int * dirty, int * total) +{ + pmd_t * pmd; + unsigned long end; + + if (pgd_none(*pgd)) + return; + if (pgd_bad(*pgd)) { + printk("statm_pmd_range: bad pgd (%08lx)\n", pgd_val(*pgd)); + pgd_clear(pgd); + return; + } + pmd = pmd_offset(pgd, address); + address &= ~PGDIR_MASK; + end = address + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + do { + statm_pte_range(pmd, address, end - address, pages, shared, dirty, total); + address = (address + PMD_SIZE) & PMD_MASK; + pmd++; + } while (address < end); +} + +static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long end, + int * pages, int * shared, int * dirty, int * total) +{ + while (address < end) { + statm_pmd_range(pgd, address, end - address, pages, shared, dirty, total); + address = (address + PGDIR_SIZE) & PGDIR_MASK; + pgd++; + } +} + +int +table_fkt (int type, union table *buf, const void *param) +{ + union table tbl; + struct sysinfo i; + struct task_struct *tsk = NULL; + int index, err; + pid_t pid; + + if (type == TABLE_VERSION) + return _TABLE_VERSION; + + if (!buf) + return -EFAULT; + + memset (&tbl, 0, sizeof (union table)); + + /* For TABLE_PROC_*, read pid and get task_struct */ + + switch (type) { + case TABLE_PROC_UID: + case TABLE_PROC_MEM: + case TABLE_PROC_SEGMENT: + case TABLE_PROC_TIME: + case TABLE_PROC_STATE: + case TABLE_PROC_SIGNAL: + case TABLE_PROC_KERNEL: + err = verify_area (VERIFY_READ, param, sizeof (pid_t)); + if (err) + return err; + copy_from_user (&pid, param, sizeof (pid_t)); + + read_lock (&tasklist_lock); + tsk = find_task_by_pid (pid); + /* FIXME!! This should be done after the last use */ + read_unlock(&tasklist_lock); + + if (tsk == NULL) + return -ESRCH; + break; + } + + /* Main function dispatcher */ + + switch (type) { + case TABLE_PROCLIST: + tsk = task [0]; + for (index = 0; index < nr_tasks; index++) { + tbl.proclist.pids [index] = tsk->pid; + tsk = tsk->next_task; + } + tbl.proclist.nr_running = nr_running; + tbl.proclist.nr_tasks = nr_tasks; + tbl.proclist.last_pid = last_pid; + break; + case TABLE_CPU: + tbl.cpu.total = jiffies; + tbl.cpu.user = kstat.cpu_user; + tbl.cpu.nice = kstat.cpu_nice; + tbl.cpu.sys = kstat.cpu_system; + tbl.cpu.idle = tbl.cpu.total - + (tbl.cpu.user + tbl.cpu.nice + tbl.cpu.sys); + tbl.cpu.frequency = HZ; + break; + case TABLE_MEM: + si_meminfo (&i); + tbl.mem.total = i.totalram; + tbl.mem.used = i.totalram - i.freeram; + tbl.mem.free = i.freeram; + tbl.mem.shared = i.sharedram; + tbl.mem.buffer = i.bufferram; + tbl.mem.cached = page_cache_size << PAGE_SHIFT; + break; + case TABLE_SWAP: + si_swapinfo (&i); + tbl.swap.total = i.totalswap; + tbl.swap.used = i.totalswap - i.freeswap; + tbl.swap.free = i.freeswap; + break; + case TABLE_LOADAVG: + tbl.loadavg.loadavg [0] = (double) avenrun [0] / (1 << FSHIFT); + tbl.loadavg.loadavg [1] = (double) avenrun [1] / (1 << FSHIFT); + tbl.loadavg.loadavg [2] = (double) avenrun [2] / (1 << FSHIFT); + tbl.loadavg.nr_running = nr_running; + tbl.loadavg.nr_tasks = nr_tasks; + tbl.loadavg.last_pid = last_pid; + break; + case TABLE_UPTIME: + tbl.uptime.uptime = jiffies; + tbl.uptime.idle = task[0]->times.tms_utime + + task[0]->times.tms_stime; + break; + case TABLE_PROC_STATE: + tbl.proc_state.state = tsk->state; + tbl.proc_state.flags = tsk->flags; + memcpy (tbl.proc_state.comm, tsk->comm, + sizeof (tbl.proc_state.comm)); + break; + case TABLE_PROC_UID: + tbl.proc_uid.uid = tsk->uid; + tbl.proc_uid.euid = tsk->euid; + tbl.proc_uid.suid = tsk->suid; + tbl.proc_uid.fsuid = tsk->fsuid; + + tbl.proc_uid.gid = tsk->gid; + tbl.proc_uid.egid = tsk->egid; + tbl.proc_uid.sgid = tsk->sgid; + tbl.proc_uid.fsgid = tsk->fsgid; + + tbl.proc_uid.pid = tsk->pid; + tbl.proc_uid.pgrp = tsk->pgrp; + tbl.proc_uid.ppid = tsk->p_pptr->pid; + + tbl.proc_uid.session = tsk->session; + tbl.proc_uid.tty = tsk->tty ? + kdev_t_to_nr (tsk->tty->device) : 0; + tbl.proc_uid.tpgid = tsk->tty ? tsk->tty->pgrp : -1; + + tbl.proc_uid.priority = tsk->priority; + tbl.proc_uid.counter = tsk->counter; + tbl.proc_uid.def_priority = DEF_PRIORITY; + break; + case TABLE_PROC_SIGNAL: + tbl.proc_signal.signal = tsk->signal; + tbl.proc_signal.blocked = tsk->blocked; + + collect_sigign_sigcatch (tsk, &tbl.proc_signal.ignored, + &tbl.proc_signal.caught); + break; + case TABLE_PROC_MEM: + if (tsk->mm && tsk->mm != &init_mm) { + tbl.proc_mem.context = tsk->mm->context; + tbl.proc_mem.start_code = tsk->mm->start_code; + tbl.proc_mem.end_code = tsk->mm->end_code; + tbl.proc_mem.start_data = tsk->mm-> start_data; + tbl.proc_mem.end_data = tsk->mm->end_data; + tbl.proc_mem.start_brk = tsk->mm->start_brk; + tbl.proc_mem.brk = tsk->mm->brk; + tbl.proc_mem.start_stack = tsk->mm->start_stack; + tbl.proc_mem.start_mmap = tsk->mm->mmap ? + tsk->mm->mmap->vm_start : 0; + tbl.proc_mem.arg_start = tsk->mm->arg_start; + tbl.proc_mem.arg_end = tsk->mm->arg_end; + tbl.proc_mem.env_start = tsk->mm->env_start; + tbl.proc_mem.env_end = tsk->mm->env_end; + tbl.proc_mem.rss = tsk->mm->rss; + tbl.proc_mem.total_vm = tsk->mm->total_vm; + tbl.proc_mem.locked_vm = tsk->mm->locked_vm; + } + tbl.proc_mem.rlim = tsk->rlim ? tsk->rlim[RLIMIT_RSS].rlim_cur : 0; + break; + case TABLE_PROC_SEGMENT: + if (tsk->mm && tsk->mm != &init_mm) { + unsigned long vsize = 0; + int size = 0, resident = 0, share = 0; + int trs = 0, lrs = 0, drs = 0, dt = 0; + struct vm_area_struct * vma = tsk->mm->mmap; + + while (vma) { + pgd_t *pgd = pgd_offset(tsk->mm, vma->vm_start); + int pages = 0, shared = 0, dirty = 0, total = 0; + + vsize += vma->vm_end - vma->vm_start; + + statm_pgd_range (pgd, vma->vm_start, vma->vm_end, + &pages, &shared, &dirty, &total); + resident += pages; + share += shared; + dt += dirty; + size += total; + if (vma->vm_flags & VM_EXECUTABLE) + trs += pages; /* text */ + else if (vma->vm_flags & VM_GROWSDOWN) + drs += pages; /* stack */ + else if (vma->vm_end > 0x60000000) + lrs += pages; /* library */ + else + drs += pages; + vma = vma->vm_next; + } + + tbl.proc_segment.vsize = vsize; + tbl.proc_segment.size = size; + tbl.proc_segment.resident = resident; + tbl.proc_segment.shared = share; + tbl.proc_segment.trs = trs; + tbl.proc_segment.lrs = lrs; + tbl.proc_segment.dt = dt; + } + break; + case TABLE_PROC_TIME: + tbl.proc_time.utime = tsk->times.tms_utime; + tbl.proc_time.stime = tsk->times.tms_stime; + tbl.proc_time.cutime = tsk->times.tms_cutime; + tbl.proc_time.cstime = tsk->times.tms_cstime; + + tbl.proc_time.start_time = tsk->start_time; + tbl.proc_time.timeout = tsk->timeout; + tbl.proc_time.policy = tsk->policy; + tbl.proc_time.rt_priority = tsk->rt_priority; + + tbl.proc_time.it_real_value = tsk->it_real_value; + tbl.proc_time.it_prof_value = tsk->it_prof_value; + tbl.proc_time.it_virt_value = tsk->it_virt_value; + tbl.proc_time.it_real_incr = tsk->it_real_incr; + tbl.proc_time.it_prof_incr = tsk->it_prof_incr; + tbl.proc_time.it_virt_incr = tsk->it_virt_incr; + break; + case TABLE_PROC_KERNEL: + tbl.proc_kernel.min_flt = tsk->min_flt; + tbl.proc_kernel.cmin_flt = tsk->cmin_flt; + tbl.proc_kernel.maj_flt = tsk->maj_flt; + tbl.proc_kernel.cmaj_flt = tsk->cmaj_flt; + + tbl.proc_kernel.kesp = KSTK_EIP(tsk); + tbl.proc_kernel.keip = KSTK_ESP(tsk); + + tbl.proc_kernel.nswap = tsk->nswap; + tbl.proc_kernel.cnswap = tsk->cnswap; + + tbl.proc_kernel.wchan = get_wchan (tsk); + break; + default: + return -EINVAL; + } + + err = verify_area (VERIFY_WRITE, buf, sizeof (struct table)); + if (err) + return err; + + copy_to_user (buf, &tbl, sizeof (union table)); + + return 0; +} diff --git a/kernel/table21/table.h b/kernel/table21/table.h new file mode 100644 index 00000000..51aabf62 --- /dev/null +++ b/kernel/table21/table.h @@ -0,0 +1,166 @@ +#ifndef _LINUX_TABLE_H +#define _LINUX_TABLE_H + +#ifdef _KERNEL +#include <linux/types.h> +#else +#define NR_TASKS 512 +#endif + +#define TABLE_VERSION 0 +#define TABLE_CPU 1 +#define TABLE_MEM 2 +#define TABLE_SWAP 3 +#define TABLE_LOADAVG 4 +#define TABLE_UPTIME 5 +#define TABLE_PROCLIST 6 +#define TABLE_PROC_UID 7 +#define TABLE_PROC_MEM 8 +#define TABLE_PROC_SEGMENT 9 +#define TABLE_PROC_TIME 10 +#define TABLE_PROC_STATE 11 +#define TABLE_PROC_SIGNAL 12 +#define TABLE_PROC_KERNEL 13 + +/* CPU Usage (in jiffies = 1/100th seconds) */ + +struct table_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 */ + unsigned long frequency; /* Tick frequency */ +}; + +/* Memory Usage (in bytes) */ + +struct table_mem +{ + unsigned long total; /* Total physical memory */ + unsigned long used; /* Used memory size */ + unsigned long free; /* Free memory size */ + unsigned long shared; /* Shared memory size */ + unsigned long buffer; /* Size of buffers */ + unsigned long cached; /* Size of cached memory */ +}; + +/* Swap Space (in bytes) */ + +struct table_swap +{ + unsigned long total; /* Total swap space */ + unsigned long used; /* Used swap space */ + unsigned long free; /* Free swap space */ +}; + +/* Load average */ + +struct table_loadavg +{ + double loadavg [3]; + unsigned nr_running; + unsigned nr_tasks; + unsigned last_pid; +}; + +/* Uptime */ + +struct table_uptime +{ + unsigned long uptime; + unsigned long idle; +}; + +/* Process list. */ + +struct table_proclist +{ + int nr_running, nr_tasks, last_pid; + unsigned pids [NR_TASKS]; +}; + +/* Information about processes. */ + +struct table_proc_state +{ + long state; + unsigned long flags; + char comm[16]; +}; + +struct table_proc_uid +{ + int uid, euid, suid, fsuid; + int gid, egid, sgid, fsgid; + int pid, pgrp, ppid; + int session; + unsigned int tty; + int tpgid; + long priority; + long counter; + long def_priority; +}; + +struct table_proc_mem +{ + unsigned long context; + unsigned long start_code, end_code, start_data, end_data; + unsigned long start_brk, brk, start_stack, start_mmap; + unsigned long arg_start, arg_end, env_start, env_end; + unsigned long rss, rlim, total_vm, locked_vm; +}; + +struct table_proc_segment +{ + unsigned long vsize; + int size, resident, shared; + int trs, lrs, drs, dt; +}; + +struct table_proc_time +{ + long utime, stime, cutime, cstime, start_time; + unsigned long timeout, policy, rt_priority; + unsigned long it_real_value, it_prof_value, it_virt_value; + unsigned long it_real_incr, it_prof_incr, it_virt_incr; +}; + +struct table_proc_signal +{ + sigset_t signal; + sigset_t blocked; /* bitmap of masked signals */ + sigset_t ignored; /* mask of ignored signals */ + sigset_t caught; /* mask of caught signals */ +}; + +struct table_proc_kernel +{ + unsigned long keip, kesp, wchan; + unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt; + unsigned long nswap, cnswap; +}; + +/* Union */ + +union table +{ + struct table_cpu cpu; + struct table_mem mem; + struct table_swap swap; + struct table_loadavg loadavg; + struct table_uptime uptime; + struct table_proclist proclist; + struct table_proc_uid proc_uid; + struct table_proc_mem proc_mem; + struct table_proc_segment proc_segment; + struct table_proc_time proc_time; + struct table_proc_state proc_state; + struct table_proc_signal proc_signal; + struct table_proc_kernel proc_kernel; +}; + +#endif /* _LINUX_IPC_H */ + + diff --git a/kernel/table21/version.h b/kernel/table21/version.h new file mode 100644 index 00000000..d47411ee --- /dev/null +++ b/kernel/table21/version.h @@ -0,0 +1 @@ +#define _TABLE_VERSION 1 |