1/* 2 * linux/kernel/info.c 3 * 4 * Copyright (C) 1992 Darren Senn 5 */ 6 7/* This implements the sysinfo() system call */ 8 9#include <linux/mm.h> 10#include <linux/unistd.h> 11#include <linux/swap.h> 12#include <linux/smp_lock.h> 13 14#include <asm/uaccess.h> 15 16asmlinkage long sys_sysinfo(struct sysinfo *info) 17{ 18 struct sysinfo val; 19 20 memset((char *)&val, 0, sizeof(struct sysinfo)); 21 22 cli(); 23 val.uptime = jiffies / HZ; 24 25 val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT); 26 val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT); 27 val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT); 28 29 val.procs = nr_threads-1; 30 sti(); 31 32 si_meminfo(&val); 33 si_swapinfo(&val); 34 35 { 36 unsigned long mem_total, sav_total; 37 unsigned int mem_unit, bitcount; 38 39 /* If the sum of all the available memory (i.e. ram + swap) 40 * is less than can be stored in a 32 bit unsigned long then 41 * we can be binary compatible with 2.2.x kernels. If not, 42 * well, in that case 2.2.x was broken anyways... 43 * 44 * -Erik Andersen <andersee@debian.org> */ 45 46 mem_total = val.totalram + val.totalswap; 47 if (mem_total < val.totalram || mem_total < val.totalswap) 48 goto out; 49 bitcount = 0; 50 mem_unit = val.mem_unit; 51 while (mem_unit > 1) { 52 bitcount++; 53 mem_unit >>= 1; 54 sav_total = mem_total; 55 mem_total <<= 1; 56 if (mem_total < sav_total) 57 goto out; 58 } 59 60 /* If mem_total did not overflow, multiply all memory values by 61 * val.mem_unit and set it to 1. This leaves things compatible 62 * with 2.2.x, and also retains compatibility with earlier 2.4.x 63 * kernels... */ 64 65 val.mem_unit = 1; 66 val.totalram <<= bitcount; 67 val.freeram <<= bitcount; 68 val.sharedram <<= bitcount; 69 val.bufferram <<= bitcount; 70 val.totalswap <<= bitcount; 71 val.freeswap <<= bitcount; 72 val.totalhigh <<= bitcount; 73 val.freehigh <<= bitcount; 74 } 75out: 76 if (copy_to_user(info, &val, sizeof(struct sysinfo))) 77 return -EFAULT; 78 return 0; 79} 80