home *** CD-ROM | disk | FTP | other *** search
/ ftp.ee.pdx.edu / 2014.02.ftp.ee.pdx.edu.tar / ftp.ee.pdx.edu / pub / users / Harry / Blitz / version-1-0 / OSProject / p8 / TestProgram3.c < prev    next >
Text File  |  2006-05-17  |  17KB  |  587 lines

  1. code TestProgram3
  2.  
  3.  
  4.            ------------------------------------------
  5.            ------                              ------
  6.            ------  Harry's Test Program #3     ------
  7.            ------                              ------
  8.            ------------------------------------------
  9.  
  10.  
  11. -----------------------------  main  ---------------------------------
  12.  
  13.   function main ()
  14.     --
  15.     -- For each of the following tests, you should uncomment the call,
  16.     -- compile and run this program, and hand in the output it produces.
  17.     --
  18.     -- This program should be run with the following constants in the kernel:
  19.     --     NUMBER_OF_PHYSICAL_PAGE_FRAMES = 512
  20.     --     MAX_NUMBER_OF_PROCESSES = 10
  21.     --     MAX_PAGES_PER_VIRT_SPACE = 20
  22.     --     MAX_FILES_PER_PROCESS = 10
  23.     --     USER_STACK_SIZE_IN_PAGES = 1
  24.     --     NUMBER_OF_ENVIRONMENT_PAGES = 0
  25.  
  26.  
  27.       -- SysExitTest ()
  28.       -- BasicForkTest ()
  29.       -- YieldTest ()
  30.       -- ForkTest ()
  31.       -- JoinTest1 ()
  32.       -- JoinTest2 ()
  33.       -- JoinTest3 ()
  34.       -- ManyProcessesTest1 ()
  35.       -- ManyProcessesTest2 ()
  36.       -- ManyProcessesTest3 ()
  37.       -- ErrorTest ()
  38.  
  39.       Sys_Exit (0)
  40.     endFunction
  41.  
  42. -----------------------------  SysExitTest  ---------------------------------
  43.  
  44.   function SysExitTest ()
  45.     --
  46.     -- This function executes the Sys_Exit syscall.
  47.     --
  48.       print ("\nSysExitTest running.\n\n")
  49.       print ("About to terminate the only process; should cause the OS to stop on a 'wait' instruction.\n")
  50.       Sys_Exit (0)
  51.       print ("*****  Error: Should not return from Sys_Exit  *****")
  52.     endFunction
  53.  
  54. -----------------------------  BasicForkTest  ---------------------------------
  55.  
  56.   function BasicForkTest ()
  57.     --
  58.     -- This function creates two processes.  Each one prints a message and
  59.     -- calls Sys_Exit.
  60.     --
  61.       var pid: int
  62.       print ("\nBasicForkTest running.\n\n")
  63.       pid = Sys_Fork ()
  64.       if pid == 0
  65.         print ("I am the child\n")
  66.         Sys_Exit (0)
  67.       else
  68.         print ("I am the parent\n")
  69.         Sys_Exit (0)
  70.       endIf
  71.     endFunction
  72.  
  73. -----------------------------  YieldTest  ---------------------------------
  74.  
  75.   function YieldTest ()
  76.     --
  77.     -- This function creates two processes and each one prints several
  78.     -- messages.  It does this twice.  In the first run, the processes
  79.     -- contain no yields.  In the second run, the processes contain
  80.     -- calls to yield.  If yield acutally does anything, the two runs should
  81.     -- be different.
  82.     --
  83.       var pid, i, j: int
  84.       print ("\nYieldTest running.\n\n")
  85.       print ("This test involves calls to Fork, Yield, and Exit.\n\n")
  86.       print ("RUN ONE: You should see 10 'compiler' messages and 10 'OS' messages.\n\n")
  87.       pid = Sys_Fork ()
  88.       if pid == 0
  89.         -- Child Code
  90.         for i = 1 to 10
  91.           print ("Designing compilers is fun!\n")
  92.         endFor
  93.       else
  94.         -- Parent Code
  95.         for i = 1 to 10
  96.           print ("Writing OS kernel code is a blast!\n")
  97.         endFor
  98.         Sys_Exit (0)
  99.       endIf
  100.       Sys_Yield ()
  101.       Sys_Yield ()
  102.       Sys_Yield ()
  103.       Sys_Yield ()
  104.       Sys_Yield ()
  105.       print ("\nRUN TWO: You should see the same 20 messages, but the order should be different, due to the presence of 'Yield's.\n\n")
  106.       pid = Sys_Fork ()
  107.       if pid == 0
  108.         -- Child Code
  109.         for i = 1 to 10
  110.           for j = 1 to i
  111.             Sys_Yield ()
  112.           endFor
  113.           print ("Designing compilers is fun!\n")
  114.           Sys_Yield ()
  115.         endFor
  116.       else
  117.         -- Parent Code
  118.         for i = 1 to 10
  119.           for j = i to 10
  120.             Sys_Yield ()
  121.           endFor
  122.           print ("Writing OS kernel code is a blast!\n")
  123.         endFor
  124.         Sys_Exit (0)
  125.       endIf
  126.  
  127.     endFunction
  128.  
  129. -----------------------------  ForkTest  ---------------------------------
  130.  
  131.   function ForkTest ()
  132.     --
  133.     -- This function creates a whole bunch of processes.
  134.     --
  135.       print ("\nForkTest running.\n\n")
  136.       print ("This test involves calls to Fork, Yield, and Exit.\n")
  137.       print ("There should be 26 columns (A-Z) printed.  Each letter should be printed 5 times.\n")
  138.       ExecuteAFork ("A\n")
  139.       ExecuteAFork (" B\n")
  140.       ExecuteAFork ("  C\n")
  141.       ExecuteAFork ("   D\n")
  142.       ExecuteAFork ("    E\n")
  143.       ExecuteAFork ("     F\n")
  144.       ExecuteAFork ("      G\n")
  145.       ExecuteAFork ("       H\n")
  146.       ExecuteAFork ("        I\n")
  147.       ExecuteAFork ("         J\n")
  148.       ExecuteAFork ("          K\n")
  149.       ExecuteAFork ("           L\n")
  150.       ExecuteAFork ("            M\n")
  151.       ExecuteAFork ("             N\n")
  152.       ExecuteAFork ("              O\n")
  153.       ExecuteAFork ("               P\n")
  154.       ExecuteAFork ("                Q\n")
  155.       ExecuteAFork ("                 R\n")
  156.       ExecuteAFork ("                  S\n")
  157.       ExecuteAFork ("                   T\n")
  158.       ExecuteAFork ("                    U\n")
  159.       ExecuteAFork ("                     V\n")
  160.       ExecuteAFork ("                      W\n")
  161.       ExecuteAFork ("                       X\n")
  162.       ExecuteAFork ("                        Y\n")
  163.       ExecuteAFork ("                         Z\n")
  164.       Sys_Exit (0)
  165.     endFunction
  166.  
  167. -----------------------------  ExecuteAFork  ---------------------------------
  168.  
  169.   function ExecuteAFork (str: String)
  170.     --
  171.     -- Create a process to print out the string 5 times.  Also create a child
  172.     -- process to continue and return and terminate the parent.  This done
  173.     -- because otherwise we would create 1 parent processes, with 26 children.
  174.     -- Each child terminates but will turn into a zombie until its parent either
  175.     -- does a join or itself terminates.  With a small MAX number of processes,
  176.     -- we could run out of PCBs if we don't kill the parent and fully reclaim
  177.     -- its resources.
  178.     --
  179.       var pid: int
  180.           i, j: int
  181.       pid = Sys_Fork ()
  182.       if pid == 0
  183.         -- Child Code
  184.         for i = 1 to 5
  185.           print (str)
  186.           for j = 1 to i*50   -- Increase this constant for greater parallelism
  187.             Sys_Yield ()
  188.           endFor
  189.         endFor
  190.         Sys_Exit (0)
  191.       else
  192.         -- Parent Code
  193.         -- Create another child to continue our work and terminate this process
  194.         pid = Sys_Fork ()
  195.         if pid != 0
  196.           Sys_Exit (0)
  197.         endIf
  198.       endIf
  199.     endFunction
  200.  
  201. -----------------------------  JoinTest1  ---------------------------------
  202.  
  203.   function JoinTest1 ()
  204.     --
  205.     -- This function creates two processes.  The child immediately calls
  206.     -- Exit to return a value to the parent.  The parent waits a long time,
  207.     -- (until after the child has done its exit) and then calls Join.  It makes
  208.     -- sure the value passed from the child is returned to the parent.  Then
  209.     -- this test does the same thing again, except this time the parent calls
  210.     -- join immediately while the child waits a long time before calling Exit.
  211.     --
  212.       var pid, i: int
  213.       print ("\nJoinTest 1 running.\n\n")
  214.       print ("This test involves calls to Fork, Yield, and Exit.\n")
  215.       print ("Running first test...\n")
  216.       pid = Sys_Fork ()
  217.       if pid == 0
  218.         -- Child Code
  219.         print ("This line should print first.\n")
  220.         Sys_Exit (0x12345678)
  221.       else
  222.         -- Parent Code
  223.         -- Wait for child to finish first
  224.         for i = 1 to 100
  225.           Sys_Yield ()
  226.         endFor
  227.         print ("This line should print second.\n")
  228.         i = Sys_Join (pid)
  229.         if i != 0x12345678
  230.           print ("*****  ERROR: Exit passes 0x12345678, but join returns ")
  231.           printHex (i)
  232.           print ("  *****\n")
  233.         else
  234.           print ("Done.\n")
  235.         endIf
  236.       endIf
  237.       print ("Running second test...\n")
  238.       pid = Sys_Fork ()
  239.       if pid == 0
  240.         -- Child Code
  241.         -- Wait for parent to call join first
  242.         for i = 1 to 100
  243.           Sys_Yield ()
  244.         endFor
  245.         print ("This line should print second.\n")
  246.         Sys_Exit (0x87654321)
  247.       else
  248.         -- Parent Code
  249.         print ("This line should print first.\n")
  250.         i = Sys_Join (pid)
  251.         if i != 0x87654321
  252.           print ("*****  ERROR: Exit passes 0x87654321, but join returns ")
  253.           printHex (i)
  254.           print ("  *****\n")
  255.         else
  256.           print ("Done.\n")
  257.         endIf
  258.       endIf
  259.     endFunction
  260.  
  261. -----------------------------  JoinTest2  ---------------------------------
  262.  
  263.   function JoinTest2 ()
  264.     --
  265.     -- This function creates 5 children.  It then waits for each child to
  266.     -- finish. It makes sure that the expected value is passed back from
  267.     -- each child.
  268.     --
  269.       var pid1, pid2, pid3, pid4, pid5: int
  270.       print ("\nJoinTest 2 running.\n\n")
  271.       print ("This test involves calls to Fork, Yield, and Exit.\n")
  272.       print ("Creating 5 children...\n")
  273.  
  274.       pid1 = Sys_Fork ()
  275.       if pid1 == 0
  276.         -- Code for child 1
  277.         print ("Child 1 running...\n")
  278.         Sys_Yield ()
  279.         Sys_Exit (100)
  280.       endIf
  281.  
  282.       pid2 = Sys_Fork ()
  283.       if pid2 == 0
  284.         -- Code for child 2
  285.         print ("Child 2 running...\n")
  286.         Sys_Yield ()
  287.         Sys_Exit (200)
  288.       endIf
  289.  
  290.       pid3 = Sys_Fork ()
  291.       if pid3 == 0
  292.         -- Code for child 3
  293.         print ("Child 3 running...\n")
  294.         Sys_Yield ()
  295.         Sys_Exit (300)
  296.       endIf
  297.  
  298.       pid4 = Sys_Fork ()
  299.       if pid4 == 0
  300.         -- Code for child 4
  301.         print ("Child 4 running...\n")
  302.         Sys_Yield ()
  303.         Sys_Exit (400)
  304.       endIf
  305.  
  306.       pid5 = Sys_Fork ()
  307.       if pid5 == 0
  308.         -- Code for child 5
  309.         print ("Child 5 running...\n")
  310.         Sys_Exit (500)
  311.       endIf
  312.  
  313.       print ("Waiting for children in order 1, 2, 3, 4, 5...\n")
  314.  
  315.       if 100 != Sys_Join (pid1)
  316.         print ("*****  ERROR: 100 != Sys_Join (pid1)  *****\n")
  317.       endIf
  318.  
  319.       if 200 != Sys_Join (pid2)
  320.         print ("*****  ERROR: 200 != Sys_Join (pid2)  *****\n")
  321.       endIf
  322.  
  323.       if 300 != Sys_Join (pid3)
  324.         print ("*****  ERROR: 300 != Sys_Join (pid3)  *****\n")
  325.       endIf
  326.  
  327.       if 400 != Sys_Join (pid4)
  328.         print ("*****  ERROR: 400 != Sys_Join (pid4)  *****\n")
  329.       endIf
  330.  
  331.       if 500 != Sys_Join (pid5)
  332.         print ("*****  ERROR: 500 != Sys_Join (pid5)  *****\n")
  333.       endIf
  334.  
  335.       print ("Creating 5 more children...\n")
  336.  
  337.       pid1 = Sys_Fork ()
  338.       if pid1 == 0
  339.         -- Code for child 1
  340.         print ("Child 1 running...\n")
  341.         Sys_Yield ()
  342.         Sys_Exit (100)
  343.       endIf
  344.  
  345.       pid2 = Sys_Fork ()
  346.       if pid2 == 0
  347.         -- Code for child 2
  348.         print ("Child 2 running...\n")
  349.         Sys_Yield ()
  350.         Sys_Exit (200)
  351.       endIf
  352.  
  353.       pid3 = Sys_Fork ()
  354.       if pid3 == 0
  355.         -- Code for child 3
  356.         print ("Child 3 running...\n")
  357.         Sys_Yield ()
  358.         Sys_Exit (300)
  359.       endIf
  360.  
  361.       pid4 = Sys_Fork ()
  362.       if pid4 == 0
  363.         -- Code for child 4
  364.         print ("Child 4 running...\n")
  365.         Sys_Yield ()
  366.         Sys_Exit (400)
  367.       endIf
  368.  
  369.       pid5 = Sys_Fork ()
  370.       if pid5 == 0
  371.         -- Code for child 5
  372.         print ("Child 5 running...\n")
  373.         Sys_Exit (500)
  374.       endIf
  375.  
  376.       print ("Waiting for children in order 5, 4, 1, 3, 2...\n")
  377.  
  378.       if 500 != Sys_Join (pid5)
  379.         print ("*****  ERROR: 500 != Sys_Join (pid5)  *****\n")
  380.       endIf
  381.  
  382.       if 400 != Sys_Join (pid4)
  383.         print ("*****  ERROR: 400 != Sys_Join (pid4)  *****\n")
  384.       endIf
  385.  
  386.       if 100 != Sys_Join (pid1)
  387.         print ("*****  ERROR: 100 != Sys_Join (pid1)  *****\n")
  388.       endIf
  389.  
  390.       if 300 != Sys_Join (pid3)
  391.         print ("*****  ERROR: 300 != Sys_Join (pid3)  *****\n")
  392.       endIf
  393.  
  394.       if 200 != Sys_Join (pid2)
  395.         print ("*****  ERROR: 200 != Sys_Join (pid2)  *****\n")
  396.       endIf
  397.  
  398.       print ("Done.\n")
  399.  
  400.     endFunction
  401.  
  402. -----------------------------  JoinTest3  ---------------------------------
  403.  
  404.   function JoinTest3 ()
  405.     --
  406.     -- This function waits for a non-existent child, which is an error
  407.     --
  408.       print ("\nJoinTest3 running.\n\n")
  409.       print ("This test involves 5 illegal calls to Sys_Join, waiting on non-existent children.\n")
  410.       print ("In each case, it prints the return code, which should be -1.\n")
  411.  
  412.       printIntVar ("Return code from 1st call", Sys_Join (-1))
  413.       printIntVar ("Return code from 2nd call", Sys_Join (0))
  414.       printIntVar ("Return code from 3rd call", Sys_Join (1))
  415.       printIntVar ("Return code from 4th call", Sys_Join (2))
  416.       printIntVar ("Return code from 5th call", Sys_Join (40123))
  417.  
  418.       print ("Done.\n")
  419.  
  420.     endFunction
  421.  
  422. -----------------------------  ManyProcessesTest1  ---------------------------------
  423.  
  424.   function ManyProcessesTest1 ()
  425.     --
  426.     -- This function creates lots of processes.  Each should terminate, so
  427.     -- the test should not cause problems unless resources are not freed.
  428.     --
  429.       var i, pid: int
  430.       print ("\nManyProcessesTest1 running.\n\n")
  431.       print ("This test should create 100 child processes.\n")
  432.       print ("It should print 100 lines of output.\n")
  433.  
  434.       for i = 1 to 100
  435.         pid = Sys_Fork ()
  436.         if pid != 0
  437.           -- Parent code
  438.           Sys_Exit (0)
  439.         endIf
  440.         print ("Child ")
  441.         printInt (i)
  442.         nl ()
  443.       endFor
  444.  
  445.       print ("Done.\n")
  446.  
  447.     endFunction
  448.  
  449. -----------------------------  ManyProcessesTest2  ---------------------------------
  450.  
  451.   function ManyProcessesTest2 ()
  452.       print ("\nManyProcessesTest2 running.\n\n")
  453.       CreateManyProcesses (9)
  454.     endFunction
  455.  
  456. -----------------------------  ManyProcessesTest3  ---------------------------------
  457.  
  458.   function ManyProcessesTest3 ()
  459.       print ("\nManyProcessesTest3 running.\n\n")
  460.       CreateManyProcesses (10)
  461.     endFunction
  462.  
  463. -----------------------------  CreateManyProcesses  ---------------------------------
  464.  
  465.   function CreateManyProcesses (numProcs: int)
  466.     --
  467.     -- This function creates numProcs additional processes.  If numProcs is
  468.     -- 9 or less, this should be possible.  If numProcs is greater then the
  469.     -- OS should run out of PCBs and hang.
  470.     --
  471.       var i, pid: int
  472.       print ("This test attempts to create ")
  473.       printInt (numProcs)
  474.       print (" new processes.\n")
  475.  
  476.       if numProcs <= 9
  477.         print ("It should print a line for each process and then it should print 123.\n")
  478.       else
  479.         print ("It should run out of resources and hang.\n")
  480.       endIf
  481.  
  482.       print ("Process 0\n")  -- Print a line for the initial process
  483.       pid = Sys_Fork ()
  484.       if pid == 0
  485.         -- Code for 1st child
  486.         print ("Process 1\n")
  487.         for i = 2 to numProcs
  488.           pid = Sys_Fork ()
  489.           if pid == 0
  490.             -- Code for a new child
  491.             print ("Process ")
  492.             printInt (i)
  493.             nl ()
  494.           else
  495.             -- Code for the parent: wait on the child
  496.             Sys_Exit (Sys_Join (pid))
  497.           endIf
  498.         endFor
  499.         -- Last child will exit loop and return
  500.         Sys_Exit (123)
  501.       else
  502.         -- Code for original parent: wait on its child
  503.         printIntVar ("Final return value", Sys_Join (pid))
  504.         print ("Done.\n")
  505.       endIf
  506.  
  507.     endFunction
  508.  
  509. -----------------------------  ErrorTest  ---------------------------------
  510.  
  511.   function ErrorTest ()
  512.     --
  513.     -- This tests what happens when a user-level program has an error.
  514.     --
  515.       var pid, i: int
  516.           p: ptr to int
  517.  
  518.       print ("\nErrorTest running.\n\n")
  519.  
  520.       print ("Should print \"User Program Error: Attempt to use a null pointer!\"...\n")
  521.       pid = Sys_Fork ()
  522.       if pid == 0
  523.         -- Child process: cause runtime error
  524.         *p = 123
  525.         print ("*****  ERROR: Execution will not continue  *****\n")
  526.         Sys_Exit (0)
  527.       endIf
  528.  
  529.       -- Parent process: wait for child to complete
  530.       i = Sys_Join (pid)
  531.       nl ()
  532.       Check (i, -2)
  533.  
  534.       print ("\nShould print \"An AddressException exception has occured while in user mode\"...\n")
  535.       pid = Sys_Fork ()
  536.       if pid == 0
  537.         -- Child process: cause address exception
  538.         p = 0xeeeeeee0 asPtrTo int
  539.         *p = 123
  540.         print ("*****  ERROR: Execution will not continue  *****\n")
  541.         Sys_Exit (0)
  542.       endIf
  543.  
  544.       -- Parent process: wait for child to complete
  545.       i = Sys_Join (pid)
  546.       nl ()
  547.       Check (i, -1)
  548.  
  549.       print ("\nShould print \"A PageReadonlyException exception has occured while in user mode\"...\n")
  550.       pid = Sys_Fork ()
  551.       if pid == 0
  552.         -- Child process: cause page fault
  553.         p = main asPtrTo int
  554.         *p = 123
  555.         print ("*****  ERROR: Execution will not continue  *****\n")
  556.         Sys_Exit (0)
  557.       endIf
  558.  
  559.       -- Parent process: wait for child to complete
  560.       i = Sys_Join (pid)
  561.       nl ()
  562.       Check (i, -1)
  563.  
  564.       print ("\nDone.\n")
  565.  
  566.     endFunction
  567.  
  568. -----------------------------  Check  ---------------------------------
  569.  
  570.   function Check (i, expectedVal: int)
  571.     --
  572.     -- This function is passed the return code from a syscall and
  573.     -- the expected value.  It prints an error message if it is incorrect.
  574.     --
  575.       if i == expectedVal
  576.         print ("Okay.\n")
  577.       else
  578.         print ("*****  ERROR: Return value from syscall (")
  579.         printInt (i)
  580.         print (") is incorrect  *****\n")
  581.       endIf
  582.       
  583.     endFunction
  584.  
  585.  
  586. endCode
  587.