From: Ben Pfaff Date: Sat, 11 Sep 2004 23:35:48 +0000 (+0000) Subject: Make less sensitive to slow processors. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a9211d5f5546b7b47087850e058ec97e92a85093;p=pintos-anon Make less sensitive to slow processors. --- diff --git a/src/threads/test.c b/src/threads/test.c index 6f7d10e..ccb2427 100644 --- a/src/threads/test.c +++ b/src/threads/test.c @@ -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); } -struct sleep_once_data +/* Based on a test originally submitted for Stanford's CS 140 in + winter 1998 by Rob Baesman , Ben + Taskar , and Toli Kuznets + . */ +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); } -