From: Ben Pfaff <blp@cs.stanford.edu>
Date: Wed, 13 Apr 2005 05:32:09 +0000 (+0000)
Subject: Use runtime options instead of conditional compilation for MLFQS,
X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=59385cfe7f0fc5a66dfc1da7c2e5b817edbcae65;p=pintos-anon

Use runtime options instead of conditional compilation for MLFQS,
RANDOM_REPLACEMENT, extra credit.  Update documentation, grading.
---

diff --git a/doc/standards.texi b/doc/standards.texi
index a1c70a4..162ec44 100644
--- a/doc/standards.texi
+++ b/doc/standards.texi
@@ -56,53 +56,14 @@ read.  We're only going to do a compile in the directory for the current
 project, so you don't need to make sure that the previous projects also
 compile.
 
-@node Conditional Compilation
-@section Conditional Compilation
-
-Given the scope and complexity of your assignments this quarter, you
-may find it convenient while coding and debugging (and we will find it
-convenient while grading) to be able to independently turn different
-parts of the assignments on and off.  To do this, choose a macro name
-and use it in conditional
-compilation directives, e.g.:
-
-@example
-#ifdef @var{NAME}
-@dots{}your code@dots{}
-#endif
-@end example
-
-In general, the code that you turn in must not depend on conditional
-compilation directives.  Project code should be written so that all of
-the subproblems for the project function together, and it should
-compile properly without the need for any new macros to be defined.
-There are a few exceptions:
-
-@itemize @bullet
-@item
-Problem 1-3, the advanced scheduler.  We must be able to turn this on
-and off with a compile-time directive.  You must use the macro name we
-specify for that part.  @xref{Problem 1-3 Advanced Scheduler}, for
-details.
-
-@item
-Problem 3-2, paging to and from disk.  Your page replacement policy must
-default to LRU-like replacement, but we must be able to choose a random
-replacement policy with a compile-time directive.  You must use the
-macro name we specify for that part.  @xref{Problem 3-2 Paging To and
-From Disk}, for details.
-
-@item
-Code written for extra credit may be included conditionally.  If the
-extra credit code changes the normally expected functionality of the
-code, then it @emph{must} be included conditionally, and it must not
-be enabled by default.
-@end itemize
-
-You can use @file{constants.h} in @file{pintos/src} to define macros
-for conditional compilation.  We will replace the @file{constants.h}
-that you supply with one of our own when we test your code, so do not
-define anything important in it.
+Project code should be written so that all of the subproblems for the
+project function together, that is, without the need to rebuild with
+different macros defined, etc.  If you do extra credit work that
+changes normal Pintos behavior so as to interfere with grading, then
+you must implement it so that it only acts that way when given a
+special command-line option of the form @option{-o @var{name}}, where
+@var{name} is a name of your choice.  You can add such an option by
+modifying @func{argv_init} in @file{threads/init.c}.
 
 @node C99
 @section C99
diff --git a/doc/threads.texi b/doc/threads.texi
index 061c6ee..b001548 100644
--- a/doc/threads.texi
+++ b/doc/threads.texi
@@ -499,10 +499,12 @@ relative to the original Pintos scheduling algorithm (round robin) for
 at least one workload of your own design (i.e.@: in addition to the
 provided test).
 
-You must write your code so that we can turn the MLFQS on and off at
-compile time.  By default, it must be off, but we must be able to turn
-it on by inserting the line @code{#define MLFQS 1} in
-@file{constants.h}.  @xref{Conditional Compilation}, for details.
+You must write your code so that we can choose a scheduling algorithm
+policy at Pintos startup time.  By default, the round-robin scheduler
+must be active, but we must be able to choose the MLFQS by invoking
+@command{pintos} with the @option{-o mlfqs} option.  Passing this
+option sets @code{enable_mlfqs}, declared in @file{threads/init.h}, to
+true.
 
 @node Threads FAQ
 @section FAQ
diff --git a/doc/vm.texi b/doc/vm.texi
index 99f4f4f..f922810 100644
--- a/doc/vm.texi
+++ b/doc/vm.texi
@@ -412,11 +412,12 @@ pages less frequently using your algorithm than using some inferior
 page replacement policy.  The canonical example of a poor page
 replacement policy is random replacement.
 
-You must write your code so that we can choose a page replacement policy
-at compile time.  By default, the LRU-like algorithm must be in effect,
-but we must be able to choose random replacement by inserting the line
-@code{#define RANDOM_REPLACEMENT 1} in @file{constants.h}.
-@xref{Conditional Compilation}, for details.
+You must write your code so that we can choose a page replacement
+policy at Pintos startup time.  By default, the LRU-like algorithm
+must be in effect, but we must be able to choose random replacement by
+invoking @command{pintos} with the @option{-o random-paging} option.
+Passing this option sets @code{enable_random_paging}, declared in
+@file{threads/init.h}, to true.
 
 Since you will already be paging from disk, you should implement a
 ``lazy'' loading scheme for new processes.  When a process is created,
diff --git a/grading/lib/Pintos/Grading.pm b/grading/lib/Pintos/Grading.pm
index 240b16e..ad2a825 100644
--- a/grading/lib/Pintos/Grading.pm
+++ b/grading/lib/Pintos/Grading.pm
@@ -96,9 +96,8 @@ EOF
 
 # Source tarballs.
 
-# Extracts the group's source files into pintos/src,
-# applies any patches providing in the grading directory,
-# and installs a default pintos/src/constants.h
+# Extracts the group's source files into pintos/src
+# and applies any patches providing in the grading directory.
 sub extract_sources {
     # Make sure the output dir exists.
     -d ("output") || mkdir ("output") or die "output: mkdir: $!\n";
@@ -137,11 +136,6 @@ sub extract_sources {
 	xsystem ("patch -fs -p0 < $patch",
 		 LOG => $stem, DIE => "applying patch $stem failed\n");
     }
-
-    # Install default pintos/src/constants.h (which is empty).
-    open (CONSTANTS, ">pintos/src/constants.h")
-	or die "constants.h: create: $!\n";
-    close CONSTANTS;
 }
 
 # Returns the name of the tarball to extract.
diff --git a/grading/threads/alarm-multiple.c b/grading/threads/alarm-multiple.c
index 6e7c3d4..f5085c0 100644
--- a/grading/threads/alarm-multiple.c
+++ b/grading/threads/alarm-multiple.c
@@ -11,15 +11,14 @@
 #include "threads/thread.h"
 #include "devices/timer.h"
 
-#ifdef MLFQS
-#error This test not applicable with MLFQS enabled.
-#endif
-
 static void test_sleep (int thread_cnt, int iterations);
 
 void
 test (void) 
 {
+  /* This test does not work with the MLFQS. */
+  ASSERT (!enable_mlfqs);
+
   test_sleep (5, 7);
 }
 
diff --git a/grading/threads/alarm-single.c b/grading/threads/alarm-single.c
index aff2064..ebed46f 100644
--- a/grading/threads/alarm-single.c
+++ b/grading/threads/alarm-single.c
@@ -11,15 +11,14 @@
 #include "threads/thread.h"
 #include "devices/timer.h"
 
-#ifdef MLFQS
-#error This test not applicable with MLFQS enabled.
-#endif
-
 static void test_sleep (int thread_cnt, int iterations);
 
 void
 test (void) 
 {
+  /* This test does not work with the MLFQS. */
+  ASSERT (!enable_mlfqs);
+
   test_sleep (5, 1);
 }
 
diff --git a/grading/threads/priority-donate-multiple.c b/grading/threads/priority-donate-multiple.c
index a00447e..db527de 100644
--- a/grading/threads/priority-donate-multiple.c
+++ b/grading/threads/priority-donate-multiple.c
@@ -6,10 +6,6 @@
    <gmh@leland.stanford.edu>, Yu Ping Hu <yph@cs.stanford.edu>.
    Modified by arens. */
 
-#ifdef MLFQS
-#error This test not applicable with MLFQS enabled.
-#endif
-
 #include "threads/test.h"
 #include <stdio.h>
 #include "threads/synch.h"
@@ -20,6 +16,9 @@ static void test_donate_multiple (void);
 void
 test (void) 
 {
+  /* This test does not work with the MLFQS. */
+  ASSERT (!enable_mlfqs);
+
   /* Make sure our priority is the default. */
   ASSERT (thread_get_priority () == PRI_DEFAULT);
 
diff --git a/grading/threads/priority-donate-nest.c b/grading/threads/priority-donate-nest.c
index 73c7866..8e7316f 100644
--- a/grading/threads/priority-donate-nest.c
+++ b/grading/threads/priority-donate-nest.c
@@ -6,10 +6,6 @@
    <gmh@leland.stanford.edu>, Yu Ping Hu <yph@cs.stanford.edu>.
    Modified by arens. */
 
-#ifdef MLFQS
-#error This test not applicable with MLFQS enabled.
-#endif
-
 #include "threads/test.h"
 #include <stdio.h>
 #include "threads/synch.h"
@@ -20,6 +16,9 @@ static void test_donate_nest (void);
 void
 test (void) 
 {
+  /* This test does not work with the MLFQS. */
+  ASSERT (!enable_mlfqs);
+
   /* Make sure our priority is the default. */
   ASSERT (thread_get_priority () == PRI_DEFAULT);
 
diff --git a/grading/threads/priority-donate-one.c b/grading/threads/priority-donate-one.c
index 35f135c..afc1e83 100644
--- a/grading/threads/priority-donate-one.c
+++ b/grading/threads/priority-donate-one.c
@@ -6,10 +6,6 @@
    <gmh@leland.stanford.edu>, Yu Ping Hu <yph@cs.stanford.edu>.
    Modified by arens. */
 
-#ifdef MLFQS
-#error This test not applicable with MLFQS enabled.
-#endif
-
 #include "threads/test.h"
 #include <stdio.h>
 #include "threads/synch.h"
@@ -20,6 +16,9 @@ static void test_donate_return (void);
 void
 test (void) 
 {
+  /* This test does not work with the MLFQS. */
+  ASSERT (!enable_mlfqs);
+
   /* Make sure our priority is the default. */
   ASSERT (thread_get_priority () == PRI_DEFAULT);
 
diff --git a/grading/threads/priority-fifo.c b/grading/threads/priority-fifo.c
index 6f8fa9b..01cc7a7 100644
--- a/grading/threads/priority-fifo.c
+++ b/grading/threads/priority-fifo.c
@@ -6,10 +6,6 @@
    <gmh@leland.stanford.edu>, Yu Ping Hu <yph@cs.stanford.edu>.
    Modified by arens. */
 
-#ifdef MLFQS
-#error This test not applicable with MLFQS enabled.
-#endif
-
 #include "threads/test.h"
 #include <stdio.h>
 #include "devices/timer.h"
@@ -22,6 +18,9 @@ static void test_fifo (void);
 void
 test (void) 
 {
+  /* This test does not work with the MLFQS. */
+  ASSERT (!enable_mlfqs);
+
   /* Make sure our priority is the default. */
   ASSERT (thread_get_priority () == PRI_DEFAULT);
 
diff --git a/grading/threads/priority-preempt.c b/grading/threads/priority-preempt.c
index 1e2a268..8953748 100644
--- a/grading/threads/priority-preempt.c
+++ b/grading/threads/priority-preempt.c
@@ -6,10 +6,6 @@
    <gmh@leland.stanford.edu>, Yu Ping Hu <yph@cs.stanford.edu>.
    Modified by arens. */
 
-#ifdef MLFQS
-#error This test not applicable with MLFQS enabled.
-#endif
-
 #include "threads/test.h"
 #include <stdio.h>
 #include "threads/synch.h"
@@ -20,6 +16,9 @@ static void test_preempt (void);
 void
 test (void) 
 {
+  /* This test does not work with the MLFQS. */
+  ASSERT (!enable_mlfqs);
+
   /* Make sure our priority is the default. */
   ASSERT (thread_get_priority () == PRI_DEFAULT);
 
diff --git a/grading/threads/run-tests b/grading/threads/run-tests
index 5346211..bd705e4 100755
--- a/grading/threads/run-tests
+++ b/grading/threads/run-tests
@@ -51,14 +51,6 @@ die "Don't know how to '$action'";
 # Runs $test in directory output/$test.
 # Returns 'ok' if it went ok, otherwise an explanation.
 sub run_test {
-    # Change constants.h if necessary.
-    my ($defines) = $test ne 'mlfqs-on' ? "" : "#define MLFQS 1\n";
-    if ($defines ne snarf ("pintos/src/constants.h")) {
-	open (CONSTANTS, ">pintos/src/constants.h");
-	print CONSTANTS $defines;
-	close (CONSTANTS);
-    }
-
     # Changes devices/timer.c if necessary.
     my ($new_time_slice) = $test eq 'priority-fifo' ? 100 : 1;
     my (@timer_c) = snarf ("pintos/src/devices/timer.c");
@@ -103,7 +95,9 @@ sub run_test {
 
     # Run.
     my ($timeout) = $test !~ /^mlfqs/ ? 15 : 600;
-    return run_pintos (["-v", "run", "-q"],
+    my (@command) = ("-v", "run", "-q");
+    push (@command, "-o mlfqs") if $test eq 'mlfqs-on';
+    return run_pintos (\@command,
 		       CHDIR => "pintos/src/threads/build",
 		       LOG => "$test/run",
 		       TIMEOUT => $timeout);
diff --git a/src/Makefile.build b/src/Makefile.build
index df38777..e124011 100644
--- a/src/Makefile.build
+++ b/src/Makefile.build
@@ -7,8 +7,7 @@ VPATH = ../..
 
 # Compiler and assembler options.
 DEFINES += -DKERNEL
-CPPFLAGS = -nostdinc -I../.. -I- -I../../lib -I../../lib/kernel	\
-	   -include constants.h
+CPPFLAGS = -nostdinc -I../.. -I- -I../../lib -I../../lib/kernel
 
 # Core kernel.
 threads_SRC  = threads/init.c		# Main program.
diff --git a/src/constants.h b/src/constants.h
deleted file mode 100644
index 8ffe2f6..0000000
--- a/src/constants.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* Use this header file to define macros for configuring
-   compilation.  This file will be replaced by the TAs when your
-   code is tested, using the macros described in the course
-   documentation.  Your code should not require other macros to
-   be defined here to function properly. */
-
-/* Example definition. */
-/*#define MACRONAME 1 */
diff --git a/src/tests/threads/p1-1.c b/src/tests/threads/p1-1.c
index 627bba5..694ea0b 100644
--- a/src/tests/threads/p1-1.c
+++ b/src/tests/threads/p1-1.c
@@ -11,15 +11,14 @@
 #include "threads/thread.h"
 #include "devices/timer.h"
 
-#ifdef MLFQS
-#error This test not applicable with MLFQS enabled.
-#endif
-
 static void test_sleep (int thread_cnt, int iterations);
 
 void
 test (void) 
 {
+  /* This test does not work with the MLFQS. */
+  ASSERT (!enable_mlfqs);
+
   /* Easy test: 5 threads sleep once each. */
   test_sleep (5, 1);
 
diff --git a/src/tests/threads/p1-2.c b/src/tests/threads/p1-2.c
index 50a4fcf..e96f03c 100644
--- a/src/tests/threads/p1-2.c
+++ b/src/tests/threads/p1-2.c
@@ -6,10 +6,6 @@
    <gmh@leland.stanford.edu>, Yu Ping Hu <yph@cs.stanford.edu>.
    Modified by arens. */
 
-#ifdef MLFQS
-#error This test not applicable with MLFQS enabled.
-#endif
-
 #include "threads/test.h"
 #include <stdio.h>
 #include "threads/synch.h"
@@ -22,6 +18,9 @@ static void test_donate_return (void);
 void
 test (void) 
 {
+  /* This test does not work with the MLFQS. */
+  ASSERT (!enable_mlfqs);
+
   /* Make sure our priority is the default. */
   ASSERT (thread_get_priority () == PRI_DEFAULT);
 
diff --git a/src/threads/init.c b/src/threads/init.c
index 8b2b7f7..51d6bdd 100644
--- a/src/threads/init.c
+++ b/src/threads/init.c
@@ -39,16 +39,28 @@ size_t ram_pages;
 /* Page directory with kernel mappings only. */
 uint32_t *base_page_dir;
 
-#ifdef FILESYS
-/* -f: Format the filesystem? */
-static bool format_filesys;
-#endif
+/* -o mlfqs:
+   If false (default), use round-robin scheduler.
+   If true, use multi-level feedback queue scheduler. */
+bool enable_mlfqs;
 
 #ifdef USERPROG
 /* -ex: Initial program to run. */
 static char *initial_program;
 #endif
 
+#ifdef VM
+/* -o random-paging:
+   If false (default), use LRU page replacement policy.
+   If true, use random page replacement policy. */
+bool enable_random_paging;
+#endif
+
+#ifdef FILESYS
+/* -f: Format the filesystem? */
+static bool format_filesys;
+#endif
+
 /* -q: Power off after kernel tasks complete? */
 bool power_off_when_done;
 
@@ -220,7 +232,19 @@ argv_init (void)
 
   /* Parse the words. */
   for (i = 0; i < argc; i++)
-    if (!strcmp (argv[i], "-rs")) 
+    if (!strcmp (argv[i], "-o"))
+      {
+        i++;
+        if (!strcmp (argv[i], "mlfqs"))
+          enable_mlfqs = true;
+#ifdef VM
+        else if (!strcmp (argv[i], "random-paging"))
+          enable_random_paging = true;
+#endif
+        else
+          PANIC ("unknown option `-o %s' (use -u for help)", argv[i]);
+      }
+    else if (!strcmp (argv[i], "-rs")) 
       random_init (atoi (argv[++i]));
     else if (!strcmp (argv[i], "-q"))
       power_off_when_done = true;
@@ -251,11 +275,14 @@ argv_init (void)
       {
         printf (
           "Kernel options:\n"
-          " -rs SEED            Set random seed to SEED.\n"
+          " -o mlfqs            Use multi-level feedback queue scheduler.\n"
 #ifdef USERPROG
           " -ex 'PROG [ARG...]' Run PROG, passing the optional arguments.\n"
           " -ul USER_MAX        Limit user memory to USER_MAX pages.\n"
 #endif
+#ifdef VM
+          " -o random-paging    Use random page replacement policy.\n"
+#endif
 #ifdef FILESYS
           " -f                  Format the filesystem disk (hdb or hd0:1).\n"
           " -ci FILE SIZE       Copy SIZE bytes from the scratch disk (hdc\n"
@@ -266,6 +293,7 @@ argv_init (void)
           " -r FILE             Delete FILE.\n"
           " -ls                 List files in the root directory.\n"
 #endif
+          " -rs SEED            Set random seed to SEED.\n"
           " -q                  Power off after doing requested actions.\n"
           " -u                  Print this help message and power off.\n"
           );
diff --git a/src/threads/init.h b/src/threads/init.h
index a6fec05..45e9545 100644
--- a/src/threads/init.h
+++ b/src/threads/init.h
@@ -12,6 +12,18 @@ extern size_t ram_pages;
 /* Page directory with kernel mappings only. */
 extern uint32_t *base_page_dir;
 
+/* -o mlfqs:
+   If false (default), use round-robin scheduler.
+   If true, use multi-level feedback queue scheduler. */
+extern bool enable_mlfqs;
+
+#ifdef VM
+/* -o random-paging:
+   If false (default), use LRU page replacement policy.
+   If true, use random page replacement policy. */
+extern bool enable_random_paging;
+#endif
+
 /* -q: Power off when kernel tasks complete? */
 extern bool power_off_when_done;
 
diff --git a/src/threads/test.c b/src/threads/test.c
index 627bba5..694ea0b 100644
--- a/src/threads/test.c
+++ b/src/threads/test.c
@@ -11,15 +11,14 @@
 #include "threads/thread.h"
 #include "devices/timer.h"
 
-#ifdef MLFQS
-#error This test not applicable with MLFQS enabled.
-#endif
-
 static void test_sleep (int thread_cnt, int iterations);
 
 void
 test (void) 
 {
+  /* This test does not work with the MLFQS. */
+  ASSERT (!enable_mlfqs);
+
   /* Easy test: 5 threads sleep once each. */
   test_sleep (5, 1);
 
diff --git a/src/threads/test.h b/src/threads/test.h
index dde08fa..d6b3ca8 100644
--- a/src/threads/test.h
+++ b/src/threads/test.h
@@ -1,6 +1,8 @@
 #ifndef THREADS_TEST_H
 #define THREADS_TEST_H
 
+#include "threads/init.h"
+
 void test (void);
 
 #endif /* threads/test.h */