From: Ben Pfaff Date: Fri, 10 Sep 2004 00:19:06 +0000 (+0000) Subject: Add timer_sleep() that takes an argument in timer ticks. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=275c68384d654e4c1f9ac4a3eadd2c3d4e46cf86;p=pintos-anon Add timer_sleep() that takes an argument in timer ticks. Remove timer_msleep(), timer_usleep(), timer_nsleep() and add corresponding timer_ms2ticks(), timer_us2ticks(), and timer_ns2ticks() to make the conversions. --- diff --git a/doc/filesys.texi b/doc/filesys.texi index 36d92e3..7652a84 100644 --- a/doc/filesys.texi +++ b/doc/filesys.texi @@ -218,7 +218,7 @@ demonstrate the performance improvement. Note that write-behind makes your filesystem more fragile in the face of crashes. Therefore, you should implement some manner to periodically write all cached blocks to disk. If you have -@code{timer_msleep()} from the first project working, this is an +@code{timer_sleep()} from the first project working, this is an excellent application for it. Likewise, read-ahead is only really useful when done asynchronously. diff --git a/doc/threads.texi b/doc/threads.texi index c1fb41d..c604b96 100644 --- a/doc/threads.texi +++ b/doc/threads.texi @@ -7,9 +7,9 @@ better understanding of synchronization problems. Additionally, you will use at least part of this increased functionality in future assignments. -You will be working in the @file{threads} and @file{devices} -directories for this assignment. Compilation should be done in the -@file{threads} directory. +You will be working in primarily in the @file{threads} directory for +this assignment, with some work in the @file{devices} directory on the +side. Compilation should be done in the @file{threads} directory. @menu * Understanding Threads:: @@ -157,9 +157,9 @@ Problem 4. @section Problem 1-2: Alarm Clock Improve the implementation of the timer device defined in -@file{devices/timer.c} by reimplementing @code{timer_msleep(0}. -Threads call @code{timer_msleep(@var{x})} to suspend execution until -time has advanced by at least @w{@var{x} milliseconds}. This is +@file{devices/timer.c} by reimplementing @code{timer_sleep()}. +Threads call @code{timer_sleep(@var{x})} to suspend execution until +time has advanced by at least @w{@var{x} timer ticks}. This is useful for threads that operate in real-time, for example, for blinking the cursor once per second. There is no requirement that threads start running immediately after waking up; just put them on @@ -173,9 +173,8 @@ advanced far enough. This is undesirable because it wastes time that could potentially be used more profitably by another thread. Your solution should not busy wait. -The argument to @code{timer_msleep()} is expressed in milliseconds. -You must convert it into timer ticks, rounding up. The code provided -does this acceptably; there is no need to change it. +The argument to @code{timer_sleep()} is expressed in timer ticks, not +in milliseconds or some other unit. @node Problem 1-2 Join, Problem 1-3 Priority Scheduling, Problem 1-1 Alarm Clock, Project 1--Threads @section Problem 1-2: Join @@ -357,17 +356,17 @@ attempt to sleep, you won't be able to call those in Having said that, you need to make sure that global data does not get updated by multiple threads simultaneously executing -@code{timer_msleep()}. Here are some pieces of information to think +@code{timer_sleep()}. Here are some pieces of information to think about: @enumerate a @item Interrupts are turned off while @code{timer_interrupt()} runs. This means that @code{timer_interrupt()} will not be interrupted by a -thread running in @code{timer_msleep()}. +thread running in @code{timer_sleep()}. @item -A thread in @code{timer_msleep()}, however, can be interrupted by a +A thread in @code{timer_sleep()}, however, can be interrupted by a call to @code{timer_interrupt()}, except when that thread has turned off interrupts. diff --git a/src/devices/disk.c b/src/devices/disk.c index d8bed65..234d5a9 100644 --- a/src/devices/disk.c +++ b/src/devices/disk.c @@ -255,12 +255,12 @@ reset_channel (struct channel *c) /* Issue soft reset sequence, which selects device 0 as a side effect. Also enable interrupts. */ outb (reg_ctl (c), 0); - timer_usleep (10); + timer_sleep (timer_us2ticks (10)); outb (reg_ctl (c), CTL_SRST); - timer_usleep (10); + timer_sleep (timer_us2ticks (10)); outb (reg_ctl (c), 0); - timer_msleep (150); + timer_sleep (timer_ms2ticks (150)); /* Wait for device 0 to clear BSY. */ if (present[0]) @@ -279,7 +279,7 @@ reset_channel (struct channel *c) { if (inb (reg_nsect (c)) == 1 && inb (reg_lbal (c)) == 1) break; - timer_msleep (10); + timer_sleep (timer_ms2ticks (10)); } wait_while_busy (&c->devices[1]); } @@ -445,7 +445,7 @@ wait_until_idle (const struct disk *d) { if ((inb (reg_status (d->channel)) & (STA_BSY | STA_DRQ)) == 0) return; - timer_usleep (10); + timer_sleep (timer_us2ticks (10)); } printf ("%s: idle timeout\n", d->name); @@ -471,7 +471,7 @@ wait_while_busy (const struct disk *d) printf ("ok\n"); return (inb (reg_alt_status (c)) & STA_DRQ) != 0; } - timer_msleep (10); + timer_sleep (timer_ms2ticks (10)); } printf ("failed\n"); @@ -488,7 +488,7 @@ select_device (const struct disk *d) dev |= DEV_DEV; outb (reg_device (c), dev); inb (reg_alt_status (c)); - timer_nsleep (400); + timer_sleep (timer_ns2ticks (400)); } /* Select disk D in its channel, as select_device(), but wait for diff --git a/src/devices/timer.c b/src/devices/timer.c index 951c2a6..8f4838f 100644 --- a/src/devices/timer.c +++ b/src/devices/timer.c @@ -55,31 +55,39 @@ timer_elapsed (int64_t then) return timer_ticks () - then; } -/* Suspends execution for approximately MS milliseconds. */ +/* Suspends executions for approximately TICKS timer ticks. */ void -timer_msleep (int64_t ms) +timer_sleep (int64_t ticks) { - int64_t ticks = (int64_t) DIV_ROUND_UP (ms * TIMER_FREQ, 1000); int64_t start = timer_ticks (); while (timer_elapsed (start) < ticks) continue; } -/* Suspends execution for approximately US microseconds. - Note: this is ridiculously inaccurate. */ -void -timer_usleep (int64_t us) +/* Returns MS milliseconds in timer ticks, rounding up. */ +int64_t +timer_ms2ticks (int64_t ms) { - timer_msleep (us / 1000 + 1); + /* MS / 1000 s + ------------------------ = MS * TIMER_FREQ / 1000 ticks. + (1 / TIMER_FREQ) ticks/s + */ + return DIV_ROUND_UP (ms * TIMER_FREQ, 1000); } -/* Suspends execution for approximately NS nanoseconds. - Note: this is ridiculously inaccurate. */ -void -timer_nsleep (int64_t ns) +/* Returns US microseconds in timer ticks, rounding up. */ +int64_t +timer_us2ticks (int64_t us) +{ + return DIV_ROUND_UP (us * TIMER_FREQ, 1000000); +} + +/* Returns NS nanoseconds in timer ticks, rounding up. */ +int64_t +timer_ns2ticks (int64_t ns) { - timer_msleep (ns / 1000000 + 1); + return DIV_ROUND_UP (ns * TIMER_FREQ, 1000000000); } /* Timer interrupt handler. */ diff --git a/src/devices/timer.h b/src/devices/timer.h index 5807b0f..db76f6d 100644 --- a/src/devices/timer.h +++ b/src/devices/timer.h @@ -1,6 +1,7 @@ #ifndef DEVICES_TIMER_H #define DEVICES_TIMER_H +#include #include /* Number of timer interrupts per second. */ @@ -10,8 +11,10 @@ void timer_init (void); int64_t timer_ticks (void); int64_t timer_elapsed (int64_t); -void timer_msleep (int64_t ms); -void timer_usleep (int64_t us); -void timer_nsleep (int64_t ns); +void timer_sleep (int64_t ticks); + +int64_t timer_ms2ticks (int64_t ms); +int64_t timer_us2ticks (int64_t us); +int64_t timer_ns2ticks (int64_t ns); #endif /* devices/timer.h */