Print statistics at power off.
authorBen Pfaff <blp@cs.stanford.edu>
Sun, 26 Sep 2004 21:15:17 +0000 (21:15 +0000)
committerBen Pfaff <blp@cs.stanford.edu>
Sun, 26 Sep 2004 21:15:17 +0000 (21:15 +0000)
16 files changed:
src/devices/disk.c
src/devices/disk.h
src/devices/kbd.c
src/devices/kbd.h
src/devices/timer.c
src/devices/timer.h
src/lib/kernel/console.c
src/lib/kernel/console.h
src/threads/init.c
src/threads/thread.c
src/threads/thread.h
src/userprog/exception.c
src/userprog/exception.h
src/userprog/pagedir.c
src/userprog/pagedir.h
src/userprog/syscall.c

index 5867caa19c2d599fa76d3f3bb4d217c67da596e5..baf120864399f11a8c33ae27f37a41992b413cab 100644 (file)
@@ -52,7 +52,10 @@ struct disk
     int dev_no;                 /* Device 0 or 1 for master or slave. */
 
     bool is_ata;                /* 1=This device is an ATA disk. */
-    disk_sector_t capacity;    /* Capacity in sectors (if is_ata is true). */
+    disk_sector_t capacity;     /* Capacity in sectors (if is_ata). */
+
+    long long read_cnt;         /* Number of sectors read. */
+    long long write_cnt;        /* Number of sectors written. */
   };
 
 /* An ATA channel (aka controller).
@@ -131,6 +134,8 @@ disk_init (void)
 
           d->is_ata = false;
           d->capacity = 0;
+
+          d->read_cnt = d->write_cnt = 0;
         }
 
       /* Register interrupt handler. */
@@ -150,6 +155,26 @@ disk_init (void)
     }
 }
 
+/* Prints disk statistics. */
+void
+disk_print_stats (void) 
+{
+  int chan_no;
+
+  for (chan_no = 0; chan_no < CHANNEL_CNT; chan_no++) 
+    {
+      int dev_no;
+
+      for (dev_no = 0; dev_no < 2; dev_no++) 
+        {
+          struct disk *d = disk_get (chan_no, dev_no);
+          if (d != NULL && d->is_ata) 
+            printf ("%s: %lld reads, %lld writes\n",
+                    d->name, d->read_cnt, d->write_cnt);
+        }
+    }
+}
+
 /* Returns the disk numbered DEV_NO--either 0 or 1 for master or
    slave, respectively--within the channel numbered CHAN_NO. */
 struct disk *
@@ -194,6 +219,7 @@ disk_read (struct disk *d, disk_sector_t sec_no, void *buffer)
   if (!wait_while_busy (d))
     PANIC ("%s: disk read failed, sector=%"PRDSNu, d->name, sec_no);
   input_sector (c, buffer);
+  d->read_cnt++;
   lock_release (&c->lock);
 }
 
@@ -216,6 +242,7 @@ disk_write (struct disk *d, disk_sector_t sec_no, const void *buffer)
     PANIC ("%s: disk write failed, sector=%"PRDSNu, d->name, sec_no);
   output_sector (c, buffer);
   sema_down (&c->completion_wait);
+  d->write_cnt++;
   lock_release (&c->lock);
 }
 \f
index 539c4b0bafdd8c589125e30d05266c4ded065210..3bcbb9a10612d223434bae8b81bd75b72de3d4d4 100644 (file)
@@ -16,6 +16,8 @@ typedef uint32_t disk_sector_t;
 #define PRDSNu PRIu32
 
 void disk_init (void);
+void disk_print_stats (void);
+
 struct disk *disk_get (int chan_no, int dev_no);
 disk_sector_t disk_size (struct disk *);
 void disk_read (struct disk *, disk_sector_t, void *);
index 9cd28400864abddcc1a18fa586eaf5951d9a96bb..a26498477cb3397c5f1d771b06303c5c6c3ffaaf 100644 (file)
@@ -25,6 +25,9 @@ static unsigned shift_state;
 /* Keyboard buffer. */
 static struct intq buffer;
 
+/* Number of keys pressed. */
+static int64_t key_cnt;
+
 static intr_handler_func keyboard_interrupt;
 
 /* Initializes the keyboard. */
@@ -49,6 +52,13 @@ kbd_getc (void)
   
   return key;
 }
+
+/* Prints keyboard statistics. */
+void
+kbd_print_stats (void) 
+{
+  printf ("Keyboard: %lld keys pressed\n", key_cnt);
+}
 \f
 /* Maps a set of contiguous scancodes into characters. */
 struct keymap
@@ -160,8 +170,11 @@ keyboard_interrupt (struct intr_frame *args UNUSED)
             c += 0x80;
 
           /* Append to keyboard buffer. */
-          if (!intq_full (&buffer))
-            intq_putc (&buffer, c);
+          if (!intq_full (&buffer)) 
+            {
+              key_cnt++;
+              intq_putc (&buffer, c); 
+            }
         }
     }
   else
index 1720d365335ed12249a29a9a19942282d6c04600..ecf477f566e35cc0d3c56aad2f079325b1724b4f 100644 (file)
@@ -5,5 +5,6 @@
 
 void kbd_init (void);
 uint8_t kbd_getc (void);
+void kbd_print_stats (void);
 
 #endif /* devices/kbd.h */
index 9c611a1d3eda68b6fd2317304faaef9381f9eb40..8f47c810ffc8af5a1c6804933fad710929450318 100644 (file)
@@ -1,6 +1,8 @@
 #include "devices/timer.h"
 #include <debug.h>
+#include <inttypes.h>
 #include <round.h>
+#include <stdio.h>
 #include "threads/interrupt.h"
 #include "threads/io.h"
 #include "threads/thread.h"
@@ -91,12 +93,20 @@ timer_ns2ticks (int64_t ns)
 {
   return DIV_ROUND_UP (ns * TIMER_FREQ, 1000000000);
 }
+
+/* Prints timer statistics. */
+void
+timer_print_stats (void) 
+{
+  printf ("Timer: %"PRId64" ticks.\n", ticks);
+}
 \f
 /* Timer interrupt handler. */
 static void
 timer_interrupt (struct intr_frame *args UNUSED)
 {
   ticks++;
+  thread_tick ();
   if (ticks % TIME_SLICE == 0)
     intr_yield_on_return ();
 }
index db76f6d3456345f9380dfdf880f314210cbe4b81..59f7c9a57835dc6fbc523b47c4cdd3d086119a17 100644 (file)
@@ -17,4 +17,6 @@ int64_t timer_ms2ticks (int64_t ms);
 int64_t timer_us2ticks (int64_t us);
 int64_t timer_ns2ticks (int64_t ns);
 
+void timer_print_stats (void);
+
 #endif /* devices/timer.h */
index 14c707a63681129a66463677d6e7916d80199855..d09801d984a6f2250b18f15d819dc781c521f741 100644 (file)
@@ -42,6 +42,9 @@ static struct lock console_lock;
    counter. */
 static int console_lock_depth;
 
+/* Number of characters written to console. */
+static int64_t write_cnt;
+
 /* Initializes the console. */
 void
 console_init (void) 
@@ -49,6 +52,13 @@ console_init (void)
   lock_init (&console_lock, "console");
 }
 
+/* Prints console statistics. */
+void
+console_print_stats (void) 
+{
+  printf ("Console: %lld characters output\n", write_cnt);
+}
+
 /* Acquires the console lock. */
 static void
 acquire_console (void) 
@@ -140,6 +150,7 @@ vprintf_helper (char c, void *char_cnt_)
 static void
 putchar_unlocked (uint8_t c) 
 {
+  write_cnt++;
   serial_putc (c);
   vga_putc (c);
 }
index 6e5b41bd79473f035d57a885ee6234a0b9c3d728..788edf2309d1ce94a0c312454d51c3f811ecd634 100644 (file)
@@ -2,5 +2,6 @@
 #define __LIB_KERNEL_CONSOLE_H
 
 void console_init (void);
+void console_print_stats (void);
 
 #endif /* lib/kernel/console.h */
index 1afa8653dc6c828f8ab79ad3c500ce69eaee5cc0..9774493d9e31f8af5687d421d3f0d987e17f389f 100644 (file)
@@ -55,6 +55,7 @@ static bool do_power_off;
 static void ram_init (void);
 static void paging_init (void);
 static void argv_init (void);
+static void print_stats (void);
 
 int main (void) NO_RETURN;
 
@@ -282,6 +283,8 @@ power_off (void)
   filesys_done ();
 #endif
 
+  print_stats ();
+
   printf ("Powering off...\n");
   serial_flush ();
 
@@ -289,3 +292,19 @@ power_off (void)
     outb (0x8900, *p);
   for (;;);
 }
+
+/* Print statistics about Pintos execution. */
+static void
+print_stats (void) 
+{
+  timer_print_stats ();
+  thread_print_stats ();
+#ifdef FILESYS
+  disk_print_stats ();
+#endif
+  console_print_stats ();
+  kbd_print_stats ();
+#ifdef USERPROG
+  exception_print_stats ();
+#endif
+}
index e85bc164d172094839124f6e818f23c7946957e9..afb2006bc1aa8a51ebffc002f80d29e766470e96 100644 (file)
@@ -41,6 +41,11 @@ struct kernel_thread_frame
     void *aux;                  /* Auxiliary data for function. */
   };
 
+/* Statistics. */
+static long long idle_ticks;    /* # of timer ticks spent idle. */
+static long long kernel_ticks;  /* # of timer ticks in kernel threads. */
+static long long user_ticks;    /* # of timer ticks in user programs. */
+
 static void kernel_thread (thread_func *, void *aux);
 
 static void idle (void *aux UNUSED);
@@ -86,6 +91,30 @@ thread_start (void)
   intr_enable ();
 }
 
+/* Called by the timer interrupt handler at each timer tick to
+   update statistics. */
+void
+thread_tick (void) 
+{
+  struct thread *t = thread_current ();
+  if (t == idle_thread)
+    idle_ticks++;
+#ifdef USERPROG
+  else if (t->pagedir != NULL)
+    user_ticks++;
+#endif
+  else
+    kernel_ticks++;
+}
+
+/* Prints thread statistics. */
+void
+thread_print_stats (void) 
+{
+  printf ("Thread: %lld idle ticks, %lld kernel ticks, %lld user ticks\n",
+          idle_ticks, kernel_ticks, user_ticks);
+}
+
 /* Creates a new kernel thread named NAME with the given initial
    PRIORITY, which executes FUNCTION passing AUX as the argument,
    and adds it to the ready queue.  If thread_start() has been
index 9b55700315ec4b293530a00b5b367d761f5c1768..c0551273d80b5927ad0f41f76f94ca598a9de9b7 100644 (file)
@@ -103,6 +103,8 @@ struct thread
 
 void thread_init (void);
 void thread_start (void);
+void thread_tick (void);
+void thread_print_stats (void);
 
 typedef void thread_func (void *aux);
 tid_t thread_create (const char *name, int priority, thread_func *, void *);
index f31f7a884a323b12b48c6c598d1fa6689fc57fa3..8b2e8b641adf7b90168b7b3ff4b3ae81e2bf4d6c 100644 (file)
@@ -5,6 +5,9 @@
 #include "threads/interrupt.h"
 #include "threads/thread.h"
 
+/* Number of page faults processed. */
+static long long page_fault_cnt;
+
 static void kill (struct intr_frame *);
 static void page_fault (struct intr_frame *);
 
@@ -54,6 +57,13 @@ exception_init (void)
   intr_register (14, 0, INTR_OFF, page_fault, "#PF Page-Fault Exception");
 }
 
+/* Prints exception statistics. */
+void
+exception_print_stats (void) 
+{
+  printf ("Exception: %lld page faults\n", page_fault_cnt);
+}
+
 /* Handler for an exception (probably) caused by a user process. */
 static void
 kill (struct intr_frame *f) 
@@ -129,6 +139,9 @@ page_fault (struct intr_frame *f)
      be assured of reading CR2 before it changed). */
   intr_enable ();
 
+  /* Count page faults. */
+  page_fault_cnt++;
+
   /* Determine cause. */
   not_present = (f->error_code & PF_P) == 0;
   write = (f->error_code & PF_W) != 0;
index e37841018f6a72cb87687225dcd3f7f26280319d..f1a1537b99edbfa05b93d21afb3ba2d5f3623dc8 100644 (file)
@@ -2,5 +2,6 @@
 #define USERPROG_EXCEPTION_H
 
 void exception_init (void);
+void exception_print_stats (void);
 
 #endif /* userprog/exception.h */
index 7c392e61d5fee657b773b879ca4377bce1d62e32..fa8f244d88220a954e43ebc880e1140d242643f4 100644 (file)
@@ -168,23 +168,14 @@ pagedir_test_accessed (uint32_t *pd, const void *upage)
   return pte != NULL && (*pte & PG_A) != 0;
 }
 
-/* Returns true if the PTE for user virtual page UPAGE in PD has
-   been accessed recently, and then resets the accessed bit for
-   that page.
-   Returns false and has no effect if PD contains no PDE for
-   UPAGE. */
-bool
-pagedir_test_accessed_and_clear (uint32_t *pd, const void *upage) 
+/* Resets the accessed bit in the PTE for user virtual page UPAGE
+   in PD. */
+void
+pagedir_clear_accessed (uint32_t *pd, const void *upage) 
 {
   uint32_t *pte = lookup_page (pd, (void *) upage, false);
   if (pte != NULL) 
-    {
-      bool accessed = (*pte & PG_A) != 0;
-      *pte &= ~(uint32_t) PG_A;
-      return accessed;
-    }
-  else
-    return false;
+    *pte &= ~(uint32_t) PG_A;
 }
 
 /* Loads page directory PD into the CPU's page directory base
index bb84856781c0be77df72db7f4d9f6bc8143036f3..f1ddace6b58be198f5b3d5ee82c34119d8d612f8 100644 (file)
@@ -11,7 +11,7 @@ void *pagedir_get_page (uint32_t *pd, const void *upage);
 void pagedir_clear_page (uint32_t *pd, void *upage);
 bool pagedir_test_dirty (uint32_t *pd, const void *upage);
 bool pagedir_test_accessed (uint32_t *pd, const void *upage);
-bool pagedir_test_accessed_and_clear (uint32_t *pd, const void *upage);
+void pagedir_clear_accessed (uint32_t *pd, const void *upage);
 void pagedir_activate (uint32_t *pd);
 
 #endif /* userprog/pagedir.h */
index 7f758c617d8089fd664cafba0d7973ae9ccc5e57..db67593b4d910e223e8ec645b78942895c9232af 100644 (file)
@@ -13,7 +13,7 @@ syscall_init (void)
 }
 
 static void
-syscall_handler (struct intr_frame *f) 
+syscall_handler (struct intr_frame *f UNUSED
 {
   printf ("system call!\n");
   thread_exit ();