]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] sys_sysinfo cleanup
authorRobert Love <rml@tech9.net>
Mon, 3 Jun 2002 03:56:04 +0000 (20:56 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Mon, 3 Jun 2002 03:56:04 +0000 (20:56 -0700)
Looks like sys_sysinfo has not been touched in years.  Among other
things, it uses a global cli() for protection; I switched it to an
existing rwlock.  I also pulled it out of info.c and stuck it in timer.c
(I choose timer.c because it shares dependencies there already).

The details:

        - move sys_sysinfo to kernel/timer.c from kernel/info.c:
          why one small syscall got its own file is beyond me.

        - delete kernel/info.c

        - stop the global cli!  now grab a read_lock on xtime_lock.
          this is safe as we moved the write_unlock on xtime_lock
          down one line to cover the calculating of avenrun.

        - trivial code cleanup

kernel/Makefile
kernel/info.c [deleted file]
kernel/timer.c

index 23efe9a8698d376f132e8524f2994cb02a00944b..d0cad7d5115cd7684dbbe0c57adf572f4c1866f4 100644 (file)
@@ -13,7 +13,7 @@ export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o \
                printk.o platform.o suspend.o
 
 obj-y     = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
-           module.o exit.o itimer.o info.o time.o softirq.o resource.o \
+           module.o exit.o itimer.o time.o softirq.o resource.o \
            sysctl.o capability.o ptrace.o timer.o user.o \
            signal.o sys.o kmod.o context.o futex.o platform.o
 
diff --git a/kernel/info.c b/kernel/info.c
deleted file mode 100644 (file)
index 5894f25..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * linux/kernel/info.c
- *
- * Copyright (C) 1992 Darren Senn
- */
-
-/* This implements the sysinfo() system call */
-
-#include <linux/mm.h>
-#include <linux/unistd.h>
-#include <linux/swap.h>
-#include <linux/smp_lock.h>
-
-#include <asm/uaccess.h>
-
-asmlinkage long sys_sysinfo(struct sysinfo *info)
-{
-       struct sysinfo val;
-
-       memset((char *)&val, 0, sizeof(struct sysinfo));
-
-       cli();
-       val.uptime = jiffies / HZ;
-
-       val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
-       val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT);
-       val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT);
-
-       val.procs = nr_threads;
-       sti();
-
-       si_meminfo(&val);
-       si_swapinfo(&val);
-
-       {
-               unsigned long mem_total, sav_total;
-               unsigned int mem_unit, bitcount;
-
-               /* If the sum of all the available memory (i.e. ram + swap)
-                * is less than can be stored in a 32 bit unsigned long then
-                * we can be binary compatible with 2.2.x kernels.  If not,
-                * well, in that case 2.2.x was broken anyways...
-                *
-                *  -Erik Andersen <andersee@debian.org> */
-
-               mem_total = val.totalram + val.totalswap;
-               if (mem_total < val.totalram || mem_total < val.totalswap)
-                       goto out;
-               bitcount = 0;
-               mem_unit = val.mem_unit;
-               while (mem_unit > 1) {
-                       bitcount++;
-                       mem_unit >>= 1;
-                       sav_total = mem_total;
-                       mem_total <<= 1;
-                       if (mem_total < sav_total)
-                               goto out;
-               }
-
-               /* If mem_total did not overflow, multiply all memory values by
-                * val.mem_unit and set it to 1.  This leaves things compatible
-                * with 2.2.x, and also retains compatibility with earlier 2.4.x
-                * kernels...  */
-
-               val.mem_unit = 1;
-               val.totalram <<= bitcount;
-               val.freeram <<= bitcount;
-               val.sharedram <<= bitcount;
-               val.bufferram <<= bitcount;
-               val.totalswap <<= bitcount;
-               val.freeswap <<= bitcount;
-               val.totalhigh <<= bitcount;
-               val.freehigh <<= bitcount;
-       }
-out:
-       if (copy_to_user(info, &val, sizeof(struct sysinfo)))
-               return -EFAULT;
-       return 0;
-}
index 62a36b5740a77c59f46e553368d91ae1868825a4..0b7efa84970b3c304034c13f772da4cdf2b6c628 100644 (file)
@@ -13,6 +13,7 @@
  *              serialize accesses to xtime/lost_ticks).
  *                              Copyright (C) 1998  Andrea Arcangeli
  *  1999-03-10  Improved NTP compatibility by Ulrich Windl
+ *  2002-05-31 Move sys_sysinfo here and make its locking sane, Robert Love
  */
 
 #include <linux/config.h>
@@ -605,9 +606,15 @@ static unsigned long count_active_tasks(void)
  * imply that avenrun[] is the standard name for this kind of thing.
  * Nothing else seems to be standardized: the fractional size etc
  * all seem to differ on different machines.
+ *
+ * Requires xtime_lock to access.
  */
 unsigned long avenrun[3];
 
+/*
+ * calc_load - given tick count, update the avenrun load estimates.
+ * This is called while holding a write_lock on xtime_lock.
+ */
 static inline void calc_load(unsigned long ticks)
 {
        unsigned long active_tasks; /* fixed-point */
@@ -627,7 +634,8 @@ static inline void calc_load(unsigned long ticks)
 unsigned long wall_jiffies;
 
 /*
- * This spinlock protect us from races in SMP while playing with xtime. -arca
+ * This read-write spinlock protects us from races in SMP while
+ * playing with xtime and avenrun.
  */
 rwlock_t xtime_lock = RW_LOCK_UNLOCKED;
 unsigned long last_time_offset;
@@ -649,8 +657,8 @@ static inline void update_times(void)
                update_wall_time(ticks);
        }
        last_time_offset = 0;
-       write_unlock_irq(&xtime_lock);
        calc_load(ticks);
+       write_unlock_irq(&xtime_lock);
 }
 
 void timer_bh(void)
@@ -912,3 +920,73 @@ asmlinkage long sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp)
        return 0;
 }
 
+/*
+ * sys_sysinfo - fill in sysinfo struct
+ */ 
+asmlinkage long sys_sysinfo(struct sysinfo *info)
+{
+       struct sysinfo val;
+       unsigned long mem_total, sav_total;
+       unsigned int mem_unit, bitcount;
+
+       memset((char *)&val, 0, sizeof(struct sysinfo));
+
+       read_lock_irq(&xtime_lock);
+       val.uptime = jiffies / HZ;
+
+       val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
+       val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT);
+       val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT);
+
+       val.procs = nr_threads;
+       read_unlock_irq(&xtime_lock);
+
+       si_meminfo(&val);
+       si_swapinfo(&val);
+
+       /*
+        * If the sum of all the available memory (i.e. ram + swap)
+        * is less than can be stored in a 32 bit unsigned long then
+        * we can be binary compatible with 2.2.x kernels.  If not,
+        * well, in that case 2.2.x was broken anyways...
+        *
+        *  -Erik Andersen <andersee@debian.org>
+        */
+
+       mem_total = val.totalram + val.totalswap;
+       if (mem_total < val.totalram || mem_total < val.totalswap)
+               goto out;
+       bitcount = 0;
+       mem_unit = val.mem_unit;
+       while (mem_unit > 1) {
+               bitcount++;
+               mem_unit >>= 1;
+               sav_total = mem_total;
+               mem_total <<= 1;
+               if (mem_total < sav_total)
+                       goto out;
+       }
+
+       /*
+        * If mem_total did not overflow, multiply all memory values by
+        * val.mem_unit and set it to 1.  This leaves things compatible
+        * with 2.2.x, and also retains compatibility with earlier 2.4.x
+        * kernels...
+        */
+
+       val.mem_unit = 1;
+       val.totalram <<= bitcount;
+       val.freeram <<= bitcount;
+       val.sharedram <<= bitcount;
+       val.bufferram <<= bitcount;
+       val.totalswap <<= bitcount;
+       val.freeswap <<= bitcount;
+       val.totalhigh <<= bitcount;
+       val.freehigh <<= bitcount;
+
+out:
+       if (copy_to_user(info, &val, sizeof(struct sysinfo)))
+               return -EFAULT;
+
+       return 0;
+}