home *** CD-ROM | disk | FTP | other *** search
/ Programmer's ROM - The Computer Language Library / programmersrom.iso / ada / test / tasking.src < prev   
Encoding:
Text File  |  1988-05-03  |  65.3 KB  |  2,299 lines

  1. ::::::::::
  2. cpu_body.ada
  3. ::::::::::
  4. With SYSTEM;
  5. package body Cpu is
  6.  
  7. Type Time_Val is record  -- how unix represents cpu time
  8.            Seconds : INTEGER;
  9.        Micro_Seconds : INTEGER;
  10.      end record;
  11.  
  12. type Filler is array (INTEGER range <>) of INTEGER;
  13.  
  14. type RUsage is record     -- unix structure
  15.       User_Time : Time_Val;
  16.       System_Time : Time_Val;
  17.       Junk        : Filler (1 .. 100);  -- not used here
  18.     end record;
  19.  
  20.   -- unix procedure to return the resource utilization information
  21. procedure getrusage (Who : INTEGER; Rec_Addr : in SYSTEM.ADDRESS);
  22. Pragma INTERFACE (C, getrusage);
  23.  
  24.  
  25.   -- implementation of package specification routine  
  26. function Milliseconds return INTEGER is
  27.   Unix_Info : RUsage;
  28. begin
  29.     -- ask unix for the resource utilization information
  30.   getrusage (0,                  -- this process
  31.          Unix_Info'ADDRESS); -- where to put the results
  32.  
  33.     -- add together the user and system time and convert to milliseconds
  34.   return (Unix_Info.User_Time.Micro_Seconds +
  35.       Unix_Info.System_Time.Micro_Seconds) / 1000 +
  36.      (Unix_Info.User_Time.Seconds +
  37.       Unix_Info.System_Time.Seconds) * 1000;
  38. end Milliseconds;
  39.  
  40. function Clock return Time is
  41. begin
  42.   return Time(Time(Milliseconds) * Time(0.001));
  43. end Clock;
  44.  
  45. function "-" (Stop_Time, Start_Time : Time) return DURATION is
  46. begin
  47.   return DURATION (DURATION (Stop_Time) - DURATION (Start_Time));
  48. end "-";
  49.  
  50. begin
  51.   null;
  52. end Cpu;
  53. ::::::::::
  54. cpu_spec.ada
  55. ::::::::::
  56. --  this is a machine specific package for reporting the amount of
  57. --  CPU time used. 
  58. package Cpu is
  59.   type Time is private;
  60.  
  61.     --  The time returned by Clock can only be used to determine the
  62.     --  difference between two times.
  63.   function Clock return Time;
  64.  
  65.     -- subtracting two times will result in the duration (seconds).
  66.   function "-" (Stop_Time, Start_Time : Time) return DURATION;
  67. private
  68.   type Time is new DURATION;
  69. end Cpu;
  70.  
  71. ::::::::::
  72. driver.ada
  73. ::::::::::
  74. ---------------- tasking benchmark main driver -----------------------
  75.  
  76. ------------------ note that SYSTEM is included so that system dependent
  77. ------------------ characteristics can be displayed.
  78. with TEXT_IO, SYSTEM, CALENDAR;
  79. use  TEXT_IO;
  80.  
  81. ------------------ all the tests are in packages PartN procedure Do_Test
  82. ------------------ where N ranges from 1 to the number of test sections
  83. with Part1, Part2, Part3, Part4, Part5;
  84.  
  85. procedure Driver is
  86.   Version : constant STRING := "August 1, 1986"; -- last modification date
  87.  
  88.  
  89.   Quiet : BOOLEAN;  -- true implies no further prompting on each test
  90.                     -- and that each test is to be run.
  91.  
  92.   Results : FILE_TYPE;     -- file where test results are written.
  93.                            -- Do not use this file directly.  Instead, use
  94.                            -- standard output for user messages and 
  95.                            -- current output for test results.
  96.  
  97. procedure Print_Header_Info is
  98. use SYSTEM;
  99. begin
  100.   PUT_LINE ("                      Tasking Benchmark");
  101.   NEW_LINE;
  102.   PUT_LINE ("Benchmark Version of " & Version);
  103.   PUT_LINE ("System is " & SYSTEM.NAME'IMAGE (SYSTEM_NAME));
  104.  
  105.   declare
  106.     use CALENDAR;
  107.     Yr : YEAR_NUMBER;
  108.     Mo : MONTH_NUMBER;
  109.     Da : DAY_NUMBER;
  110.     Se : DAY_DURATION;
  111.     Hr  : INTEGER range 0 .. 23;
  112.     Min : INTEGER range 0 .. 59;
  113.     Sec : INTEGER range 0 .. 86_400;  -- seconds in a day
  114.   begin
  115.     SPLIT (CLOCK, Yr, Mo, Da, Se);
  116.     Sec := INTEGER (Se);
  117.     Hr := Sec / 3600;
  118.     Min := (Sec - Hr * 3600) / 60;
  119.     PUT      ("Benchmark run on ");
  120.     case Mo is
  121.       when  1 => PUT ("January");
  122.       when  2 => PUT ("February");
  123.       when  3 => PUT ("March");
  124.       when  4 => PUT ("April");
  125.       when  5 => PUT ("May");
  126.       when  6 => PUT ("June");
  127.       when  7 => PUT ("July");
  128.       when  8 => PUT ("August");
  129.       when  9 => PUT ("September");
  130.       when 10 => PUT ("October");
  131.       when 11 => PUT ("November");
  132.       when 12 => PUT ("December");
  133.     end case;
  134.     PUT_LINE (INTEGER'IMAGE (Da) & "," & INTEGER'IMAGE (Yr) & "   " & 
  135.               INTEGER'IMAGE (Hr * 100 + Min));
  136.   end;
  137.  
  138.   declare
  139.     package Float_Text_IO is new FLOAT_IO (FLOAT);
  140.     X : FLOAT;
  141.   begin
  142.     PUT ("Basic Clock Period (SYSTEM.TICK) is ");
  143.     X := FLOAT (TICK);
  144.     Float_Text_IO.DEFAULT_EXP := 0;  -- dont want scientific notation
  145.     Float_Text_IO.PUT (X);
  146.     PUT_LINE (" seconds.");
  147.   end;
  148.  
  149.   PUT_LINE ("INTEGER is represented with" & INTEGER'IMAGE (INTEGER'SIZE) &
  150.             " bits.");
  151.   
  152.   declare
  153.     task type T;
  154.     task body T is begin null; end T;
  155.   begin
  156.     PUT_LINE ("An empty task is allocated" & INTEGER'IMAGE (T'STORAGE_SIZE) &
  157.               " storage units.");
  158.   end;
  159. end Print_Header_Info;
  160.  
  161.  
  162. function Ask (Question : STRING) return BOOLEAN is
  163.   Ch : CHARACTER;
  164. begin
  165.   PUT (STANDARD_OUTPUT, Question & " (Y/N)? ");
  166.   loop
  167.     GET (Ch);
  168.     if (Ch = 'Y') or (Ch = 'y') then
  169.       return TRUE;
  170.     elsif (Ch = 'N') or (Ch = 'n') then
  171.       return FALSE;
  172.     end if;
  173.   end loop;
  174. end Ask;
  175.  
  176.  
  177. procedure Open_Files is
  178.   -- this procedure opens the output file for the results and makes
  179.   -- this file the default output file.
  180.  
  181.   Name : STRING (1 .. 80);
  182.   Len  : INTEGER range 0 .. Name'LAST;
  183. begin
  184.   Try_To_Open:
  185.   loop
  186.     PUT ("File name for results (<cr> for console) ");
  187.     GET_LINE (Name, Len);
  188.     exit Try_To_Open when Len = 0;
  189.       
  190.     begin
  191.       CREATE (Results, NAME => Name (1 .. Len));
  192.       SET_OUTPUT (Results);
  193.       exit Try_To_Open;
  194.     exception
  195.       when NAME_ERROR | USE_ERROR => PUT_LINE ("Cannot create file");
  196.     end;
  197.   end loop Try_To_Open;
  198. end Open_Files;
  199.  
  200. begin  -- Driver
  201.   PUT_LINE ("Tasking Benchmark");
  202.   Open_Files;
  203.   Quiet := Ask ("Do you wish to run all the tests");
  204.  
  205.   Print_Header_Info;
  206.  
  207.   if Quiet or else Ask ("Run " & Part1.Title & " timings") then
  208.     NEW_PAGE;
  209.     Part1.Do_Test;
  210.   end if;
  211.  
  212.   if Quiet or else Ask ("Run " & Part2.Title & " timings") then
  213.     NEW_PAGE;
  214.     Part2.Do_Test;
  215.   end if;
  216.  
  217.   if Quiet or else Ask ("Run " & Part3.Title & " timings") then
  218.     NEW_PAGE;
  219.     Part3.Do_Test;
  220.   end if;
  221.  
  222.   if Quiet or else Ask ("Run " & Part4.Title & " timings") then
  223.     NEW_PAGE;
  224.     Part4.Do_Test;
  225.   end if;
  226.  
  227.   if Quiet or else Ask ("Run " & Part5.Title & " timings") then
  228.     NEW_PAGE;
  229.     Part5.Do_Test;
  230.   end if;
  231.  
  232.  
  233.   -- other tests go here
  234.  
  235.  
  236.   if LINE > 50 then
  237.     NEW_PAGE;
  238.   else
  239.     NEW_LINE (10);
  240.   end if;
  241.  
  242.   PUT_LINE (STANDARD_OUTPUT, "Test Complete");
  243. end Driver;
  244. ::::::::::
  245. misc_benchmark_body.ada
  246. ::::::::::
  247. --  this is a package which provides a default
  248. --  for the overhead timing subprogram in the Benchmark Generic
  249. --  as well as miscellaneous timing routines.
  250. with TEXT_IO; use TEXT_IO;
  251. with CALENDAR; use CALENDAR;
  252. with Cpu; use Cpu;
  253. package body Misc_Benchmark is
  254.  
  255. procedure Get_Both_Times (Now : out Raw_Time_Info) is
  256. -- retrieves the current elapsed time and cpu time
  257. begin
  258.   Now.Elapsed_Time := CALENDAR.CLOCK;
  259.   Now.Cpu_Time := Cpu.Clock;
  260. end Get_Both_Times;
  261.  
  262. function "-" (Stop, Start : in Raw_Time_Info) return Time_Info is
  263. begin
  264.   return (Elapsed_Time => Stop.Elapsed_Time - Start.Elapsed_Time,
  265.           Cpu_Time => Stop.Cpu_Time - Start.Cpu_Time);
  266. end "-";
  267.  
  268. procedure Print_Results (Results : in Results_Type;
  269.                          Overhead_Results : in Results_Type;
  270.                          Test_Repetitions : NATURAL;
  271.                          Iterations : NATURAL) is
  272.  
  273.   package Duration_IO is new FIXED_IO (DURATION);
  274.   use Duration_IO;
  275.  
  276.   type Net_Cpu_Type is array (1..Test_Repetitions) of DURATION;
  277.   Net_Cpus : Net_Cpu_Type;  -- contains the Net Cpu per repetition
  278.   Total_Cpu : DURATION := 0.0;
  279.  
  280. begin
  281.   NEW_LINE;
  282.   PUT("Number of iterations executed per repetition: ");
  283.   PUT(NATURAL'IMAGE(Iterations));
  284.   NEW_LINE;
  285.   NEW_LINE;
  286.   PUT_LINE("Note that all times are in seconds.");
  287.   NEW_LINE;
  288.  
  289.   -- build table header
  290.   PUT("|-----------------------------------------------------------------");
  291.   PUT_LINE("-------------|");
  292.   PUT("| REPETITION |  OVERHEAD  |    TEST    |     NET    |   TEST     |");
  293.   PUT_LINE(" NET CPU PER |");
  294.   PUT("| NUMBER     |  CPU       |    CPU     |     CPU    |   ELAPSED  |");
  295.   PUT_LINE(" ITERATION   |");
  296.  
  297.   for Repetitions in 1..Test_Repetitions loop
  298.     PUT("|------------|------------|------------|------------|------------|");
  299.     PUT_LINE("-------------|");
  300.     PUT("|     ");
  301.     PUT(NATURAL'IMAGE(Repetitions));
  302.     SET_COL(14); 
  303.     PUT("| "); 
  304.     PUT(Overhead_Results (Repetitions).Cpu_Time,FORE => 5);
  305.     SET_COL(27);
  306.     PUT("| "); 
  307.     PUT(Results (Repetitions).Cpu_Time,FORE => 5);
  308.     SET_COL(40);
  309.     PUT("| ");
  310.     Net_Cpus(Repetitions) := DURATION(Results(Repetitions).Cpu_Time - 
  311.                                       Overhead_Results(Repetitions).Cpu_Time);
  312.     Total_Cpu := Total_Cpu + Net_Cpus(Repetitions);
  313.     PUT(Net_Cpus(Repetitions),FORE => 5);
  314.     SET_COL(53);
  315.     PUT("| ");
  316.     PUT(Results (Repetitions).Elapsed_Time,FORE => 5);
  317.     SET_COL(66);
  318.     PUT("|  ");
  319.     PUT(DURATION(Net_Cpus(Repetitions) / DURATION(Iterations)),FORE => 5);
  320.     SET_COL(80);
  321.     PUT_LINE("|");
  322.   end loop;
  323.  
  324.   PUT("|-----------------------------------------------------------------");
  325.   PUT_LINE("-------------|");
  326.  
  327.   -- Output Net Cpu time averaged across repetitions
  328.   NEW_LINE;
  329.   NEW_LINE;
  330.   PUT("The average net cpu time (across repetitions) was: ");
  331.   PUT(DURATION(Total_Cpu / DURATION(Test_Repetitions)),FORE=>5);
  332.   NEW_LINE;
  333.   PUT("The average net cpu time per iteration was: ");
  334.   PUT(DURATION(Total_Cpu / DURATION(Test_Repetitions * Iterations)),FORE=>5);
  335.   NEW_LINE;
  336.   NEW_LINE;
  337.   PUT_LINE((1..80=> '-'));
  338.   PUT_LINE((1..80=> '-'));
  339. end Print_Results;
  340.  
  341.  
  342. procedure Default_Overhead (Iterations : in NATURAL) is
  343. begin
  344.   for Loop_Count in 1..Iterations loop
  345.     null;
  346.   end loop;
  347. end Default_Overhead;
  348.  
  349. begin
  350.   null;
  351. end Misc_Benchmark;
  352. ::::::::::
  353. misc_benchmark_spec.ada
  354. ::::::::::
  355. --  this is a package which provides a default
  356. --  for the overhead timing subprogram in the Benchmark Generic
  357. --  as well as miscellaneous timing routines.
  358. with CALENDAR; use CALENDAR;
  359. with Cpu; use Cpu;
  360. package Misc_Benchmark is
  361.   type Time_Info is private;
  362.   type Raw_Time_Info is private;
  363.   type Results_Type is array (NATURAL range <>) of Time_Info;
  364.  
  365.   procedure Get_Both_Times (Now : out Raw_Time_Info);
  366.   function "-" (Stop, Start : in Raw_Time_Info) return Time_Info;
  367.   procedure Print_Results (Results : in Results_Type;
  368.                            Overhead_Results : in Results_Type;
  369.                            Test_Repetitions : NATURAL;
  370.                            Iterations : NATURAL);
  371.  
  372.   procedure Default_Overhead (Iterations : in NATURAL);
  373.  
  374. private
  375.   type Time_Info is record
  376.          Elapsed_Time,
  377.          Cpu_Time : DURATION;
  378.        end record;
  379.  
  380.   type Raw_Time_Info is record
  381.          Elapsed_Time  : CALENDAR.TIME;
  382.          Cpu_Time      : Cpu.Time;
  383.        end record;
  384.  
  385. end Misc_Benchmark;
  386. ::::::::::
  387. part1.ada
  388. ::::::::::
  389. ---- test section 1 - task activation/termination
  390. with TEXT_IO, Benchmark;
  391. use  TEXT_IO;
  392. package body Part1 is
  393.  
  394. procedure Do_Test is
  395.  
  396.     procedure Task_Activation (N : in NATURAL) is
  397.       -- this procedure declares N tasks locally - timing this procedure
  398.       -- will time 1 procedure call and N task activations/terminations
  399.  
  400.       task type Empty_Task;
  401.  
  402.       Lots_Of_Tasks : array (1 .. N) of Empty_Task;
  403.  
  404.       task body Empty_Task is
  405.       begin
  406.         null;
  407.       end  Empty_Task;
  408.  
  409.     begin
  410.       null;
  411.     end Task_Activation;
  412.  
  413.  
  414.     procedure Task_Allocation (N : in NATURAL) is
  415.     -- this procedure allocates N tasks.  Since the task type is declared
  416.     -- locally, deallocation of the task space should occur during the
  417.     -- call to this procedure.
  418.  
  419.       task type Empty_Task;
  420.  
  421.       type Empty_Task_Ptr is access Empty_Task;
  422.       Lots_Of_Tasks : array (1 .. N) of Empty_Task_Ptr;
  423.  
  424.       task body Empty_Task is
  425.       begin
  426.         null;
  427.       end  Empty_Task;
  428.  
  429.     begin
  430.       Lots_Of_Tasks := (1 .. N => new Empty_Task);
  431.     end Task_Allocation;
  432.  
  433.     procedure Task_Activation2 (N : in NATURAL) is
  434.       -- this procedure declares N tasks locally - timing this procedure
  435.       -- will time 1 procedure call and N task activations/terminations
  436.  
  437.       task type Empty_Task is
  438.          entry Dont_Call_Me;
  439.       end Empty_Task;
  440.  
  441.       Lots_Of_Tasks : array (1 .. N) of Empty_Task;
  442.  
  443.       task body Empty_Task is
  444.       begin
  445.         select
  446.           accept Dont_Call_Me;
  447.         or
  448.           terminate;
  449.         end select;
  450.       end  Empty_Task;
  451.  
  452.     begin
  453.       null;
  454.     end Task_Activation2;
  455.  
  456.  
  457. begin  -- Do_Test
  458.     PUT_LINE ("               Task Activation/Termination Test");
  459.     NEW_LINE;
  460.     PUT_LINE ("This test times task activation and termination under a ");
  461.     PUT_LINE ("variety of circumstances.");
  462.  
  463.               --------------------------------------------
  464.  
  465.     NEW_LINE (2);
  466.     PUT_LINE ("In this test an array of tasks is declared locally to a");
  467.     PUT_LINE ("procedure.  Both the procedure and the task have null bodies.");
  468.     NEW_LINE;
  469.  
  470.     declare
  471.       package Local_Array_Pkg is new Benchmark 
  472.               (Item_Of_Interest => Task_Activation);
  473.     begin
  474.       Local_Array_Pkg.Timer;
  475.     end;
  476.  
  477.               --------------------------------------------
  478.  
  479.     NEW_LINE (2);
  480.     PUT_LINE ("In this test an array of tasks is declared locally to a");
  481.     PUT_LINE ("procedure.  The task uses the terminate option in a select");
  482.     PUT_LINE ("statement to terminate.  The task is never called");
  483.     NEW_LINE;
  484.  
  485.     declare
  486.       package Terminate_Array_Pkg is new Benchmark
  487.               (Item_Of_Interest => Task_Activation2);
  488.     begin
  489.       Terminate_Array_Pkg.Timer;
  490.     end;
  491.  
  492.              ----------------------------------------
  493.  
  494.     NEW_LINE (2);
  495.     PUT_LINE ("In this test an access type to a task is used to create a");
  496.     PUT_LINE ("series of tasks.  The timing should include both allocation");
  497.     PUT_LINE ("and deallocation of the task as well as activation and");
  498.     PUT_LINE ("termination.");
  499.     NEW_LINE;
  500.  
  501.     declare
  502.       package Access_Type_Pkg is new Benchmark
  503.               (Item_Of_Interest => Task_Allocation);
  504.     begin
  505.       Access_Type_Pkg.Timer;
  506.     end;
  507.  
  508.  
  509. exception
  510.   when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  511.   when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  512.   when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  513.   when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  514.   when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  515.   when others           => PUT_LINE ("*** test aborted due to exception");
  516.  
  517. end Do_Test;
  518.  
  519. end Part1;
  520. ::::::::::
  521. part1spec.ada
  522. ::::::::::
  523. ---- test section 1
  524.  
  525. package Part1 is
  526.   Title : constant STRING := "task activation/termination";
  527.   procedure Do_Test;
  528. end Part1;
  529. ::::::::::
  530. part2.ada
  531. ::::::::::
  532. --- test section 2  --  task communication
  533. with TEXT_IO, Benchmark;
  534. use  TEXT_IO;
  535. package body Part2 is
  536.  
  537. -- define the continue and terminate conditions for the tasks
  538. Continue_Item : constant := 1;
  539. Terminate_Item : constant := -1;
  540.  
  541.  
  542. procedure Do_Test is
  543.  
  544.  
  545.   -- task types that are used in several tests
  546.  
  547.   task type Buffer_Type is
  548.     entry Take_Item (Item : in INTEGER);
  549.     entry Provide_Item (Item : out INTEGER);
  550.   end Buffer_Type;
  551.  
  552.   task type Called_Consumer_Type is
  553.         -- consumer is to take items until 
  554.         -- a value of Terminate_Item is accepted. 
  555.     entry Take_Item (Item : in INTEGER);
  556.   end Called_Consumer_Type;
  557.  
  558. pragma PAGE;
  559.   
  560.   task body Buffer_Type is
  561.      type Buffer_Count is range 0 .. 2;
  562.      subtype Buffer_Index is Buffer_Count range 1 .. Buffer_Count'LAST;
  563.      Buf : array (Buffer_Index) of INTEGER;
  564.      Head, Tail : Buffer_Index := Buffer_Index'FIRST;
  565.      Count : Buffer_Count := 0;
  566.   begin
  567.     loop
  568.       select
  569.         when Count > 0 =>
  570.         accept Provide_Item (Item : out INTEGER) do
  571.           Item := Buf (Tail);
  572.           Tail := (Tail mod Buffer_Index'LAST) + 1;
  573.           Count := Count - 1;
  574.         end Provide_Item;
  575.       or
  576.         when Count < Buffer_Count'LAST =>
  577.         accept Take_Item (Item : in INTEGER) do
  578.           Buf (Head) := Item;
  579.           Head := (Head mod Buffer_Index'LAST) + 1;
  580.           Count := Count + 1;
  581.         end Take_Item;
  582.       or
  583.         terminate;
  584.       end select;
  585.     end loop;
  586.   end Buffer_Type;
  587.  
  588.  
  589.  
  590.   task body Called_Consumer_Type is
  591.     Item : INTEGER;
  592.   begin
  593.     loop
  594.       accept Take_Item (Item : in INTEGER) do
  595.         Called_Consumer_Type.Item := Item;
  596.       end Take_Item;
  597.  
  598.       exit when Item = Terminate_Item;
  599.  
  600.     end loop;
  601.   end Called_Consumer_Type;
  602. pragma PAGE;
  603.  
  604. procedure Time_PC is
  605.   Consumer : Called_Consumer_Type;
  606.  
  607. begin
  608.   NEW_LINE (2);
  609.   PUT_LINE ("SIMPLE PC");
  610.   PUT_LINE ("In this test the main task calls a consumer task.");
  611.   PUT_LINE ("A simple integer value is the only data transferred");
  612.   PUT_LINE ("and the consumer simply loops on the accept.");
  613.   PUT_LINE ("Task activation/termination time is not included in the timing.");
  614.   NEW_LINE;
  615.  
  616.   declare
  617.     procedure Send_Item (Iterations : in NATURAL) is
  618.     begin
  619.       for J in 1..Iterations loop
  620.         Consumer.Take_Item (Continue_Item);
  621.       end loop;
  622.     end Send_Item;
  623.  
  624.     package PC_Pkg is new Benchmark
  625.             (Item_Of_Interest => Send_Item);
  626.   begin
  627.     PC_Pkg.Timer;
  628.     Consumer.Take_Item (Terminate_Item);
  629.   end;
  630.  
  631. exception
  632.   when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  633.   when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  634.   when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  635.   when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  636.   when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  637.   when others           => PUT_LINE ("*** test aborted due to exception");
  638. end Time_PC;
  639. pragma PAGE;
  640.  
  641. procedure Time_PC2 is
  642.  
  643.   task type Called_Consumer_Type_With_Select is
  644.         -- consumer is to take items until 
  645.         -- a value of Terminate_Item is accepted. 
  646.     entry Take_Item (Item : in INTEGER);
  647.     entry Stop;  -- alternate entry for Take_Item
  648.   end Called_Consumer_Type_With_Select;
  649.  
  650.   Consumer : Called_Consumer_Type_With_Select;
  651.  
  652.  
  653.  
  654.   task body Called_Consumer_Type_With_Select is
  655.     Item : INTEGER;
  656.   begin
  657.     loop
  658.       select
  659.         accept Take_Item (Item : in INTEGER) do
  660.           Called_Consumer_Type_With_Select.Item := Item;
  661.         end Take_Item;
  662.       or
  663.         accept Stop do
  664.            Item := Item;
  665.         end Stop;
  666.       end select;
  667.  
  668.       exit when Item = Terminate_Item;
  669.  
  670.     end loop;
  671.   end Called_Consumer_Type_With_Select;
  672.  
  673.  
  674. begin
  675.   NEW_LINE (2);
  676.   PUT_LINE ("SELECTIVE WAIT");
  677.   PUT_LINE ("In this test the main task calls a consumer task that");
  678.   PUT_LINE ("consumes more than one type of item.");
  679.   PUT_LINE ("A simple integer value is the only data transferred");
  680.   PUT_LINE ("and the consumer simply loops on the selective accept.");
  681.   PUT_LINE ("This test differs from the previous test in that the consumer");
  682.   PUT_LINE ("uses a select statement to take the entry call where the");
  683.   PUT_LINE ("select has two open alternatives.  In the previous case");
  684.   PUT_LINE ("there was no select statement.");
  685.   NEW_LINE;
  686.  
  687.   declare
  688.     procedure Send_Item (Iterations : in NATURAL) is
  689.     begin
  690.       for J in 1..Iterations loop
  691.         Consumer.Take_Item (Continue_Item);
  692.       end loop;
  693.     end Send_Item;
  694.  
  695.     package PC2_Pkg is new Benchmark
  696.             (Item_Of_Interest => Send_Item);
  697.   begin
  698.     PC2_Pkg.Timer;
  699.     Consumer.Take_Item (Terminate_Item);
  700.   end;
  701.  
  702. exception
  703.   when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  704.   when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  705.   when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  706.   when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  707.   when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  708.   when others           => PUT_LINE ("*** test aborted due to exception");
  709. end Time_PC2;
  710. pragma PAGE;
  711.  
  712. procedure Time_PC3 is
  713.   Consumer : Called_Consumer_Type;
  714.  
  715.   task Producer is
  716.        -- producer terminates upon accepting Terminate_Item.
  717.     entry Produce (Num : in INTEGER);
  718.     entry Have_Finished;
  719.     
  720.     -- Calls
  721.        -- Consumer.Take_Item
  722.   end Producer;
  723.  
  724.  
  725.   task body Producer is
  726.     Count : INTEGER;
  727.   begin
  728.     loop
  729.       accept Produce (Num : in INTEGER) do
  730.         Count := Num;
  731.       end Produce;
  732.  
  733.       exit when Count = Terminate_Item;
  734.  
  735.       for I in 1 .. Count loop
  736.         Consumer.Take_Item (Continue_Item);
  737.       end loop;
  738.  
  739.       accept Have_Finished;
  740.     end loop;
  741.   end Producer;
  742.  
  743.   
  744. begin
  745.   NEW_LINE (2);
  746.   PUT_LINE ("PC");
  747.   PUT_LINE ("In this test a producer task communicates with a consumer task");
  748.   PUT_LINE ("directly. This timing should be similar to the simple PC tests.");
  749.   PUT_LINE ("Interaction with the main task takes place only at the beginning");
  750.   PUT_LINE ("and at the end.");
  751.   PUT_LINE ("Total number of task interactions is N+2");
  752.   NEW_LINE;
  753.  
  754.   declare
  755.     procedure Tell_Producer (Iterations : in NATURAL) is
  756.     begin
  757.       Producer.Produce (Iterations);
  758.       Producer.Have_Finished;
  759.     end Tell_Producer;
  760.  
  761.     package PC3_Pkg is new Benchmark
  762.             (Item_Of_Interest => Tell_Producer);
  763.  
  764.   begin
  765.     PC3_Pkg.Timer;
  766.     Producer.Produce (Terminate_Item);
  767.     Consumer.Take_Item (Terminate_Item);
  768.   end;
  769.  
  770. exception
  771.   when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  772.   when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  773.   when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  774.   when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  775.   when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  776.   when others           => PUT_LINE ("*** test aborted due to exception");
  777. end Time_PC3;
  778. pragma PAGE;
  779.  
  780. procedure Time_PBC is
  781.   Buffer : Buffer_Type;
  782.  
  783.  
  784.   task type Calling_Consumer_Type is
  785.         -- consumer is to take items until 
  786.         -- a value of Terminate_Item is received. 
  787.     entry Stop_On_Number (Num : in INTEGER); 
  788.  
  789.     -- Calls
  790.        -- Buffer.Provide_Item
  791.   end Calling_Consumer_Type;
  792.  
  793.   Consumer : Calling_Consumer_Type;
  794.  
  795.  
  796.   task Producer is
  797.     entry Produce (Num : in INTEGER);
  798.     entry Have_Finished;
  799.     -- Calls
  800.        -- Buffer.Take_Item
  801.   end Producer;
  802.  
  803.  
  804.   task body Producer is
  805.     Count : INTEGER;
  806.   begin
  807.     loop
  808.       accept Produce (Num : in INTEGER) do
  809.         Count := Num;
  810.       end Produce;
  811.  
  812.       exit when Count = Terminate_Item;
  813.  
  814.       for I in 1 .. Count loop
  815.         Buffer.Take_Item (Continue_Item);
  816.       end loop;
  817.  
  818.       accept Have_Finished;
  819.     end loop;
  820.   end Producer;
  821.  
  822.  
  823.   task body Calling_Consumer_Type is
  824.     Item,
  825.     Count : INTEGER;
  826.   begin
  827.     loop
  828.       Accept Stop_On_Number (Num : in INTEGER) do
  829.         Count := Num;
  830.       end Stop_On_Number;
  831.  
  832.       exit when Count = Terminate_Item;
  833.  
  834.       for I in 1..Count loop
  835.         Buffer.Provide_Item (Item);
  836.       end loop;
  837.     end loop;
  838.   end Calling_Consumer_Type;
  839.  
  840.  
  841. begin
  842.   NEW_LINE (2);
  843.   PUT_LINE ("PBC");
  844.   PUT_LINE ("In this test a producer task communicates with a consumer task");
  845.   PUT_LINE ("indirectly through a bounded buffer (buffer size = 2).");
  846.   PUT_LINE ("Interaction with the main task takes place only at the beginning");
  847.   PUT_LINE ("and at the end.");
  848.   PUT_LINE ("Total number of task interactions is 2N+3.");
  849.   NEW_LINE;
  850.  
  851.   declare
  852.     procedure Tell_PC (Iterations : NATURAL) is
  853.     begin
  854.       Producer.Produce (Iterations);
  855.       Consumer.Stop_On_Number (Iterations);
  856.       Producer.Have_Finished;
  857.     end Tell_PC;
  858.  
  859.     package PBC_Pkg is new Benchmark
  860.             (Item_Of_Interest => Tell_PC);
  861.  
  862.   begin
  863.     PBC_Pkg.Timer;
  864.     Producer.Produce (Terminate_Item);
  865.     Consumer.Stop_On_Number (Terminate_Item);
  866.   end;
  867.  
  868. exception
  869.   when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  870.   when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  871.   when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  872.   when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  873.   when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  874.   when others           => PUT_LINE ("*** test aborted due to exception");
  875. end Time_PBC;
  876. pragma PAGE;
  877.  
  878. procedure Time_PBTC is
  879.   Buffer      : Buffer_Type;
  880.   Consumer    : Called_Consumer_Type;
  881.  
  882.   task Producer is
  883.     entry Produce (Num : in INTEGER);
  884.     entry Have_Finished;
  885.  
  886.     -- Calls
  887.        -- Buffer.Take_Item
  888.   end Producer;
  889.  
  890.   
  891.   task Transporter is
  892.     -- Calls
  893.        -- Buffer.Provide_Item
  894.        -- Consumer.Take_Item
  895.   end Transporter;
  896.  
  897.  
  898.   task body Transporter is
  899.     Item : INTEGER;
  900.   begin
  901.     loop
  902.       Buffer.Provide_Item (Item);
  903.       Consumer.Take_Item (Item);
  904.     end loop;
  905.   end Transporter;
  906.  
  907.  
  908.   task body Producer is
  909.     Count : INTEGER;
  910.   begin
  911.     loop
  912.       accept Produce (Num : in INTEGER) do
  913.         Count := Num;
  914.       end Produce;
  915.  
  916.       exit when Count = Terminate_Item;
  917.  
  918.       for I in 1 .. Count loop
  919.         Buffer.Take_Item (Continue_Item);
  920.       end loop;
  921.  
  922.       accept Have_Finished;
  923.     end loop;
  924.   end Producer;
  925.  
  926. begin
  927.   NEW_LINE (2);
  928.   PUT_LINE ("PBTC");
  929.   PUT_LINE ("In this test a producer task communicates with a consumer task");
  930.   PUT_LINE ("indirectly through a bounded buffer (buffer size = 2) with");
  931.   PUT_LINE ("a transporter between the buffer and the consumer.");
  932.   PUT_LINE ("Interaction with the main task takes place only at the beginning");
  933.   PUT_LINE ("and at the end.");
  934.   PUT_LINE ("Total number of task interactions is 3N+2.");
  935.   NEW_LINE;
  936.  
  937.   declare
  938.     procedure Tell_Producer (Iterations : in NATURAL) is
  939.     begin
  940.       Producer.Produce (Iterations);
  941.       Producer.Have_Finished;
  942.     end Tell_Producer;
  943.  
  944.     package PBTC_Pkg is new Benchmark
  945.             (Item_Of_Interest => Tell_Producer);
  946.  
  947.   begin
  948.     PBTC_Pkg.Timer;
  949.     Producer.Produce (Terminate_Item);         
  950.     Consumer.Take_Item (Terminate_Item);  
  951.     abort Transporter;            -- do this so buffer will die on its own
  952.   end;
  953.  
  954. exception
  955.   when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  956.   when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  957.   when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  958.   when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  959.   when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  960.   when others           => PUT_LINE ("*** test aborted due to exception");
  961. end Time_PBTC;
  962. pragma PAGE;
  963.  
  964. procedure Time_PTBTC is
  965.   Buffer      : Buffer_Type;
  966.   Consumer    : Called_Consumer_Type;
  967.  
  968.   task Producer is
  969.     entry Produce (Num : in INTEGER);
  970.     entry Provide_Item (Item : out INTEGER);
  971.     entry Have_Finished;
  972.   end Producer;
  973.  
  974.   
  975.   task C_Transporter is
  976.     -- Calls
  977.        -- Buffer.Provide_Item
  978.        -- Consumer.Take_Item
  979.   end C_Transporter;
  980.  
  981.  
  982.   task body C_Transporter is
  983.     Item : INTEGER;
  984.   begin
  985.     loop
  986.       Buffer.Provide_Item (Item);
  987.       Consumer.Take_Item (Item);
  988.     end loop;
  989.   end C_Transporter;
  990.  
  991.   
  992.   task P_Transporter is
  993.     -- Calls
  994.        -- Producer.Provide_Item
  995.        -- Buffer.Take_Item
  996.   end P_Transporter;
  997.  
  998.  
  999.   task body P_Transporter is
  1000.     Item : INTEGER;
  1001.   begin
  1002.     loop
  1003.       Producer.Provide_Item (Item);
  1004.       Buffer.Take_Item (Item);
  1005.     end loop;
  1006.   end P_Transporter;
  1007.  
  1008.  
  1009.   task body Producer is
  1010.     Count : INTEGER;
  1011.   begin
  1012.     loop
  1013.       accept Produce (Num : in INTEGER) do
  1014.         Count := Num;
  1015.       end Produce;
  1016.  
  1017.       exit when Count = Terminate_Item;
  1018.  
  1019.       for I in 1 .. Count loop
  1020.         accept Provide_Item (Item : out INTEGER) do
  1021.            Item := Continue_Item;
  1022.         end Provide_Item;
  1023.       end loop;
  1024.  
  1025.       accept Have_Finished;
  1026.  
  1027.     end loop;
  1028.   end Producer;
  1029.  
  1030. begin
  1031.   NEW_LINE (2);
  1032.   PUT_LINE ("PTBTC");
  1033.   PUT_LINE ("In this test a producer task communicates with a consumer task");
  1034.   PUT_LINE ("indirectly through a bounded buffer (buffer size = 2) with");
  1035.   PUT_LINE ("a transporter for both the producer and the consumer.");
  1036.   PUT_LINE ("Interaction with the main task takes place only at the beginning");
  1037.   PUT_LINE ("and at the end.");
  1038.   PUT_LINE ("Total number of task interactions is 4N+2.");
  1039.   NEW_LINE;
  1040.  
  1041.   declare
  1042.     procedure Tell_Producer (Iterations : in NATURAL) is
  1043.     begin
  1044.       Producer.Produce (Iterations);
  1045.       Producer.Have_Finished;
  1046.     end Tell_Producer;
  1047.  
  1048.     package PTBTC_Pkg is new Benchmark
  1049.             (Item_Of_Interest => Tell_Producer);
  1050.   begin
  1051.     PTBTC_Pkg.Timer;
  1052.     Producer.Produce (Terminate_Item);         
  1053.     Consumer.Take_Item (Terminate_Item); 
  1054.     abort P_Transporter, C_Transporter; -- do this so buffer will die on its own
  1055.   end;
  1056.  
  1057. exception
  1058.   when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  1059.   when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  1060.   when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  1061.   when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  1062.   when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  1063.   when others           => PUT_LINE ("*** test aborted due to exception");
  1064. end Time_PTBTC;
  1065. pragma PAGE;
  1066.  
  1067. procedure Time_Relay is
  1068.   Consumer    : Called_Consumer_Type;
  1069.   
  1070.  
  1071.   task Producer is
  1072.     entry Produce (Num : in INTEGER);
  1073.     entry Have_Finished;
  1074.  
  1075.     -- Calls
  1076.        -- Relay.Take_Item
  1077.   end Producer;
  1078.  
  1079.   
  1080.   task Relay is
  1081.     entry Take_Item (Item : in INTEGER);
  1082.  
  1083.     -- Calls
  1084.        -- Consumer.Take_Item
  1085.   end Relay;
  1086.  
  1087.  
  1088.   task body Relay is
  1089.     Item : INTEGER;
  1090.   begin
  1091.     loop
  1092.       accept Take_Item (Item : in INTEGER) do
  1093.         Relay.Item := Take_Item.Item;
  1094.       end Take_Item;
  1095.  
  1096.       exit when Item = Terminate_Item;
  1097.  
  1098.       Consumer.Take_Item (Item);
  1099.     end loop;
  1100.   end Relay;
  1101.  
  1102.  
  1103.   task body Producer is
  1104.     Count : INTEGER;
  1105.   begin
  1106.     loop
  1107.       accept Produce (Num : in INTEGER) do
  1108.         Count := Num;
  1109.       end Produce;
  1110.  
  1111.       exit when Count = Terminate_Item;
  1112.  
  1113.       for I in 1 .. Count loop
  1114.         Relay.Take_Item (Continue_Item);
  1115.       end loop;
  1116.  
  1117.       accept Have_Finished;
  1118.  
  1119.     end loop;
  1120.   end Producer;
  1121.  
  1122. begin
  1123.   NEW_LINE (2);
  1124.   PUT_LINE ("RELAY");
  1125.   PUT_LINE ("In this test a producer task communicates with a consumer task");
  1126.   PUT_LINE ("indirectly through a relay.  In terms of the task communication");
  1127.   PUT_LINE ("model, this resembles the PBTC paradigm but in terms of");
  1128.   PUT_LINE ("performance it should resemble the PBC test.");
  1129.   PUT_LINE ("Interaction with the main task takes place only at the beginning");
  1130.   PUT_LINE ("and at the end.");
  1131.   PUT_LINE ("Total number of task interactions is 2N+2.");
  1132.   NEW_LINE;
  1133.  
  1134.   declare
  1135.     procedure Tell_Producer (Iterations : in NATURAL) is
  1136.     begin
  1137.       Producer.Produce (Iterations);
  1138.       Producer.Have_Finished;
  1139.     end Tell_Producer;
  1140.  
  1141.     package Relay_Pkg is new Benchmark
  1142.             (Item_Of_Interest => Tell_Producer);
  1143.   begin
  1144.     Relay_Pkg.Timer;
  1145.     Producer.Produce (Terminate_Item);         
  1146.     Consumer.Take_Item (Terminate_Item);  
  1147.     Relay.Take_Item (Terminate_Item);          
  1148.   end;
  1149.  
  1150. exception
  1151.   when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  1152.   when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  1153.   when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  1154.   when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  1155.   when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  1156.   when others           => PUT_LINE ("*** test aborted due to exception");
  1157. end Time_Relay;
  1158. pragma PAGE;
  1159.  
  1160. begin
  1161.   PUT_LINE ("               Task Communication");
  1162.   NEW_LINE;
  1163.   PUT_LINE ("This test times task to task communication in order to determine");
  1164.   PUT_LINE ("the cost of the various task communication models.  Task");
  1165.   PUT_LINE ("activation and termination is not included in the timings.");
  1166.   Time_PC;
  1167.   Time_PC2;
  1168.   Time_PC3;
  1169.   Time_PBC;
  1170.   Time_PBTC;
  1171.   Time_PTBTC;
  1172.   Time_Relay;
  1173.  
  1174. exception
  1175.   when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  1176.   when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  1177.   when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  1178.   when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  1179.   when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  1180.   when others           => PUT_LINE ("*** test aborted due to exception");
  1181.  
  1182. end Do_Test;
  1183.  
  1184. end Part2;
  1185. ::::::::::
  1186. part2spec.ada
  1187. ::::::::::
  1188. ---- test section 2
  1189.  
  1190. package Part2 is
  1191.   Title : constant STRING := "task communication";
  1192.   procedure Do_Test;
  1193. end Part2;
  1194. ::::::::::
  1195. part3.ada
  1196. ::::::::::
  1197. ------ test section 3 - task optimization techniques
  1198. with TEXT_IO, Benchmark;
  1199. use  TEXT_IO;
  1200. package body Part3 is
  1201.  
  1202. -- define the continue and terminate conditions for the tasks.
  1203. Continue_Item : constant := 1;
  1204. Terminate_Item : constant := -1;
  1205.  
  1206. procedure Do_Test is
  1207.  
  1208. procedure Time_Monitor is
  1209.  
  1210.   task General_Task is
  1211.     entry Take_Item (Item : in INTEGER);
  1212.     entry Provide_Item (Item : out INTEGER);
  1213.   end General_Task;
  1214.  
  1215.   task Monitor is
  1216.     entry Take_Item (Item : in INTEGER);
  1217.     entry Provide_Item (Item : out INTEGER);
  1218.   end Monitor;
  1219.  
  1220.   
  1221.   task body General_Task is
  1222.     Local : INTEGER;
  1223.   begin
  1224.     loop
  1225.       select
  1226.         accept Take_Item (Item : in INTEGER) do
  1227.           Local := Item;
  1228.         end Take_Item;
  1229.         Local := Local + 1;  -- the only difference is where this line is
  1230.       or
  1231.         accept Provide_Item (Item : out INTEGER) do
  1232.           Item := Local;
  1233.         end Provide_Item;
  1234.       or
  1235.         terminate;
  1236.       end select;
  1237.     end loop;
  1238.   end General_Task;
  1239.  
  1240.   
  1241.   task body Monitor is
  1242.     Local : INTEGER;
  1243.   begin
  1244.     loop
  1245.       select
  1246.         accept Take_Item (Item : in INTEGER) do
  1247.           Local := Item;
  1248.           Local := Local + 1;  -- the only difference is where this line is
  1249.         end Take_Item;
  1250.       or
  1251.         accept Provide_Item (Item : out INTEGER) do
  1252.           Item := Local;
  1253.         end Provide_Item;
  1254.       or
  1255.         terminate;
  1256.       end select;
  1257.     end loop;
  1258.   end Monitor;
  1259.  
  1260.  
  1261. begin
  1262.   NEW_LINE (2);
  1263.   PUT_LINE ("MONITOR");
  1264.   PUT_LINE ("A task that contains no code outside of the accept bodies");
  1265.   PUT_LINE ("is considered to be a monitor.  It is possible to eliminate");
  1266.   PUT_LINE ("such a task by protecting the task entries with semaphores.");
  1267.   PUT_LINE ("In this test the main task interacts with a monitor and with");
  1268.   PUT_LINE ("a more general task in order to determine if this optimization");
  1269.   PUT_LINE ("is performed.  The monitor is the overhead item and the general");
  1270.   PUT_LINE ("task is the tested item.  If the net cpu is negative or near");
  1271.   PUT_LINE ("zero, it can be assumed that the optimization is not done.");
  1272.   NEW_LINE;
  1273.  
  1274.   declare
  1275.     procedure Send_To_Monitor (Iterations : in NATURAL) is
  1276.     begin
  1277.       for J in 1..Iterations loop
  1278.         Monitor.Take_Item (Continue_Item);
  1279.       end loop;
  1280.     end Send_To_Monitor;
  1281.  
  1282.     procedure Send_To_General (Iterations : in NATURAL) is
  1283.     begin
  1284.       for J in 1..Iterations loop
  1285.         General_Task.Take_Item (Continue_Item);
  1286.       end loop;
  1287.     end Send_To_General;
  1288.  
  1289.     package Monitor_Pkg is new Benchmark
  1290.             (Overhead => Send_To_Monitor,
  1291.              Item_Of_Interest => Send_To_General);
  1292.  
  1293.   begin
  1294.     Monitor_Pkg.Timer;
  1295.   end;
  1296. end Time_Monitor;
  1297. pragma PAGE;
  1298.  
  1299. procedure Time_Single_Accept_Body is
  1300.  
  1301.   task Single_Accept is
  1302.     entry Take_Item (Item : in INTEGER);
  1303.     entry Stop;
  1304.   end Single_Accept;
  1305.  
  1306.   task body Single_Accept is
  1307.   begin
  1308.     loop
  1309.       select 
  1310.         accept Take_Item (Item : in INTEGER) do
  1311.           if Item = 0 then
  1312.             PUT_LINE ("error in test (single accept)");
  1313.           end if;
  1314.         end Take_Item;
  1315.       or
  1316.         accept Stop;
  1317.         exit;
  1318.       end select;
  1319.     end loop;
  1320.   end Single_Accept;
  1321.  
  1322.  
  1323.   task Multiple_Accept is
  1324.     entry Take_Item (Item : in INTEGER);
  1325.     entry Stop;
  1326.   end Multiple_Accept;
  1327.  
  1328.   task body Multiple_Accept is
  1329.   begin
  1330.     loop
  1331.       select 
  1332.         accept Take_Item (Item : in INTEGER) do
  1333.           if Item = 0 then
  1334.             PUT_LINE ("error in test (single accept)");
  1335.           end if;
  1336.         end Take_Item;
  1337.       or
  1338.         accept Stop;
  1339.         exit;
  1340.       end select;
  1341.  
  1342.          -- repeat select statement to create the multiple accept bodies
  1343.       select 
  1344.         accept Take_Item (Item : in INTEGER) do
  1345.           if Item = 0 then
  1346.             PUT_LINE ("error in test (single accept)");
  1347.           end if;
  1348.         end Take_Item;
  1349.       or
  1350.         accept Stop;
  1351.         exit;
  1352.       end select;
  1353.     end loop;
  1354.   end Multiple_Accept;
  1355.  
  1356.  
  1357. begin
  1358.   NEW_LINE (2);
  1359.   PUT_LINE ("SINGLE ACCEPT BODIES");
  1360.   PUT_LINE ("In the case where a task entry has a single accept body there");
  1361.   PUT_LINE ("is no need for the indirect referencing that may be used when");
  1362.   PUT_LINE ("a single entry has multiple accept bodies.");
  1363.   PUT_LINE ("This test checks to see if calls to entrys that have a ");
  1364.   PUT_LINE ("single accept body are more efficient than when multiple ");
  1365.   PUT_LINE ("accept bodies are used.  The single accept body is the ");
  1366.   PUT_LINE ("overhead item and the multiple accept body is the tested item.");
  1367.   PUT_LINE ("If the net cpu is negative or near zero, it can be assumed ");
  1368.   PUT_LINE ("that the optimization is not done.");
  1369.   NEW_LINE;
  1370.  
  1371.   declare
  1372.     procedure Send_To_Single (Iterations : in NATURAL) is
  1373.     begin
  1374.       for J in 1..Iterations loop
  1375.         Single_Accept.Take_Item (Continue_Item);
  1376.       end loop;
  1377.     end Send_To_Single;
  1378.  
  1379.     procedure Send_To_Multiple (Iterations : in NATURAL) is
  1380.     begin
  1381.       for J in 1..Iterations loop
  1382.         Multiple_Accept.Take_Item (Continue_Item);
  1383.       end loop;
  1384.     end Send_To_Multiple;
  1385.  
  1386.     package Accept_Pkg is new Benchmark
  1387.             (Overhead => Send_To_Single,
  1388.              Item_Of_Interest => Send_To_Multiple);
  1389.  
  1390.   begin
  1391.     Accept_Pkg.Timer;
  1392.     Single_Accept.Stop;   -- kill off the tasks
  1393.     Multiple_Accept.Stop;
  1394.   end;
  1395. end Time_Single_Accept_Body;
  1396. pragma PAGE;
  1397.  
  1398. begin  -- Do_Test
  1399.   PUT_LINE ("               Task Optimizations");
  1400.   NEW_LINE;
  1401.   PUT_LINE ("This test determines if the implementation optimizes various");
  1402.   PUT_LINE ("special cases of tasking.  The specific optimizations being");
  1403.   PUT_LINE ("tested for are machine independent optimizations that have been");
  1404.   PUT_LINE ("discussed in the Ada literature. For each specific optimization");
  1405.   PUT_LINE ("the general case and the special case is timed.");
  1406.   PUT_LINE ("If the special case is significantly");
  1407.   PUT_LINE ("faster than the general case then it is assumed that the");
  1408.   PUT_LINE ("optimization technique is employed.");
  1409.  
  1410.   Time_Monitor;
  1411.   Time_Single_Accept_Body;
  1412.  
  1413.  
  1414. exception
  1415.   when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  1416.   when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  1417.   when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  1418.   when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  1419.   when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  1420.   when others           => PUT_LINE ("*** test aborted due to exception");
  1421.  
  1422. end Do_Test;
  1423. end Part3;
  1424. ::::::::::
  1425. part3spec.ada
  1426. ::::::::::
  1427. ---- test section 3
  1428.  
  1429. package Part3 is
  1430.   Title : constant STRING := "task optimization";
  1431.   procedure Do_Test;
  1432. end Part3;
  1433. ::::::::::
  1434. part4.ada
  1435. ::::::::::
  1436. ---------- test section 4  -- exception propagation
  1437. with TEXT_IO, Benchmark;
  1438. use  TEXT_IO;
  1439. package body Part4 is
  1440.  
  1441. procedure Do_Test is
  1442.  
  1443. procedure Time_Simple_Exception is
  1444. begin
  1445.   NEW_LINE (2);
  1446.   PUT_LINE ("EXCEPTION IN BLOCK");
  1447.   PUT_LINE ("In this test an exception is raised and handled in the same");
  1448.   PUT_LINE ("block.  The user defined exception is declared local to the");
  1449.   PUT_LINE ("block where it is raised.  The same block is timed without");
  1450.   PUT_LINE ("the exception being raised so the exception handling time can");
  1451.   PUT_LINE ("be determined.");
  1452.  
  1453.   declare 
  1454.     procedure Do_Raise (Iterations : in NATURAL) is
  1455.     begin
  1456.       for J in 1..Iterations loop
  1457.         declare
  1458.           Exc : exception;
  1459.         begin
  1460.           raise Exc;
  1461.           PUT_LINE ("ERROR: exception not raised as it should.");
  1462.           raise PROGRAM_ERROR;
  1463.         exception
  1464.           when Exc =>
  1465.                null;
  1466.         end;
  1467.       end loop;
  1468.     end Do_Raise;
  1469.  
  1470.     procedure Dont_Raise (Iterations : in NATURAL) is
  1471.     begin
  1472.       for J in 1..Iterations loop
  1473.         declare
  1474.           Exc : exception;
  1475.         begin
  1476.           null;
  1477.         exception
  1478.           when Exc =>
  1479.             PUT_LINE ("ERROR: exception improperly raised.");
  1480.         end;
  1481.       end loop;
  1482.     end Dont_Raise;
  1483.  
  1484.     package Simple_Exception_Pkg is new Benchmark
  1485.             (Overhead => Dont_Raise,
  1486.              Item_Of_Interest => Do_Raise);
  1487.  
  1488.   begin
  1489.     Simple_Exception_Pkg.Timer;
  1490.   end;
  1491. end Time_Simple_Exception;
  1492. pragma PAGE;
  1493.  
  1494. procedure Time_Procedure_Exception is
  1495.   Exc         : exception;
  1496.  
  1497.     -- raise Exc if the parameter is true otherwise do nothing
  1498.   procedure Raise_Exc (Do_It : in BOOLEAN) is
  1499.   begin
  1500.     if Do_It then
  1501.       raise Exc;
  1502.     end if;
  1503.  
  1504.     if Do_It then  -- make sure the exception was raised
  1505.       PUT_LINE ("ERROR: exception not properly raised.");
  1506.       raise PROGRAM_ERROR;
  1507.     end if;
  1508.   end Raise_Exc;
  1509.  
  1510. begin
  1511.   NEW_LINE (2);
  1512.   PUT_LINE ("EXCEPTION WITHIN PROCEDURE");
  1513.   PUT_LINE ("In this test an exception is raised in a procedure and");
  1514.   PUT_LINE ("handled by the caller. The same procedure call is timed without");
  1515.   PUT_LINE ("the exception being raised so the exception handling time can");
  1516.   PUT_LINE ("be determined.");
  1517.  
  1518.   declare
  1519.     procedure Do_Raise (Iterations : in NATURAL) is
  1520.     begin
  1521.       for J in 1..Iterations loop
  1522.         begin
  1523.           Raise_Exc (TRUE);
  1524.         exception -- handle exception raised by the procedure
  1525.           when Exc =>
  1526.                 null;
  1527.         end;
  1528.       end loop;
  1529.     end Do_Raise;
  1530.  
  1531.     procedure Dont_Raise (Iterations : in NATURAL) is
  1532.     begin
  1533.       for J in 1..Iterations loop
  1534.         begin
  1535.           Raise_Exc (FALSE);
  1536.         exception
  1537.           when Exc =>
  1538.             PUT_LINE ("ERROR: exception improperly raised.");
  1539.         end;
  1540.       end loop;
  1541.     end Dont_Raise;
  1542.  
  1543.     package Procedure_Exception_Pkg is new Benchmark
  1544.             (Overhead => Dont_Raise,
  1545.              Item_Of_Interest => Do_Raise);
  1546.  
  1547.   begin
  1548.     Procedure_Exception_Pkg.Timer;
  1549.   end;
  1550. end Time_Procedure_Exception;
  1551. pragma PAGE;
  1552.  
  1553. procedure Time_Task_Propagation is
  1554.   Exc         : exception;
  1555.  
  1556.   task Some_Task is
  1557.     entry Raise_Exc (Do_It : in BOOLEAN);
  1558.   end Some_Task;
  1559.  
  1560.   task body Some_Task is
  1561.   begin
  1562.     loop
  1563.       begin
  1564.         select
  1565.           accept Raise_Exc (Do_It : in BOOLEAN) do
  1566.             -- raise Exc if the parameter is true otherwise do nothing
  1567.             if Do_It then
  1568.               raise Exc;
  1569.             end if;
  1570.   
  1571.             if Do_It then  -- make sure the exception was raised
  1572.               PUT_LINE ("ERROR: exception not properly raised.");
  1573.               raise PROGRAM_ERROR;
  1574.             end if;
  1575.           end Raise_Exc;
  1576.         or 
  1577.           terminate;
  1578.         end select;
  1579.       exception
  1580.         when Exc => null;
  1581.       end;
  1582.     end loop;
  1583.   end Some_Task;
  1584.  
  1585. begin
  1586.   NEW_LINE (2);
  1587.   PUT_LINE ("EXCEPTION IN ENTRY");
  1588.   PUT_LINE ("In this test an exception is raised during a rendezvous.");
  1589.   PUT_LINE ("The exception is handled in both the calling environment and");
  1590.   PUT_LINE ("in the task.  The same entry is timed without");
  1591.   PUT_LINE ("the exception being raised so the exception handling time can");
  1592.   PUT_LINE ("be determined.");
  1593.  
  1594.   declare
  1595.     procedure Do_Raise (Iterations : in NATURAL) is
  1596.     begin
  1597.       for J in 1..Iterations loop
  1598.         begin
  1599.           Some_Task.Raise_Exc (TRUE);
  1600.         exception -- handle exception raised by the procedure
  1601.           when Exc =>
  1602.                 null;
  1603.         end;
  1604.       end loop;
  1605.     end Do_Raise;
  1606.  
  1607.     procedure Dont_Raise (Iterations : in NATURAL) is
  1608.     begin
  1609.       for J in 1..Iterations loop
  1610.         begin
  1611.           Some_Task.Raise_Exc (FALSE);
  1612.         exception
  1613.           when Exc =>
  1614.             PUT_LINE ("ERROR: exception improperly raised.");
  1615.         end;
  1616.       end loop;
  1617.     end Dont_Raise;
  1618.  
  1619.     package Task_Exception_Pkg is new Benchmark
  1620.             (Overhead => Dont_Raise,
  1621.              Item_Of_Interest => Do_Raise);
  1622.  
  1623.   begin
  1624.     Task_Exception_Pkg.Timer;
  1625.   end;
  1626. end Time_Task_Propagation;
  1627. pragma PAGE;
  1628.  
  1629. begin  -- Do_Test
  1630.   PUT_LINE ("               Exception Propagation");
  1631.   NEW_LINE;
  1632.   PUT_LINE ("This test times exception propagation in various contexts");
  1633.   PUT_LINE ("including propagating an exception to a calling task during a");
  1634.   PUT_LINE ("rendezvous.");
  1635.  
  1636.   Time_Simple_Exception;
  1637.   Time_Procedure_Exception;
  1638.   Time_Task_Propagation;
  1639.  
  1640. exception
  1641.   when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  1642.   when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  1643.   when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  1644.   when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  1645.   when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  1646.   when others           => PUT_LINE ("*** test aborted due to exception");
  1647. end Do_Test;
  1648. end Part4;
  1649. ::::::::::
  1650. part4spec.ada
  1651. ::::::::::
  1652. ---- test section 4 - exception propagation
  1653.  
  1654. package Part4 is
  1655.   Title : constant STRING := "exception propagation";
  1656.   procedure Do_Test;
  1657. end Part4;
  1658. ::::::::::
  1659. part5.ada
  1660. ::::::::::
  1661. --- test section 5  --  task interaction
  1662. with TEXT_IO, Benchmark;
  1663. use  TEXT_IO;
  1664. package body Part5 is
  1665.  
  1666.   -- define the continue and terminate conditions for the tasks
  1667.   Continue_Item : constant := 1;
  1668.   Terminate_Item : constant := -1;
  1669.  
  1670.   -- task types that are common to several tests
  1671.  
  1672.   task type Called_Consumer_Type_1 is
  1673.         -- consumer is to take items until 
  1674.         -- a value of Terminate_Item is accepted.
  1675.     entry Take_Item (Item : in INTEGER);
  1676.   end Called_Consumer_Type_1;
  1677.  
  1678.  
  1679.   task type Called_Consumer_Type_2 is
  1680.         -- consumer is to take items until 
  1681.         -- a value of Terminate_Item is accepted.
  1682.         -- However, enabling takes must be done first.
  1683.     entry Take_Item (Item : in INTEGER);
  1684.     entry Enable_Takes;
  1685.   end Called_Consumer_Type_2;
  1686.  
  1687.  
  1688.   task body Called_Consumer_Type_1 is
  1689.     Item : INTEGER;
  1690.   begin
  1691.     loop   
  1692.       accept Take_Item (Item : in INTEGER) do
  1693.         Called_Consumer_Type_1.Item := Item;
  1694.       end Take_Item;
  1695.  
  1696.       exit when Item = Terminate_Item;
  1697.  
  1698.     end loop;
  1699.   end Called_Consumer_Type_1;
  1700.  
  1701.   task body Called_Consumer_Type_2 is
  1702.     Item : INTEGER;
  1703.   begin
  1704.     accept Enable_Takes;
  1705.     loop   
  1706.       accept Take_Item (Item : in INTEGER) do
  1707.         Called_Consumer_Type_2.Item := Item;
  1708.       end Take_Item;
  1709.  
  1710.       exit when Item = Terminate_Item;
  1711.  
  1712.     end loop;
  1713.   end Called_Consumer_Type_2;
  1714. pragma PAGE;
  1715.  
  1716. procedure Do_Test is
  1717.  
  1718. procedure Time_Procedure_Calls is
  1719.   Finished    : BOOLEAN := FALSE;
  1720.  
  1721.   procedure Take_Number (Num : in INTEGER) is
  1722.   begin
  1723.     -- note that Num is never 0.  The conditional recursion is to help
  1724.     -- prevent the compiler from making this procedure implicitly inline.
  1725.     if Num <= 0 then
  1726.        Take_Number (Num + 1);
  1727.     else
  1728.       Finished := Num = 1;
  1729.     end if;
  1730.   end Take_Number;
  1731.  
  1732.   procedure Give_Number (Iterations : in NATURAL) is
  1733.   begin
  1734.     for J in 1..Iterations loop
  1735.       Take_Number (1);
  1736.     end loop;
  1737.   end Give_Number;
  1738.  
  1739. begin
  1740.   NEW_LINE (2);
  1741.   PUT_LINE ("PROCEDURE CALLING");
  1742.   PUT_LINE ("In this test the time to do a procedure call is measured");
  1743.   PUT_LINE ("so it can be compared to a task entry call.  The procedure");
  1744.   PUT_LINE ("contains a minimum amount of code - just enough to keep a");
  1745.   PUT_LINE ("compiler from thinking it can be eliminated.");
  1746.   NEW_LINE;
  1747.  
  1748.   declare
  1749.     package Procedure_Pkg is new Benchmark
  1750.             (Item_Of_Interest => Give_Number);
  1751.   begin
  1752.     Procedure_Pkg.Timer;
  1753.   end;
  1754.  
  1755. exception
  1756.   when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  1757.   when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  1758.   when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  1759.   when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  1760.   when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  1761.   when others           => PUT_LINE ("*** test aborted due to exception");
  1762. end Time_Procedure_Calls;
  1763. pragma PAGE;
  1764.  
  1765. procedure Time_Conditional_Entry is
  1766.   Enabled_Task   : Called_Consumer_Type_1;
  1767.   Disabled_Task  : Called_Consumer_Type_2;
  1768.   Not_Accepted_Err,
  1769.   Accepted_Err : INTEGER := 0;
  1770.  
  1771.   procedure Not_Accepted (Iterations : in NATURAL) is
  1772.   begin
  1773.     for J in 1..Iterations-1 loop  -- -1 to account for Enable call
  1774.       select
  1775.         Disabled_Task.Take_Item (Continue_Item);
  1776.         Not_Accepted_Err := Not_Accepted_Err + 1;
  1777.       else
  1778.         null;
  1779.       end select;
  1780.     end loop;
  1781.   end Not_Accepted;
  1782.  
  1783.   procedure Accepted (Iterations : in NATURAL) is
  1784.   begin
  1785.     for J in 1..Iterations-1 loop  -- -1 to account for Enable call
  1786.       select
  1787.         Enabled_Task.Take_Item (Continue_Item);
  1788.       else
  1789.         Accepted_Err := Accepted_Err + 1;
  1790.       end select;
  1791.     end loop;
  1792.   end Accepted;
  1793.  
  1794. begin
  1795.   NEW_LINE (2);
  1796.   PUT_LINE ("CONDITIONAL ENTRY");
  1797.   PUT_LINE ("In this test the main task calls a consumer task with a");
  1798.   PUT_LINE ("conditional entry call.  The test tries calls that are not");
  1799.   PUT_LINE ("accepted then tries calls that are accepted.");
  1800.   PUT_LINE ("Since the consumer is the same type of consumer used in the");
  1801.   PUT_LINE ("other producer/consumer tests these results can be compared");
  1802.   PUT_LINE ("to the simple producer/consumer test.");
  1803.   NEW_LINE;
  1804.                                                                    
  1805.   declare
  1806.     package Conditional_Pkg is new Benchmark
  1807.             (Overhead => Not_Accepted,
  1808.              Item_Of_Interest => Accepted);
  1809.   begin
  1810.     Conditional_Pkg.Timer;
  1811.     Enabled_Task.Take_Item (Terminate_Item);  -- kill off the tasks
  1812.     Disabled_Task.Enable_Takes;
  1813.     Disabled_Task.Take_Item (Terminate_Item);  
  1814.   end;
  1815.  
  1816. exception
  1817.   when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  1818.   when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  1819.   when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  1820.   when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  1821.   when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  1822.   when others           => PUT_LINE ("*** test aborted due to exception");
  1823. end Time_Conditional_Entry;
  1824. pragma PAGE;
  1825.  
  1826. procedure Time_Timed_Entry is
  1827.   Enabled_Task   : Called_Consumer_Type_1;
  1828.   Disabled_Task   : Called_Consumer_Type_2;
  1829.   Not_Accepted_Err,
  1830.   Accepted_Err : INTEGER := 0;
  1831.  
  1832.   procedure Not_Accepted (Iterations : in NATURAL) is
  1833.   begin
  1834.     for J in 1..Iterations loop
  1835.       select
  1836.         Disabled_Task.Take_Item (Continue_Item);
  1837.         Not_Accepted_Err := Not_Accepted_Err + 1;
  1838.       or
  1839.         delay 0.0;
  1840.       end select;
  1841.     end loop;
  1842.   end Not_Accepted;
  1843.  
  1844.   procedure Accepted (Iterations : in NATURAL) is
  1845.   begin
  1846.     for J in 1..Iterations loop
  1847.       select
  1848.         Enabled_Task.Take_Item (Continue_Item);
  1849.       or
  1850.         delay 0.0;
  1851.         Accepted_Err := Accepted_Err + 1;
  1852.       end select;
  1853.     end loop;
  1854.   end Accepted;
  1855.  
  1856. begin
  1857.   NEW_LINE (2);
  1858.   PUT_LINE ("TIMED ENTRY");
  1859.   PUT_LINE ("In this test the main task calls a consumer task with a");
  1860.   PUT_LINE ("timed entry call with a time limit of 0.0.  The test tries");
  1861.   PUT_LINE ("calls that are not accepted then tries calls that are accepted.");
  1862.   PUT_LINE ("Since the consumer is the same type of consumer used in the");
  1863.   PUT_LINE ("other producer/consumer tests these results can be compared");
  1864.   PUT_LINE ("to the simple producer/consumer test.");
  1865.   NEW_LINE;
  1866.  
  1867.   declare
  1868.     package Timed_Entry_Pkg is new Benchmark
  1869.             (Overhead => Not_Accepted,
  1870.              Item_Of_Interest => Accepted);
  1871.   begin
  1872.     Timed_Entry_Pkg.Timer;
  1873.     Enabled_Task.Take_Item (Terminate_Item);  -- kill off the tasks
  1874.     Disabled_Task.Enable_Takes;
  1875.     Disabled_Task.Take_Item (Terminate_Item);
  1876.   end;
  1877.  
  1878. exception
  1879.   when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  1880.   when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  1881.   when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  1882.   when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  1883.   when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  1884.   when others           => PUT_LINE ("*** test aborted due to exception");
  1885. end Time_Timed_Entry;
  1886. pragma PAGE;
  1887.  
  1888. procedure Time_Family is
  1889.   
  1890.   type Family is range 1 .. 10;  -- size of entry family
  1891.   Family_Member : Family := 3;   -- this is the one we will use
  1892.  
  1893.   task Some_Task is
  1894.         -- consumer is to take items until 
  1895.         -- a value of Terminat_Item is accepted.
  1896.     entry Take_Item (Family)(Item : in INTEGER);
  1897.   end Some_Task;
  1898.  
  1899.  
  1900.   task body Some_Task is
  1901.     Item : INTEGER;
  1902.   begin
  1903.     loop
  1904.       accept Take_Item (Family_Member) (Item : in INTEGER) do
  1905.         Some_Task.Item := Item;
  1906.       end Take_Item;
  1907.  
  1908.       exit when Item = Terminate_Item;
  1909.  
  1910.     end loop;
  1911.   end Some_Task;
  1912.  
  1913.  
  1914. begin
  1915.   NEW_LINE (2);
  1916.   PUT_LINE ("FAMILY OF ENTRIES");
  1917.   PUT_LINE ("This test is similar to the simple producer/consumer (SIMPLE PC)");
  1918.   PUT_LINE ("in that the main task produces integer values that are consumed");
  1919.   PUT_LINE ("by a consumer task.  The difference is that the consumer task");
  1920.   PUT_LINE ("uses a family of entries instead of a single entry.");
  1921.   NEW_LINE;
  1922.  
  1923.   declare
  1924.     procedure Send_Item (Iterations : in NATURAL) is
  1925.     begin
  1926.       for J in 1..Iterations Loop
  1927.         Some_Task.Take_Item (Family_Member) (Continue_Item);
  1928.       end loop;
  1929.     end Send_Item;
  1930.  
  1931.     package Family_Pkg is new Benchmark
  1932.             (Item_Of_Interest => Send_Item);
  1933.  
  1934.   begin
  1935.     Family_Pkg.Timer;
  1936.     Some_Task.Take_Item (Family_Member) (Terminate_Item);
  1937.   end;
  1938.  
  1939. exception
  1940.   when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  1941.   when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  1942.   when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  1943.   when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  1944.   when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  1945.   when others           => PUT_LINE ("*** test aborted due to exception");
  1946. end Time_Family;
  1947. pragma PAGE;
  1948.  
  1949. procedure Time_Simple_Sync is
  1950.   task Sync is
  1951.     entry Pass;
  1952.   end Sync;
  1953.  
  1954.   task body Sync is
  1955.   begin
  1956.     loop
  1957.       accept Pass;
  1958.     end loop;
  1959.   end Sync;
  1960.  
  1961. begin
  1962.   NEW_LINE (2);
  1963.   PUT_LINE ("SIMPLE SYNCHRONIZATION");
  1964.   PUT_LINE ("This test times the use of a simple synchronization task entry.");
  1965.   PUT_LINE ("In this type of task interaction no parameters are passed to the");
  1966.   PUT_LINE ("task entry and there is no body for the accept. The called task");
  1967.   PUT_LINE ("loops on an unconditional accept.");
  1968.   NEW_LINE;
  1969.  
  1970.   declare
  1971.     procedure Call_Sync (Iterations : in NATURAL) is
  1972.     begin
  1973.       for J in 1..Iterations loop
  1974.         Sync.Pass;
  1975.       end loop;
  1976.     end Call_Sync;
  1977.  
  1978.     package Simple_Sync_Pkg is new Benchmark
  1979.             (Item_Of_Interest => Call_Sync);
  1980.  
  1981.   begin
  1982.     Simple_Sync_Pkg.Timer;
  1983.     abort Sync;   -- kill off the task
  1984.   end;
  1985.  
  1986. exception
  1987.   when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  1988.   when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  1989.   when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  1990.   when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  1991.   when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  1992.   when others           => PUT_LINE ("*** test aborted due to exception");
  1993. end Time_Simple_Sync;
  1994. pragma PAGE;
  1995.  
  1996. procedure Time_Sync_With_Term is
  1997.   task Sync is
  1998.     entry Pass;
  1999.   end Sync;
  2000.  
  2001.   task body Sync is
  2002.   begin
  2003.     loop
  2004.       select
  2005.         accept Pass;
  2006.       or
  2007.         terminate;
  2008.       end select;
  2009.     end loop;
  2010.   end Sync;
  2011.  
  2012. begin
  2013.   NEW_LINE (2);
  2014.   PUT_LINE ("SYNCHRONIZATION WITH TERMINATION");
  2015.   PUT_LINE ("This test times the use of a simple synchronization task entry.");
  2016.   PUT_LINE ("In this type of task interaction no parameters are passed to the");
  2017.   PUT_LINE ("task entry and there is no body for the accept. The called task");
  2018.   PUT_LINE ("loops on an select statement containing an accept and a");
  2019.   PUT_LINE ("terminate alternative.");
  2020.   NEW_LINE;
  2021.  
  2022.   declare
  2023.     procedure Call_Sync (Iterations : in NATURAL) is
  2024.     begin
  2025.       for J in 1..Iterations loop
  2026.         Sync.Pass;
  2027.       end loop;
  2028.     end Call_Sync;
  2029.  
  2030.     package Sync_Term_Pkg is new Benchmark
  2031.             (Item_Of_Interest => Call_Sync);
  2032.  
  2033.   begin
  2034.     Sync_Term_Pkg.Timer;
  2035.   end;
  2036.  
  2037. exception
  2038.   when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  2039.   when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  2040.   when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  2041.   when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  2042.   when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  2043.   when others           => PUT_LINE ("*** test aborted due to exception");
  2044. end Time_Sync_With_Term;
  2045. pragma PAGE;
  2046.  
  2047. procedure Time_Term_Option is
  2048.   Open_Terminate : BOOLEAN := FALSE;
  2049.  
  2050.   task Sync is
  2051.     entry Pass;
  2052.   end Sync;
  2053.  
  2054.   task body Sync is
  2055.   begin
  2056.     loop
  2057.       select
  2058.         accept Pass;
  2059.       or
  2060.         when Open_Terminate =>
  2061.         terminate;
  2062.       end select;
  2063.     end loop;
  2064.   end Sync;
  2065.  
  2066. begin
  2067.   NEW_LINE (2);
  2068.   PUT_LINE ("TERMINATE OPTION");
  2069.   PUT_LINE ("This test times the use of a simple synchronization task entry");
  2070.   PUT_LINE ("both without and with a terminate option.  The overhead test");
  2071.   PUT_LINE ("is for the time without the terminate option.");
  2072.   PUT_LINE ("In this type of task interaction no parameters are passed to the");
  2073.   PUT_LINE ("task entry and there is no body for the accept. The called task");
  2074.   PUT_LINE ("loops on an select statement containing an accept and a");
  2075.   PUT_LINE ("conditional terminate alternative.");
  2076.   NEW_LINE;
  2077.  
  2078.   declare
  2079.     procedure Closed_Terminate (Iterations : in NATURAL) is
  2080.     begin
  2081.       for J in 1..Iterations loop
  2082.         Sync.Pass;
  2083.       end loop;
  2084.     end Closed_Terminate;
  2085.  
  2086.     procedure Opened_Terminate (Iterations : in NATURAL) is
  2087.     begin         
  2088.       Open_Terminate := TRUE;
  2089.       for J in 1..Iterations loop
  2090.         Sync.Pass;
  2091.       end loop;
  2092.     end Opened_Terminate;
  2093.  
  2094.     package Term_Option_Pkg is new Benchmark
  2095.             (Overhead => Closed_Terminate,
  2096.              Item_Of_Interest => Opened_Terminate);
  2097.  
  2098.   begin
  2099.     Term_Option_Pkg.Timer;
  2100.   end;
  2101.  
  2102. exception
  2103.   when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  2104.   when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  2105.   when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  2106.   when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  2107.   when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  2108.   when others           => PUT_LINE ("*** test aborted due to exception");
  2109. end Time_Term_Option;
  2110. pragma PAGE;
  2111.  
  2112. begin
  2113.   PUT_LINE ("               Task Interaction");
  2114.   NEW_LINE;
  2115.   PUT_LINE ("This test times various task interactions in order to determine");
  2116.   PUT_LINE ("their relative cost. These tests are related to the task");
  2117.   PUT_LINE ("communication tests and in many cases the output should be");
  2118.   PUT_LINE ("compared to those tests (see each test for details).");
  2119.  
  2120.   Time_Procedure_Calls;
  2121.   Time_Conditional_Entry;
  2122.   Time_Timed_Entry;
  2123.   Time_Family;
  2124.   Time_Simple_Sync;
  2125.   Time_Sync_With_Term;
  2126.   Time_Term_Option;
  2127.  
  2128. exception
  2129.   when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  2130.   when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  2131.   when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  2132.   when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  2133.   when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  2134.   when others           => PUT_LINE ("*** test aborted due to exception");
  2135.  
  2136. end Do_Test;
  2137.  
  2138. end Part5;
  2139. ::::::::::
  2140. part5spec.ada
  2141. ::::::::::
  2142. ---- test section 5
  2143.  
  2144. package Part5 is
  2145.   Title : constant STRING := "task interaction";
  2146.   procedure Do_Test;
  2147. end Part5;
  2148. ::::::::::
  2149. timer_body.ada
  2150. ::::::::::
  2151. --++
  2152. -- FACILITY:
  2153. --      Benchmark Driver
  2154. --
  2155. -- ABSTRACT:
  2156. --      This generic procedure provides the services necessary to time
  2157. --      a given operaion and report on the performance.
  2158. --
  2159. -- AUTHOR:
  2160. --      Tom Burger
  2161. --
  2162. -- MODIFICATION HISTORY:
  2163. ----
  2164.  
  2165. with TEXT_IO;  use TEXT_IO;
  2166. with Cpu;      use Cpu;
  2167. with Misc_Benchmark; use Misc_Benchmark;
  2168. with SYSTEM;                        -- for SYSTEM.TICK
  2169. package body Benchmark is
  2170.  
  2171. Iterations : NATURAL;     -- how many iterations to run the test
  2172.  
  2173. procedure Determine_Necessary_Iterations is
  2174.   -- If a specified number of iterations is given then use this number;
  2175.   -- otherwise, determine the best number of iterations by starting at 1 and
  2176.   -- keep doubling the number of iterations until the time required for
  2177.   -- the item of interest is at least 100 times the clock resolution.
  2178.   -- The result of this procedure is left in the variable Iterations.
  2179.  
  2180.   Minimum_Time : DURATION;
  2181.   Start_Cpu,
  2182.   Stop_Cpu   : Cpu.Time;
  2183. begin
  2184.   if Number_Of_Iterations /= 0 then
  2185.     Iterations := Number_Of_Iterations;
  2186.     return;
  2187.   end if;
  2188.  
  2189.   if SYSTEM.TICK > DURATION'SMALL then  
  2190.     Minimum_Time := 100 * SYSTEM.TICK;
  2191.   else
  2192.     Minimum_Time := 100 * DURATION'SMALL;
  2193.   end if;
  2194.  
  2195.   Iterations := 1;
  2196.   loop
  2197.     Start_Cpu := Cpu.Clock;
  2198.     Item_Of_Interest (Iterations);
  2199.     Stop_Cpu := Cpu.Clock;
  2200.  
  2201.     exit when Stop_Cpu - Start_Cpu >= Minimum_Time;
  2202.  
  2203.       -- check for overflow condition
  2204.     if Iterations = NATURAL'LAST / 2 + 1 then
  2205.       Iterations := NATURAL'LAST;
  2206.       exit;
  2207.     end if;
  2208.     Iterations := Iterations * 2;
  2209.   end loop;
  2210. end Determine_Necessary_Iterations;
  2211.  
  2212.   
  2213. procedure Do_Timing_Run (Results : out Results_Type;
  2214.                          Overhead_Results : out Results_Type) is
  2215.  
  2216.   Start,
  2217.   Stop   : Raw_Time_Info;          -- Contains Elapsed and Cpu Times
  2218.  
  2219. begin               
  2220.   for Repetitions in 1..Test_Repetitions loop
  2221.     Get_Both_Times (Start);
  2222.     Overhead (Iterations);  -- run the overhead routine
  2223.     Get_Both_Times (Stop);
  2224.     Overhead_Results (Repetitions) := Stop - Start;
  2225.  
  2226.     Get_Both_Times (Start);
  2227.     Item_Of_Interest (Iterations);  -- run the item of interest routine
  2228.     Get_Both_Times (Stop);
  2229.     Results (Repetitions) := Stop - Start;
  2230.   end loop;
  2231. end Do_Timing_Run;
  2232.  
  2233.  
  2234. procedure Timer is
  2235.   Results : Results_Type (1..Test_Repetitions);
  2236.   Overhead_Results : Results_Type (1..Test_Repetitions);
  2237. begin 
  2238.   Determine_Necessary_Iterations;
  2239.   Do_Timing_Run (Results, Overhead_Results);
  2240.   Print_Results (Results, Overhead_Results, Test_Repetitions, Iterations);
  2241. end Timer;
  2242.  
  2243. end Benchmark;
  2244. ::::::::::
  2245. timer_spec.ada
  2246. ::::::::::
  2247. --++
  2248. -- FACILITY:
  2249. --      Benchmark Driver
  2250. --
  2251. -- ABSTRACT:
  2252. --      This generic procedure provides the services necessary to time
  2253. --      a given operaion and report on the performance.
  2254. --
  2255. -- AUTHOR:
  2256. --      Tom Burger
  2257. --
  2258. -- MODIFICATION HISTORY:
  2259. ---- 
  2260. with Misc_Benchmark; use Misc_Benchmark;
  2261. generic
  2262.     Test_Repetitions     : NATURAL := 5;  -- run the entire test this many times
  2263.                                           -- to check for variability in results
  2264.     Number_of_Iterations : NATURAL := 0;  -- 0 implies the number of iterations
  2265.                                           -- is to be determined.
  2266.  
  2267.     with procedure Overhead (Iterations : in NATURAL) is Default_Overhead;
  2268.     with procedure Item_Of_Interest (Iterations : in NATURAL);
  2269.  
  2270. package Benchmark is
  2271.   procedure Timer;
  2272. end Benchmark;
  2273.  
  2274. ::::::::::
  2275. wall_clock_cpu_body.ada
  2276. ::::::::::
  2277. --  this is a machine independent dummy package for reporting the amount of
  2278. --  CPU time used. It actually reports the elapsed time
  2279. with CALENDAR;  use CALENDAR;
  2280. with TEXT_IO;   use TEXT_IO;
  2281. package body Cpu is
  2282.   Base_Time : constant CALENDAR.TIME := CALENDAR.CLOCK;
  2283.  
  2284. function Clock return Time is
  2285.   Now : constant CALENDAR.TIME := CALENDAR.CLOCK;
  2286. begin
  2287.   return Cpu.Time (Now - Base_Time);
  2288. end Clock;
  2289.  
  2290. function "-" (Stop_Time, Start_Time : Time) return DURATION is
  2291. begin
  2292.   return DURATION (DURATION (Stop_Time) - DURATION (Start_Time));
  2293. end "-";
  2294.  
  2295. begin
  2296.   PUT_LINE ("NOTE: CPU Time is actually ELAPSED time!!!");
  2297. end Cpu;
  2298.  
  2299.