Make less sensitive to slow processors.
authorBen Pfaff <blp@cs.stanford.edu>
Sat, 11 Sep 2004 23:35:48 +0000 (23:35 +0000)
committerBen Pfaff <blp@cs.stanford.edu>
Sat, 11 Sep 2004 23:35:48 +0000 (23:35 +0000)
src/threads/test.c

index 6f7d10ec6b4c77b51ed33899d71e9784454c1268..ccb2427b28616c66efd9de4c26963b45885571fe 100644 (file)
@@ -4,55 +4,75 @@
 #include "threads/thread.h"
 #include "devices/timer.h"
 
-static void test_sleep_once (void);
+static void test_sleep (int iterations);
 
 void
 test (void) 
 {
-  test_sleep_once ();
-//  test_sleep_multiple ();
+  test_sleep (1);
+  test_sleep (7);
 }
 \f
-struct sleep_once_data 
+/* Based on a test originally submitted for Stanford's CS 140 in
+   winter 1998 by Rob Baesman <rbaesman@cs.stanford.edu>, Ben
+   Taskar <btaskar@cs.stanford.edu>, and Toli Kuznets
+   <tolik@cs.stanford.edu>. */
+struct sleep_thread_data 
   {
+    int64_t start;              /* Start time. */
     int duration;               /* Number of ticks to sleep. */
-    volatile int *counter;      /* Counter to check. */
+    int iterations;             /* Number of iterations to run. */
+    int *product;               /* Largest product so far. */
+    struct lock *lock;          /* Lock on access to `product'. */
     struct semaphore done;      /* Completion semaphore. */
     struct thread *thread;      /* Thread. */
   };
 
-static void sleep_once (void *);
+static void sleeper (void *);
 
 static void
-test_sleep_once (void
+test_sleep (int iterations
 {
-  struct sleep_once_data t[5];
-  const int t_cnt = sizeof t / sizeof *t;
-  volatile int counter;
+  struct sleep_thread_data threads[5];
+  const int thread_cnt = sizeof threads / sizeof *threads;
+  struct lock lock;
+  int64_t start;
+  int product;
   int i;
 
-  printf ("\nTesting one sleep per thread...\n");
+  printf ("\n"
+          "Testing %d sleeps per thread.\n"
+          "If successful, product of iteration count and\n"
+          "sleep duration will appear in nondescending order.\n",
+          iterations);
 
   /* Start all the threads. */
-  counter = 0;
-  for (i = 0; i < t_cnt; i++)
+  product = 0;
+  lock_init (&lock, "product");
+  start = timer_ticks ();
+  for (i = 0; i < thread_cnt; i++)
     {
+      struct sleep_thread_data *t;
       char name[16];
-      snprintf (name, sizeof name, "once %d", i);
-
-      t[i].duration = i * 10;
-      t[i].counter = &counter;
-      sema_init (&t[i].done, 0, name);
-      t[i].thread = thread_create (name, sleep_once, &t[i]);
+      
+      snprintf (name, sizeof name, "thread %d", i);
+      t = threads + i;
+      t->start = start;
+      t->duration = (i + 1) * 10;
+      t->iterations = iterations;
+      t->product = &product;
+      t->lock = &lock;
+      sema_init (&t->done, 0, name);
+      t->thread = thread_create (name, sleeper, t);
     }
   
   /* Wait for all the threads to finish. */
-  for (i = 0; i < t_cnt; i++) 
+  for (i = 0; i < thread_cnt; i++) 
     {
 #ifdef THREAD_JOIN_IMPLEMENTED
-      thread_join (t[i].thread);
+      thread_join (threads[i].thread);
 #else
-      sema_down (&t[i].done);
+      sema_down (&threads[i].done);
 #endif
     }
 
@@ -60,26 +80,33 @@ test_sleep_once (void)
 }
 
 static void
-sleep_once (void *t_) 
+sleeper (void *t_) 
 {
-  struct sleep_once_data *t = t_;
-
-  /* Sleep. */
-  timer_sleep (t->duration);
+  struct sleep_thread_data *t = t_;
+  int i;
 
-  /* Check ordering. */
-  if (*t->counter > t->duration)
-    printf ("%s: Out of order sleep completion (%d > %d)!\n",
-            thread_name (thread_current ()),
-            *t->counter, t->duration);
-  else 
+  for (i = 1; i <= t->iterations; i++) 
     {
-      *t->counter = t->duration;
-      printf ("%s: Sleep %d complete\n",
-              thread_name (thread_current ()), t->duration);
-    }
+      int old_product;
+      int new_product = i * t->duration;
+
+      timer_sleep ((t->start + new_product) - timer_ticks ());
 
+      lock_acquire (t->lock);
+      old_product = *t->product;
+      *t->product = new_product;
+      lock_release (t->lock);
+
+      printf ("%s: duration=%d, iteration=%d, product=%d\n",
+              thread_name (thread_current ()),
+              t->duration, i, new_product);
+
+      if (old_product > new_product)
+        printf ("%s: Out of order sleep completion (%d > %d)!\n",
+                thread_name (thread_current ()),
+                old_product, new_product);
+    }
+  
   /* Signal completion. */
   sema_up (&t->done);
 }
-