home *** CD-ROM | disk | FTP | other *** search
/ Programmer's ROM - The Computer Language Library / programmersrom.iso / ada / test / tasking.doc < prev    next >
Encoding:
Text File  |  1988-05-03  |  107.5 KB  |  3,234 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.                              Ada* Benchmark Suite
  15.  
  16.                                Tasking Section
  17.  
  18.                                  Version 1.0
  19.  
  20.  
  21.  
  22.  
  23.  
  24.                                 29 August 1986
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.                            Hughes Aircraft Company
  36.                              Ground Systems Group
  37.                         Software Engineering Division
  38.                   San Diego Software Engineering Laboratory
  39.                    Command and Control Software Department
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50.     * Ada is a registered trademark of the  U.S.   Government  (Ada  Joint
  51.     Program Office).
  52.     Ada Tasking Benchmark Version 1.0
  53.  
  54.  
  55.                                        CONTENTS
  56.  
  57.             1       PURPOSE  . . . . . . . . . . . . . . . . . . . . . . 1
  58.             2       TASKING BENCHMARK  . . . . . . . . . . . . . . . . . 1
  59.             2.1       Task Activation/Termination Test Category  . . . . 1
  60.             2.1.1       Local Array Of Null Task Bodies  . . . . . . . . 1
  61.             2.1.2       Local Array Of Tasks With Terminate Option . . . 2
  62.             2.1.3       Access Type  . . . . . . . . . . . . . . . . . . 2
  63.             2.2       Task Communication Test Category . . . . . . . . . 2
  64.             2.2.1       Simple Producer-Consumer . . . . . . . . . . . . 3
  65.             2.2.2       Selective Wait . . . . . . . . . . . . . . . . . 3
  66.             2.2.3       Producer-Consumer  . . . . . . . . . . . . . . . 3
  67.             2.2.4       Producer-Buffer-Consumer . . . . . . . . . . . . 3
  68.             2.2.5       Producer-Buffer-Transporter-Consumer . . . . . . 4
  69.             2.2.6       Producer-Transporter-Buffer-Transporter-Consumer 4
  70.             2.2.7       Relay  . . . . . . . . . . . . . . . . . . . . . 4
  71.             2.3       Task Optimizations Test Category . . . . . . . . . 5
  72.             2.3.1       Monitor  . . . . . . . . . . . . . . . . . . . . 5
  73.             2.3.2       Single Accept Bodies . . . . . . . . . . . . . . 5
  74.             2.4       Exception Propagation Test Category  . . . . . . . 5
  75.             2.4.1       Exception In A Block . . . . . . . . . . . . . . 6
  76.             2.4.2       Exception In A Procedure . . . . . . . . . . . . 6
  77.             2.4.3       Exception In An Entry  . . . . . . . . . . . . . 6
  78.             2.5       Task Interaction Test Category . . . . . . . . . . 6
  79.             2.5.1       Procedure Calling  . . . . . . . . . . . . . . . 6
  80.             2.5.2       Conditional Entry Call . . . . . . . . . . . . . 7
  81.             2.5.3       Timed Entry Call . . . . . . . . . . . . . . . . 7
  82.             2.5.4       Family Of Entries  . . . . . . . . . . . . . . . 7
  83.             2.5.5       Simple Synchronization . . . . . . . . . . . . . 8
  84.             2.5.6       Synchronization With Termination . . . . . . . . 8
  85.             2.5.7       Terminate Option   . . . . . . . . . . . . . . . 8
  86.             3       TIMING METHODOLOGY . . . . . . . . . . . . . . . . . 8
  87.             3.1       Timing Generic . . . . . . . . . . . . . . . . . . 9
  88.             3.2       Testing Environment  . . . . . . . . . . . . . . . 9
  89.             4       REFERENCES . . . . . . . . . . . . . . . . . . . .  10
  90.  
  91.  
  92.     APPENDIX A      BENCHMARK LISTINGS
  93.  
  94.             A.1     FILE ORGANIZATION  . . . . . . . . . . . . . . . . A-1
  95.             A.2     CPU_SPEC.ADA . . . . . . . . . . . . . . . . . . . A-2
  96.             A.3     CPU_BODY.ADA . . . . . . . . . . . . . . . . . . . A-3
  97.             A.4     MISC_BENCHMARK_SPEC.ADA  . . . . . . . . . . . . . A-5
  98.             A.5     MISC_BENCHMARK_SPEC.ADA  . . . . . . . . . . . . . A-6
  99.             A.6     TIMER_SPEC.ADA . . . . . . . . . . . . . . . . . . A-9
  100.             A.7     TIMER_BODY.ADA . . . . . . . . . . . . . . . . .  A-10
  101.             A.8     WALL_CLOCK_CPU_BODY.ADA  . . . . . . . . . . . .  A-12
  102.             A.9     PART1SPEC.ADA  . . . . . . . . . . . . . . . . .  A-13
  103.             A.10    PART1.ADA  . . . . . . . . . . . . . . . . . . .  A-14
  104.             A.11    PART2SPEC.ADA  . . . . . . . . . . . . . . . . .  A-17
  105.             A.12    PART2.ADA  . . . . . . . . . . . . . . . . . . .  A-18
  106.             A.13    PART3SPEC.ADA  . . . . . . . . . . . . . . . . .  A-31
  107.             A.14    PART3.ADA  . . . . . . . . . . . . . . . . . . .  A-32
  108.     Ada Tasking Benchmark Version 1.0
  109.  
  110.  
  111.             A.15    PART4SPEC.ADA  . . . . . . . . . . . . . . . . .  A-37
  112.             A.16    PART4.ADA  . . . . . . . . . . . . . . . . . . .  A-38
  113.             A.17    PART5SPEC.ADA  . . . . . . . . . . . . . . . . .  A-43
  114.             A.18    PART5.ADA  . . . . . . . . . . . . . . . . . . .  A-44
  115.             A.19    DRIVER.ADA   . . . . . . . . . . . . . . . . . .  A-54
  116.     Ada Tasking Benchmark Version 1.0                               Page 1
  117.  
  118.  
  119.     1  PURPOSE
  120.  
  121.     The Ada Benchmark Suite has been developed to provide a foundation for
  122.     the  performance  evaluation  of  various  Ada  compiler systems.  The
  123.     benchmarks are used to measure compilation speed and  execution  speed
  124.     of the Ada systems.
  125.  
  126.     This report describes the tasking benchmarks contained  in  the  suite
  127.     and  provides  a listing of the benchmarks in Appendix A.  This report
  128.     also describes the timing methodology used to gather measurements.
  129.  
  130.  
  131.  
  132.     2  TASKING BENCHMARK
  133.  
  134.     The use of  the  Ada  tasking  model  incurs  certain  overhead  costs
  135.     associated with, for example, task activation and termination, context
  136.     switching, and synchronization.  There are five general categories  of
  137.     tests,  with each category divided into individually timed tests.  The
  138.     Tasking benchmark  is  1904  source  lines  of  code.   The  following
  139.     paragraphs describe the tasking tests performed.
  140.  
  141.  
  142.  
  143.     2.1  Task Activation/Termination Test Category
  144.  
  145.     Since Ada does not include a real-time executive, task activation  and
  146.     termination  are  not  accomplished  via  programmer-written executive
  147.     service requests.  Task activation and termination in Ada is a part of
  148.     the tasking model semantics, and is perfomed automatically based on an
  149.     elaborate set of  rules  [BAR84,  p.209,  and  GEH84,  p.   45].   The
  150.     follwing  paragraphs  describe  the  task  activation  and termination
  151.     tests.
  152.  
  153.  
  154.  
  155.     2.1.1  Local Array Of Null Task Bodies
  156.  
  157.     Declaring a task within a procedure causes the task  to  be  activated
  158.     each  time  the procedure is called.  The procedure will not return to
  159.     its caller until the task terminates.
  160.  
  161.     In this test an array of tasks is declared  locally  to  a  procedure.
  162.     Both  the  procedure and the task have null bodies.  The length of the
  163.     array is determined by the iteration count (i.e., an iteration of  one
  164.     means  the  array length is one).  Therefore, the timing per iteration
  165.     is the time to activate and terminate one task in the array.
  166.     Ada Tasking Benchmark Version 1.0                               Page 2
  167.  
  168.  
  169.     2.1.2  Local Array Of Tasks With Terminate Option
  170.  
  171.     In this test an array of tasks is declared  locally  to  a  procedure.
  172.     The task uses the terminate option in a select statement to terminate.
  173.     The task is never called.  The length of the array  is  determined  by
  174.     the iteration count.
  175.  
  176.  
  177.  
  178.     2.1.3  Access Type
  179.  
  180.     It is possible to create tasks  dynamically  by  using  an  allocator.
  181.     Tasks created in this fashion are immediately activated.
  182.  
  183.     In this test an access type to a task is used to create  a  series  of
  184.     tasks.    The  timing  per  iteration  includes  both  allocation  and
  185.     deallocation of the task as well as activation and termination.
  186.  
  187.  
  188.  
  189.     2.2  Task Communication Test Category
  190.  
  191.     The  method  used  in  Ada  for  task  communcation  is   called   the
  192.     "rendezvous."  The rendezvous is a synchronous operation and therefore
  193.     limits the amount of asynchronous action between tasks.  It  is  often
  194.     desirable  to  uncouple [NIE86] the task interaction to some extent in
  195.     order  to  allow  more  independence  and  increase  the   amount   of
  196.     concurrency.   Intermediary  tasks  are  often used to accomplish this
  197.     uncoupling.   Intermediary  tasks   are   classified   as   "buffers,"
  198.     "transporters,"   or   "relays"   depending   upon  the  caller/called
  199.     relationships between the tasks.  A "buffer" is a  pure  server  task.
  200.     It  provides  one  entry for storing of items in a buffer, and another
  201.     entry for providing items from the buffer.  A "transporter" is a  pure
  202.     caller.   It  obtains  an item by calling a producer (or intermediary)
  203.     task,  and  "transports"  that  item  by  calling   a   consumer   (or
  204.     intermediary)  task.   A  "relay" is a mixture of a caller and server.
  205.     It obtains an item by calling a producer (or intermediary)  task,  and
  206.     "relays"  that  item when it is called by a consumer (or intermediary)
  207.     task.  (Alternately, a relay may be called by a producer, and  call  a
  208.     consumer).
  209.  
  210.     In addition to  providing  more  independence  between  tasks  (higher
  211.     degree  of  asynchronicity), intermediary tasks are also used to alter
  212.     the caller/called relationships.  Sometimes it is more advantageous to
  213.     be  a  called  task  and  other  times it is more advantageous to be a
  214.     calling task.  The use  of  a  buffer  allows  two  calling  tasks  to
  215.     communicate  while the use of a transporter allows two called tasks to
  216.     communicate.  A relay preserves the caller/called relationships  while
  217.     providing a degree of uncoupling.
  218.  
  219.     The case where one task passes information to another task is called a
  220.     producer-consumer  (PC)  relationship.  The task that is the source of
  221.     the information is called the  producer  and  the  task  that  is  the
  222.     Ada Tasking Benchmark Version 1.0                               Page 3
  223.  
  224.  
  225.     recipient  of  the  information  is  called the consumer.  One or more
  226.     rendezvous are used to pass the information from the producer  to  the
  227.     consumer.  A rendezvous is a rough measure of two Ada context switches
  228.     since the caller is suspended until the rendezvous is  complete.   The
  229.     first  context  switch  is  from the caller to the called task and the
  230.     second context switch is the return to the caller task.
  231.  
  232.     The following paragraphs describe the task communication tests.
  233.  
  234.  
  235.  
  236.     2.2.1  Simple Producer-Consumer
  237.  
  238.     In this test the main procedure  calls  a  consumer  task.   A  simple
  239.     integer  value  is  the  only data transferred and the consumer simply
  240.     loops on the accept.  Task activation/termination time is not included
  241.     in the timing.  An iteration consists of one rendezvous.
  242.  
  243.  
  244.  
  245.     2.2.2  Selective Wait
  246.  
  247.     In this test the main procedure calls a consumer  task  that  has  two
  248.     entries.   A simple integer value is the only data transferred and the
  249.     consumer simply loops on the selective accept.  This test differs from
  250.     the previous test in that the consumer uses a select statement to take
  251.     the entry call where the select has two  open  alternatives.   In  the
  252.     previous case there was no select statement.  An iteration consists of
  253.     one rendezvous.
  254.  
  255.  
  256.  
  257.     2.2.3  Producer-Consumer
  258.  
  259.     In this test  a  producer  task  communicates  with  a  consumer  task
  260.     directly.    This   timing   should   be   similar   to   the   simple
  261.     producer-consumer test.  An iteration consists of one rendezvous.
  262.  
  263.  
  264.  
  265.     2.2.4  Producer-Buffer-Consumer
  266.  
  267.     It is often the case that a producer and a consumer  will  communicate
  268.     via  a  buffer, i.e., producer-buffer-consumer (PBC).  A buffer serves
  269.     to uncouple the producer from the consumer  thus  providing  a  higher
  270.     degree  of  independence.   A  buffer is a task, and therefore its use
  271.     adds some overhead.  Each time a piece of information is  passed  from
  272.     the  producer to the consumer two rendezvous occur - the producer with
  273.     the buffer  and  the  consumer  with  the  buffer.   This  arrangement
  274.     requires  that  both  the  producer  and the consumer be calling tasks
  275.     since a buffer is strictly a called task.
  276.  
  277.     In this test  a  producer  task  communicates  with  a  consumer  task
  278.     Ada Tasking Benchmark Version 1.0                               Page 4
  279.  
  280.  
  281.     indirectly  through  a bounded buffer (buffer size = 2).  An iteration
  282.     consists of two rendezvous.
  283.  
  284.  
  285.  
  286.     2.2.5  Producer-Buffer-Transporter-Consumer
  287.  
  288.     Many times a producer will want to communicate with a consumer  via  a
  289.     buffer,  but  it is undesirable for the consumer to be a calling task.
  290.     For example, the consumer may want to accept requests from any  number
  291.     of  producers  and therefore would want to be a called task.  This can
  292.     be accomplished by having a transporter task take information from the
  293.     buffer     and     pass    it    on    to    the    consumer,    i.e.,
  294.     producer-buffer-transporter-consumer  (PBTC).   This  means  that  two
  295.     intermediary  tasks  are  used  between the producer and the consumer.
  296.     Each time a piece of information is passed from the  producer  to  the
  297.     consumer  three  rendezvous  occur - the producer with the buffer, the
  298.     transporter with the buffer, and the transporter with the consumer.
  299.  
  300.     In this test  a  producer  task  communicates  with  a  consumer  task
  301.     indirectly  through  a  bounded  buffer  (buffer  size  =  2)  with  a
  302.     transporter  between  the  buffer  and  the  consumer.   An  iteration
  303.     consists of three rendezvous.
  304.  
  305.  
  306.  
  307.     2.2.6  Producer-Transporter-Buffer-Transporter-Consumer
  308.  
  309.     In the event that a producer and a consumer wish to communicate via  a
  310.     buffer  and  both  need  to  be called tasks, it is necessary to use a
  311.     transporter  on  each  side  of  the  buffer.   This  results  in  the
  312.     producer-transporter-buffer-transporter-consumer   (PTBTC)   paradigm.
  313.     Each time a piece of information is passed from the  producer  to  the
  314.     consumer  four rendezvous occur - a transporter with the producer, the
  315.     transporter with the buffer, a second transporter with the buffer, and
  316.     the second transporter with the consumer.
  317.  
  318.     In this test  a  producer  task  communicates  with  a  consumer  task
  319.     indirectly  through  a  bounded  buffer  (buffer  size  =  2)  with  a
  320.     transporter for both the producer  and  the  consumer.   An  iteration
  321.     consists of four rendezvous.
  322.  
  323.  
  324.  
  325.     2.2.7  Relay
  326.  
  327.     A relay is an intermediary task that takes information from a producer
  328.     and  passes it on to the consumer.  For each piece of information that
  329.     is passed from the producer to the consumer two rendezvous occur - the
  330.     producer with the relay and the relay with the consumer.
  331.  
  332.     In this test  a  producer  task  communicates  with  a  consumer  task
  333.     indirectly through a relay.  In terms of the task communication model,
  334.     Ada Tasking Benchmark Version 1.0                               Page 5
  335.  
  336.  
  337.     this resembles th PBTC paradigm but in terms of performance it  should
  338.     resemble the PBC test.  An iteration consists of two rendezvous.
  339.  
  340.  
  341.  
  342.     2.3  Task Optimizations Test Category
  343.  
  344.     This test category determines if the implementation optimizes  various
  345.     special cases of tasking.  The specific optimizations being tested for
  346.     are machine independent optimizations that have been discussed in  the
  347.     Ada  literature  [HIL82,  HAB80].   For each specific optimization the
  348.     general case and the special case are timed.  If the special  case  is
  349.     significantly faster than the general case then it is assumed that the
  350.     optimization technique is employed.   An  iteration  consists  of  the
  351.     general  case  time  minus the special case time.  For iteration times
  352.     near zero, it can be assumed that the optimization is not done.
  353.  
  354.  
  355.  
  356.     2.3.1  Monitor
  357.  
  358.     A task  that  contains  no  code  outside  of  the  accept  bodies  is
  359.     considered  to  be a monitor.  It is possible to eliminate such a task
  360.     by protecting the task entries with semaphores.
  361.  
  362.     In this test the main procedure interacts with a monitor  and  with  a
  363.     more  general  task  in  order  to  determine  if this optimization is
  364.     performed.
  365.  
  366.  
  367.  
  368.     2.3.2  Single Accept Bodies
  369.  
  370.     In the case where a task entry has a single accept body  there  is  no
  371.     need for the indirect referencing that may be used when a single entry
  372.     has multiple accept bodies.
  373.  
  374.     This test checks to see if calls to entries that have a single  accept
  375.     body are more efficient than when multiple accept bodies are used.
  376.  
  377.  
  378.  
  379.     2.4  Exception Propagation Test Category
  380.  
  381.     The  raising  of  an  exception  is  the  means  by  which  error  and
  382.     exceptional  conditions  are reported in Ada.  An exception handler is
  383.     used to respond to an exception that has been raised.  Three types  of
  384.     exception  handling are examined here to determine the cost of raising
  385.     and  propagating  an  exception.   Each  test  is  timed  without  the
  386.     exception  being  raised  and  with  the  exception  being raised.  An
  387.     iteration consists of the difference in these times (raised minus  not
  388.     raised).
  389.     Ada Tasking Benchmark Version 1.0                               Page 6
  390.  
  391.  
  392.     2.4.1  Exception In A Block
  393.  
  394.     A block is a statement that may contain declarations,  a  sequence  of
  395.     statements, and an exception handler.  An exception that is raised and
  396.     handled within the same  block  is  the  simplest  form  of  exception
  397.     handling.
  398.  
  399.     In this test an exception is raised and handled  in  the  same  block.
  400.     The  user defined exception is declared local to the block where it is
  401.     raised.
  402.  
  403.  
  404.  
  405.     2.4.2  Exception In A Procedure
  406.  
  407.     If an exception is raised within a procedure that  does  not  have  an
  408.     exception handler for that exception, then the exception is propagated
  409.     to the caller procedure.
  410.  
  411.     In this test an exception is raised in a procedure and handled by  the
  412.     caller.
  413.  
  414.  
  415.  
  416.     2.4.3  Exception In An Entry
  417.  
  418.     If an exception is raised within a rendezvous, then it  is  propagated
  419.     to  the  task  containing  the  accept as well as to the calling task.
  420.     This is  the  most  complex  form  of  exception  handling  since  the
  421.     exception is handled in both the task containing the accept and by the
  422.     calling task.
  423.  
  424.     In this  test  an  exception  is  raised  during  a  rendezvous.   The
  425.     exception is handled in both the calling environment and in the called
  426.     task.
  427.  
  428.  
  429.  
  430.     2.5  Task Interaction Test Category
  431.  
  432.     This test  category  times  various  task  interactions  in  order  to
  433.     determine  their  relative  cost.  These tests are related to the task
  434.     communication tests and in many cases the output should be compared to
  435.     those tests.
  436.  
  437.  
  438.  
  439.     2.5.1  Procedure Calling
  440.  
  441.     In this test the time to do a procedure call is measured so it can  be
  442.     used in comparing the tasking overhead to the time of a procedure call
  443.     (i.e., normalized to a procedure  call).   The  procedure  contains  a
  444.     minimum  amount  of code, just enough to keep a compiler from thinking
  445.     Ada Tasking Benchmark Version 1.0                               Page 7
  446.  
  447.  
  448.     it can be eliminated.  An iteration consists of one procedure call.
  449.  
  450.  
  451.  
  452.     2.5.2  Conditional Entry Call
  453.  
  454.     When one task wishes to call an entry  in  another  task  it  has  the
  455.     option of:
  456.  
  457.          a.  making the call if and only if the called task  is  ready  to
  458.              accept the call, or
  459.  
  460.          b.  blocking until the called task is ready.
  461.  
  462.     The first of these two choices is a conditional entry call.
  463.  
  464.     In this test  the  main  procedure  calls  a  consumer  task  using  a
  465.     conditional  entry  call.   The  test  first  tries calls that are not
  466.     accepted, then tries calls that are accepted.  Since the  consumer  is
  467.     the  same  type of consumer used in the other producer/consumer tests,
  468.     these results can be compared to the  simple  producer/consumer  test.
  469.     An  iteration  consists  of  the "accepted call timing" minus the "not
  470.     accepted call timing" (i.e., the rendezvous time plus the overhead  of
  471.     the conditional call).
  472.  
  473.  
  474.  
  475.     2.5.3  Timed Entry Call
  476.  
  477.     Like the conditional entry mechanism, the timed entry mechanism  gives
  478.     the  calling task a degree of control over the call to the task entry.
  479.     A timed entry call allows the calling task to specify how long  it  is
  480.     willing  to  wait  for  the  rendezvous  to start.  If this time limit
  481.     expires prior to  the  start  of  the  rendezvous  then  the  call  is
  482.     cancelled.
  483.  
  484.     In this test the main procedure calls a consumer  task  with  a  timed
  485.     entry  call containing a time limit of 0.0.  The test tries calls that
  486.     are not accepted then  tries  calls  that  are  accepted.   Since  the
  487.     consumer   is   the   same   type   of  consumer  used  in  the  other
  488.     producer/consumer tests, these results can be compared to  the  simple
  489.     producer/consumer  test.   An iteration consists of the "accepted call
  490.     timing" minus the "not accepted call  timing"  (i.e.,  the  rendezvous
  491.     time plus the overhead of the timed entry call).
  492.  
  493.  
  494.  
  495.     2.5.4  Family Of Entries
  496.  
  497.     This test is similar to the simple producer/consumer in that the  main
  498.     procedure  produces  integer  values  that  are consumed by a consumer
  499.     task.  The difference is that the  consumer  task  uses  a  family  of
  500.     entries  instead  of  a  single  entry.   An iteration consists of one
  501.     Ada Tasking Benchmark Version 1.0                               Page 8
  502.  
  503.  
  504.     rendezvous.
  505.  
  506.  
  507.  
  508.     2.5.5  Simple Synchronization
  509.  
  510.     This test times the use of a simple synchronization  task  entry.   In
  511.     this  type  of  task  interaction no parameters are passed to the task
  512.     entry and there is no body for the accept.  The called task  loops  on
  513.     an unconditional accept.  An iteration consists of one rendezvous.
  514.  
  515.  
  516.  
  517.     2.5.6  Synchronization With Termination
  518.  
  519.     This test times the use of a simple synchronization  task  entry.   In
  520.     this  type  of  task  interaction no parameters are passed to the task
  521.     entry and there is no body for the accept.  The called task loops on a
  522.     select statement containing an accept and a terminate alternative.  An
  523.     iteration consists of one rendezvous.
  524.  
  525.  
  526.  
  527.     2.5.7  Terminate Option
  528.  
  529.     A group of tasks can cooperatively terminate by  using  the  terminate
  530.     option of the select statement.
  531.  
  532.     This test times the use of a simple synchronization  task  entry  both
  533.     without and with a terminate option.  In this type of task interaction
  534.     no parameters are passed to the task entry and there is  no  body  for
  535.     the accept.  The called task loops on a select statement containing an
  536.     accept and a conditional terminate alternative.  An iteration consists
  537.     of the difference in time between having the terminate option open and
  538.     having the terminate option closed.
  539.  
  540.  
  541.  
  542.     3  TIMING METHODOLOGY
  543.  
  544.     This section  describes  the  timing  methodology  employed  with  the
  545.     benchmark  tests.  For compiler speed, the measurements are taken from
  546.     the timing information  generated  by  the  compiler.   For  execution
  547.     speed,  a  generic package is used by the benchmark programs to output
  548.     the CPU time and wall-clock time elapsed during the execution  of  the
  549.     benchmark  program.   The benchmark programs are compiled and executed
  550.     in a controlled environment to limit distortion of measurements.
  551.     Ada Tasking Benchmark Version 1.0                               Page 9
  552.  
  553.  
  554.     3.1  Timing Generic
  555.  
  556.     The generic package Benchmark is used by  the  benchmark  programs  to
  557.     output  timing  measurements.  The package specification for Benchmark
  558.     is shown below:
  559.  
  560.  
  561.     with Misc_Benchmark; use Misc_Benchmark;
  562.     generic
  563.         Test_Repetitions     : NATURAL := 5;  
  564.         -- run the entire test this many times
  565.         -- to check for variability in results
  566.  
  567.         Number_of_Iterations : NATURAL := 0;
  568.         -- 0 implies the number of iterations
  569.         -- is to be determined.
  570.  
  571.         with procedure Overhead (Iterations : in NATURAL) 
  572.              is Default_Overhead;
  573.         with procedure Item_Of_Interest (Iterations : in NATURAL);
  574.  
  575.     package Benchmark is
  576.       procedure Timer;
  577.     end Benchmark;
  578.  
  579.  
  580.     The generic parameter Item_of_Interest is  the  benchmark  program  or
  581.     feature  that  is  measured.   The  generic  parameter Overhead is the
  582.     overhead involved with measuring Item_Of_Interest.
  583.  
  584.     After being instantiated as (for example):
  585.  
  586.  
  587.        package New_Benchmark is new Benchmark (Item_Of_Interest =>
  588.                                                Thing_To_Be_Measured);
  589.  
  590.  
  591.     a call to New_Benchmark.Timer causes the measurements for this test to
  592.     be  timed  and  output.   The  measurements  are  based on a number of
  593.     iterations of the "Thing_To_Be_Measured" calculated  as:   the  number
  594.     that  is  required  to have the measurements one hundred times greater
  595.     than the resolution of the system time.
  596.  
  597.     When available, a system call to a timer function  is  supplied  in  a
  598.     library unit.
  599.  
  600.  
  601.  
  602.     3.2  Testing Environment
  603.  
  604.     The testing environment is  controlled  to  limit  the  distortion  of
  605.     timing  measurements  [CLA86].   Benchmark  programs  are compiled and
  606.     executed in a batch mode in the evening.  Although  this  scheme  does
  607.     Ada Tasking Benchmark Version 1.0                              Page 10
  608.  
  609.  
  610.     not  entirely  eliminate  operating  system  interference  (i.e., time
  611.     slicing, daemon processes, and paging) or other user interference, the
  612.     results are more realistic than those obtained in an interactive mode.
  613.  
  614.  
  615.  
  616.     4  REFERENCES
  617.  
  618.                               ___________ __ ___    BAR84   Barnes, J. G. P., Programming in Ada, Second Edition,
  619.             Addison-Wesly, 1984.
  620.  
  621.     CLA86   Clapp, R.M., Duchesneau, L., Volz, R.A., Mudge, T.N., and
  622.                           ______ _________ ___________ __________            Schultze, T., Toward Real-Time Performance Benchmarks 
  623.             ___ ___            for Ada, RSD-TR-6-86, Electrical Engineering and Computer
  624.             Science Department, University of Michigan, Ann Arbor, 
  625.             January, 1986.
  626.  
  627.                         ___ __________ ___________    GEH84   Gehani, N., Ada Concurrent Programming, Prentice-Hall,
  628.             1984.
  629.  
  630.     HAB80   Habermann, A. N. and I. R. Nassi, "Efficient Implementation of
  631.             Ada Tasks," Technical Report CMU-CS-80-103, Carnegie-Mellon 
  632.             University, January 1980.
  633.  
  634.     HIL82   Hilfinger, D. N., "Implementation Strategies for Ada Tasking 
  635.             Idioms," Proceedings of the AdaTEC Conference on Ada, 
  636.             October 6-8, 1982.
  637.  
  638.     NIE86   Nielsen, K. W., "Task Coupling and Cohesion in Ada," Ada 
  639.             Letters, Volume VI, Number 4, July/August 1986.
  640.  
  641.     WEI84   Weicker, R. P., "Dhrystone: A Synthetic Systems Programming 
  642.             Benchmark," Communications of the ACM, October 1984.
  643.  
  644.  
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.  
  655.                                   APPENDIX A
  656.  
  657.                               BENCHMARK LISTINGS
  658.  
  659.  
  660.  
  661.     A.1  FILE ORGANIZATION
  662.  
  663.     The organization of the files for these benchmarks is presented below.
  664.  
  665.     The timing benchmark files must be compiled first,  in  the  following
  666.     order:
  667.  
  668.          a.  CPU_SPEC.ADA
  669.          b.  CPU_BODY.ADA
  670.          c.  MISC_BENCHMARK_SPEC.ADA
  671.          d.  MISC_BENCHMARK_BODY.ADA
  672.          e.  TIMER_SPEC.ADA
  673.          f.  TIMER_BODY.ADA
  674.  
  675.  
  676.     The file WALL_CLOCK_CPU_BODY.ADA outputs the elapsed time as  the  cpu
  677.     time.  This is machine independent and can be used until a CPU_BODY is
  678.     developed for the specific target machine.
  679.  
  680.     The tasking benchmark files must be compiled in the following order:
  681.  
  682.          a.  package specification  file  before  respective  body  (e.g.,
  683.              PART1SPEC.ADA before PART1.ADA)
  684.  
  685.          b.  all the specifications must be compiled before DRIVER.ADA.
  686.  
  687.     Ada Benchmark Suite Version 1.0                               Page A-2
  688.  
  689.  
  690.     A.2  CPU_SPEC.ADA
  691.  
  692.     The following is a listing of the specification for package Cpu:
  693.  
  694.  
  695.  
  696.     --  this is a machine specific package for reporting the amount of
  697.     --  CPU time used. 
  698.     package Cpu is
  699.       type Time is private;
  700.  
  701.         --  The time returned by Clock can only be used to determine the
  702.         --  difference between two times.
  703.       function Clock return Time;
  704.  
  705.         -- subtracting two times will result in the duration (seconds).
  706.       function "-" (Stop_Time, Start_Time : Time) return DURATION;
  707.     private
  708.       type Time is new DURATION;
  709.     end Cpu;
  710.  
  711.  
  712.     Ada Benchmark Suite Version 1.0                               Page A-3
  713.  
  714.  
  715.     A.3  CPU_BODY.ADA
  716.  
  717.     The following is a listing of the body for package Cpu:
  718.  
  719.  
  720.  
  721.     --  this is a machine specific package for reporting the amount of
  722.     --  CPU time used. The CPU time is expressed in centiseconds.
  723.     with TEXT_IO;   use TEXT_IO;
  724.     with SYSTEM;
  725.     package body Cpu is
  726.  
  727.       type Item_List is
  728.                record
  729.                   Code            : SHORT_INTEGER;
  730.                   Buffer_Length   : SHORT_INTEGER;
  731.                   Buffer_Address  : SYSTEM.ADDRESS;
  732.                   Return_Len_Addr : SYSTEM.ADDRESS;
  733.                   End_List        : INTEGER := 0;  -- marks end of requests
  734.                end record;
  735.  
  736.       for Item_List use
  737.                record
  738.                   Code                at 0 range 16 .. 31;
  739.                   Buffer_Length       at 0 range 0  .. 15;
  740.                   Buffer_Address      at 4 range 0  .. 31;
  741.                   Return_Len_Addr     at 8 range 0  .. 31;
  742.                   End_List            at 12 range 0  .. 31;
  743.                end record;
  744.  
  745.  
  746.       procedure GetJPIW (Status : out INTEGER;
  747.                          Efn    : in  INTEGER := 0;  -- not used
  748.                          PidAdr : in  INTEGER := INTEGER'NULL_PARAMETER;
  749.                          PrcNam : in  INTEGER := INTEGER'NULL_PARAMETER;
  750.                          ItmLst : in out Item_List;
  751.                          Iosb   : in  INTEGER := INTEGER'NULL_PARAMETER;
  752.                          AstAdr : in  INTEGER := INTEGER'NULL_PARAMETER;
  753.                          AstPrm : in  INTEGER := INTEGER'NULL_PARAMETER;
  754.                          Nullarg: in  INTEGER := INTEGER'NULL_PARAMETER);
  755.       pragma INTERFACE (SYSTEM, GetJPIW);
  756.       pragma IMPORT_VALUED_PROCEDURE (GetJPIW, "SYS$GETJPIW",
  757.                 MECHANISM => (VALUE, REFERENCE, REFERENCE, DESCRIPTOR, REFERENCE,
  758.                               REFERENCE, REFERENCE, REFERENCE, REFERENCE));
  759.  
  760.       function Clock return Time is
  761.         JPI_CPUTIM : constant := 1031;  -- accumulated cpu time
  762.         Rslt_Len,
  763.         Ticks     : INTEGER := 0;
  764.         Rqst      : Item_List;
  765.         Status    : INTEGER;
  766.         pragma VOLATILE (Ticks);
  767.         pragma VOLATILE (Rslt_Len);
  768.     Ada Benchmark Suite Version 1.0                               Page A-4
  769.  
  770.  
  771.       begin
  772.         Rqst.Buffer_Length   := 4;  -- 4 bytes in a longword
  773.         Rqst.Buffer_Address  := Ticks'ADDRESS;
  774.         Rqst.Return_Len_Addr := Rslt_Len'ADDRESS;
  775.         Rqst.Code            := JPI_CPUTIM;
  776.         GetJPIW (Status => Status,  ItmLst => Rqst);
  777.         if Status /= 1 or Rslt_Len /= 4 then
  778.           PUT_LINE ("bad status from Get_JPIW = " & INTEGER'IMAGE (Status) &
  779.                      "  len = " & INTEGER'IMAGE (Rslt_Len));
  780.         end if;
  781.         return Time(Time(Ticks) * Time(0.01));
  782.       end Clock;
  783.  
  784.  
  785.     function "-" (Stop_Time, Start_Time : Time) return DURATION is
  786.     begin
  787.       return DURATION (DURATION (Stop_Time) - DURATION (Start_Time));
  788.     end "-";
  789.  
  790.     begin
  791.       null;
  792.     end Cpu;
  793.  
  794.  
  795.     Ada Benchmark Suite Version 1.0                               Page A-5
  796.  
  797.  
  798.     A.4  MISC_BENCHMARK_SPEC.ADA
  799.  
  800.     The following is a listing of the specification for package Misc_Benchmark:
  801.  
  802.  
  803.  
  804.     --  this is a package which provides a default
  805.     --  for the overhead timing subprogram in the Benchmark Generic
  806.     --  as well as miscellaneous timing routines.
  807.     with CALENDAR; use CALENDAR;
  808.     with Cpu; use Cpu;
  809.     package Misc_Benchmark is
  810.       type Time_Info is private;
  811.       type Raw_Time_Info is private;
  812.       type Results_Type is array (NATURAL range <>) of Time_Info;
  813.  
  814.       procedure Get_Both_Times (Now : out Raw_Time_Info);
  815.       function "-" (Stop, Start : in Raw_Time_Info) return Time_Info;
  816.       procedure Print_Results (Results : in Results_Type;
  817.                                Overhead_Results : in Results_Type;
  818.                                Test_Repetitions : NATURAL;
  819.                                Iterations : NATURAL);
  820.  
  821.       procedure Default_Overhead (Iterations : in NATURAL);
  822.  
  823.     private
  824.       type Time_Info is record
  825.              Elapsed_Time,
  826.              Cpu_Time : DURATION;
  827.            end record;
  828.  
  829.       type Raw_Time_Info is record
  830.              Elapsed_Time  : CALENDAR.TIME;
  831.              Cpu_Time      : Cpu.Time;
  832.            end record;
  833.  
  834.     end Misc_Benchmark;
  835.     Ada Benchmark Suite Version 1.0                               Page A-6
  836.  
  837.  
  838.     A.5  MISC_BENCHMARK_SPEC.ADA
  839.  
  840.     The following is a listing of the body for package Misc_Benchmark:
  841.  
  842.  
  843.  
  844.     --  this is a package which provides a default
  845.     --  for the overhead timing subprogram in the Benchmark Generic
  846.     --  as well as miscellaneous timing routines.
  847.     with TEXT_IO; use TEXT_IO;
  848.     with CALENDAR; use CALENDAR;
  849.     with Cpu; use Cpu;
  850.     package body Misc_Benchmark is
  851.  
  852.     procedure Get_Both_Times (Now : out Raw_Time_Info) is
  853.     -- retrieves the current elapsed time and cpu time
  854.     begin
  855.       Now.Elapsed_Time := CALENDAR.CLOCK;
  856.       Now.Cpu_Time := Cpu.Clock;
  857.     end Get_Both_Times;
  858.  
  859.     function "-" (Stop, Start : in Raw_Time_Info) return Time_Info is
  860.     begin
  861.       return (Elapsed_Time => Stop.Elapsed_Time - Start.Elapsed_Time,
  862.               Cpu_Time => Stop.Cpu_Time - Start.Cpu_Time);
  863.     end "-";
  864.  
  865.     procedure Print_Results (Results : in Results_Type;
  866.                              Overhead_Results : in Results_Type;
  867.                              Test_Repetitions : NATURAL;
  868.                              Iterations : NATURAL) is
  869.  
  870.       package Duration_IO is new FIXED_IO (DURATION);
  871.       use Duration_IO;
  872.  
  873.       type Net_Cpu_Type is array (1..Test_Repetitions) of DURATION;
  874.       Net_Cpus : Net_Cpu_Type;  -- contains the Net Cpu per repetition
  875.       Total_Cpu : DURATION := 0.0;
  876.  
  877.     begin
  878.       NEW_LINE;
  879.       PUT("Number of iterations executed per repetition: ");
  880.       PUT(NATURAL'IMAGE(Iterations));
  881.       NEW_LINE;
  882.       NEW_LINE;
  883.       PUT_LINE("Note that all times are in seconds.");
  884.       NEW_LINE;
  885.  
  886.       -- build table header
  887.       PUT("|-----------------------------------------------------------------");
  888.       PUT_LINE("-------------|");
  889.       PUT("| REPETITION |  OVERHEAD  |    TEST    |     NET    |   TEST     |");
  890.       PUT_LINE(" NET CPU PER |");
  891.     Ada Benchmark Suite Version 1.0                               Page A-7
  892.  
  893.  
  894.       PUT("| NUMBER     |  CPU       |    CPU     |     CPU    |   ELAPSED  |");
  895.       PUT_LINE(" ITERATION   |");
  896.  
  897.       for Repetitions in 1..Test_Repetitions loop
  898.         PUT("|------------|------------|------------|------------|------------|");
  899.         PUT_LINE("-------------|");
  900.         PUT("|     ");
  901.         PUT(NATURAL'IMAGE(Repetitions));
  902.         SET_COL(14); 
  903.         PUT("| "); 
  904.         PUT(Overhead_Results (Repetitions).Cpu_Time,FORE => 5);
  905.         SET_COL(27);
  906.         PUT("| "); 
  907.         PUT(Results (Repetitions).Cpu_Time,FORE => 5);
  908.         SET_COL(40);
  909.         PUT("| ");
  910.         Net_Cpus(Repetitions) := DURATION(Results(Repetitions).Cpu_Time - 
  911.                                           Overhead_Results(Repetitions).Cpu_Time);
  912.         Total_Cpu := Total_Cpu + Net_Cpus(Repetitions);
  913.         PUT(Net_Cpus(Repetitions),FORE => 5);
  914.         SET_COL(53);
  915.         PUT("| ");
  916.         PUT(Results (Repetitions).Elapsed_Time,FORE => 5);
  917.         SET_COL(66);
  918.         PUT("|  ");
  919.         PUT(DURATION(Net_Cpus(Repetitions) / DURATION(Iterations)),FORE => 5);
  920.         SET_COL(80);
  921.         PUT_LINE("|");
  922.       end loop;
  923.  
  924.       PUT("|-----------------------------------------------------------------");
  925.       PUT_LINE("-------------|");
  926.  
  927.       -- Output Net Cpu time averaged across repetitions
  928.       NEW_LINE;
  929.       NEW_LINE;
  930.       PUT("The average net cpu time (across repetitions) was: ");
  931.       PUT(DURATION(Total_Cpu / DURATION(Test_Repetitions)),FORE=>5);
  932.       NEW_LINE;
  933.       PUT("The average net cpu time per iteration was: ");
  934.       PUT(DURATION(Total_Cpu / DURATION(Test_Repetitions * Iterations)),FORE=>5);
  935.       NEW_LINE;
  936.       NEW_LINE;
  937.       PUT_LINE((1..80=> '-'));
  938.       PUT_LINE((1..80=> '-'));
  939.     end Print_Results;
  940.  
  941.  
  942.     procedure Default_Overhead (Iterations : in NATURAL) is
  943.     begin
  944.       for Loop_Count in 1..Iterations loop
  945.         null;
  946.       end loop;
  947.     Ada Benchmark Suite Version 1.0                               Page A-8
  948.  
  949.  
  950.     end Default_Overhead;
  951.  
  952.     begin
  953.       null;
  954.     end Misc_Benchmark;
  955.     Ada Benchmark Suite Version 1.0                               Page A-9
  956.  
  957.  
  958.     A.6  TIMER_SPEC.ADA
  959.  
  960.     The following is a listing of the specification for package Benchmark:
  961.  
  962.  
  963.  
  964.     --++
  965.     -- FACILITY:
  966.     --      Benchmark Driver
  967.     --
  968.     -- ABSTRACT:
  969.     --      This generic procedure provides the services necessary to time
  970.     --      a given operaion and report on the performance.
  971.     --
  972.     -- AUTHOR:
  973.     --      Tom Burger
  974.     --
  975.     -- MODIFICATION HISTORY:
  976.     ---- 
  977.     with Misc_Benchmark; use Misc_Benchmark;
  978.     generic
  979.         Test_Repetitions     : NATURAL := 5;  -- run the entire test this many times
  980.                                               -- to check for variability in results
  981.         Number_of_Iterations : NATURAL := 0;  -- 0 implies the number of iterations
  982.                                               -- is to be determined.
  983.  
  984.         with procedure Overhead (Iterations : in NATURAL) is Default_Overhead;
  985.         with procedure Item_Of_Interest (Iterations : in NATURAL);
  986.  
  987.     package Benchmark is
  988.       procedure Timer;
  989.     end Benchmark;
  990.  
  991.  
  992.     Ada Benchmark Suite Version 1.0                              Page A-10
  993.  
  994.  
  995.     A.7  TIMER_BODY.ADA
  996.  
  997.     The following is a listing of the body for package Benchmark:
  998.  
  999.  
  1000.  
  1001.     --++
  1002.     -- FACILITY:
  1003.     --      Benchmark Driver
  1004.     --
  1005.     -- ABSTRACT:
  1006.     --      This generic procedure provides the services necessary to time
  1007.     --      a given operaion and report on the performance.
  1008.     --
  1009.     -- AUTHOR:
  1010.     --      Tom Burger
  1011.     --
  1012.     -- MODIFICATION HISTORY:
  1013.     ----
  1014.  
  1015.     with TEXT_IO;  use TEXT_IO;
  1016.     with Cpu;      use Cpu;
  1017.     with Misc_Benchmark; use Misc_Benchmark;
  1018.     with SYSTEM;                        -- for SYSTEM.TICK
  1019.     package body Benchmark is
  1020.  
  1021.     Iterations : NATURAL;     -- how many iterations to run the test
  1022.  
  1023.     procedure Determine_Necessary_Iterations is
  1024.       -- If a specified number of iterations is given then use this number;
  1025.       -- otherwise, determine the best number of iterations by starting at 1 and
  1026.       -- keep doubling the number of iterations until the time required for
  1027.       -- the item of interest is at least 100 times the clock resolution.
  1028.       -- The result of this procedure is left in the variable Iterations.
  1029.  
  1030.       Minimum_Time : DURATION;
  1031.       Start_Cpu,
  1032.       Stop_Cpu   : Cpu.Time;
  1033.     begin
  1034.       if Number_Of_Iterations /= 0 then
  1035.         Iterations := Number_Of_Iterations;
  1036.         return;
  1037.       end if;
  1038.  
  1039.       if SYSTEM.TICK > DURATION'SMALL then  
  1040.         Minimum_Time := 100 * SYSTEM.TICK;
  1041.       else
  1042.         Minimum_Time := 100 * DURATION'SMALL;
  1043.       end if;
  1044.  
  1045.       Iterations := 1;
  1046.       loop
  1047.         Start_Cpu := Cpu.Clock;
  1048.     Ada Benchmark Suite Version 1.0                              Page A-11
  1049.  
  1050.  
  1051.         Item_Of_Interest (Iterations);
  1052.         Stop_Cpu := Cpu.Clock;
  1053.  
  1054.         exit when Stop_Cpu - Start_Cpu >= Minimum_Time;
  1055.  
  1056.           -- check for overflow condition
  1057.         if Iterations = NATURAL'LAST / 2 + 1 then
  1058.           Iterations := NATURAL'LAST;
  1059.           exit;
  1060.         end if;
  1061.         Iterations := Iterations * 2;
  1062.       end loop;
  1063.     end Determine_Necessary_Iterations;
  1064.  
  1065.       
  1066.     procedure Do_Timing_Run (Results : out Results_Type;
  1067.                              Overhead_Results : out Results_Type) is
  1068.  
  1069.       Start,
  1070.       Stop   : Raw_Time_Info;          -- Contains Elapsed and Cpu Times
  1071.  
  1072.     begin               
  1073.       for Repetitions in 1..Test_Repetitions loop
  1074.         Get_Both_Times (Start);
  1075.         Overhead (Iterations);  -- run the overhead routine
  1076.         Get_Both_Times (Stop);
  1077.         Overhead_Results (Repetitions) := Stop - Start;
  1078.  
  1079.         Get_Both_Times (Start);
  1080.         Item_Of_Interest (Iterations);  -- run the item of interest routine
  1081.         Get_Both_Times (Stop);
  1082.         Results (Repetitions) := Stop - Start;
  1083.       end loop;
  1084.     end Do_Timing_Run;
  1085.  
  1086.  
  1087.     procedure Timer is
  1088.       Results : Results_Type (1..Test_Repetitions);
  1089.       Overhead_Results : Results_Type (1..Test_Repetitions);
  1090.     begin 
  1091.       Determine_Necessary_Iterations;
  1092.       Do_Timing_Run (Results, Overhead_Results);
  1093.       Print_Results (Results, Overhead_Results, Test_Repetitions, Iterations);
  1094.     end Timer;
  1095.  
  1096.     end Benchmark;
  1097.     Ada Benchmark Suite Version 1.0                              Page A-12
  1098.  
  1099.  
  1100.     A.8  WALL_CLOCK_CPU_BODY.ADA
  1101.  
  1102.     The following is a machine independent listing of the body for package Cpu:
  1103.  
  1104.  
  1105.  
  1106.     --  this is a machine independent dummy package for reporting the amount of
  1107.     --  CPU time used. It actually reports the elapsed time
  1108.     with CALENDAR;  use CALENDAR;
  1109.     with TEXT_IO;   use TEXT_IO;
  1110.     package body Cpu is
  1111.       Base_Time : constant CALENDAR.TIME := CALENDAR.CLOCK;
  1112.  
  1113.     function Clock return Time is
  1114.       Now : constant CALENDAR.TIME := CALENDAR.CLOCK;
  1115.     begin
  1116.       return Cpu.Time (Now - Base_Time);
  1117.     end Clock;
  1118.  
  1119.     function "-" (Stop_Time, Start_Time : Time) return DURATION is
  1120.     begin
  1121.       return DURATION (DURATION (Stop_Time) - DURATION (Start_Time));
  1122.     end "-";
  1123.  
  1124.     begin
  1125.       PUT_LINE ("NOTE: CPU Time is actually ELAPSED time!!!");
  1126.     end Cpu;
  1127.  
  1128.  
  1129.     Ada Benchmark Suite Version 1.0                              Page A-13
  1130.  
  1131.  
  1132.     A.9  PART1SPEC.ADA
  1133.  
  1134.     The following is a listing of the specification for the package Part_1:
  1135.  
  1136.  
  1137.  
  1138.     ---- test section 1
  1139.  
  1140.     package Part1 is
  1141.       Title : constant STRING := "task activation/termination";
  1142.       procedure Do_Test;
  1143.     end Part1;
  1144.     Ada Benchmark Suite Version 1.0                              Page A-14
  1145.  
  1146.  
  1147.     A.10  PART1.ADA
  1148.  
  1149.     The following is a listing of the body for the package Part_1:
  1150.  
  1151.  
  1152.  
  1153.     ---- test section 1 - task activation/termination
  1154.     with TEXT_IO, Benchmark;
  1155.     use  TEXT_IO;
  1156.     package body Part1 is
  1157.  
  1158.     procedure Do_Test is
  1159.  
  1160.         procedure Task_Activation (N : in NATURAL) is
  1161.           -- this procedure declares N tasks locally - timing this procedure
  1162.           -- will time 1 procedure call and N task activations/terminations
  1163.  
  1164.           task type Empty_Task;
  1165.  
  1166.           Lots_Of_Tasks : array (1 .. N) of Empty_Task;
  1167.  
  1168.           task body Empty_Task is
  1169.           begin
  1170.             null;
  1171.           end  Empty_Task;
  1172.  
  1173.         begin
  1174.           null;
  1175.         end Task_Activation;
  1176.  
  1177.  
  1178.         procedure Task_Allocation (N : in NATURAL) is
  1179.         -- this procedure allocates N tasks.  Since the task type is declared
  1180.         -- locally, deallocation of the task space should occur during the
  1181.         -- call to this procedure.
  1182.  
  1183.           task type Empty_Task;
  1184.  
  1185.           type Empty_Task_Ptr is access Empty_Task;
  1186.           Lots_Of_Tasks : array (1 .. N) of Empty_Task_Ptr;
  1187.  
  1188.           task body Empty_Task is
  1189.           begin
  1190.             null;
  1191.           end  Empty_Task;
  1192.  
  1193.         begin
  1194.           Lots_Of_Tasks := (1 .. N => new Empty_Task);
  1195.         end Task_Allocation;
  1196.  
  1197.         procedure Task_Activation2 (N : in NATURAL) is
  1198.           -- this procedure declares N tasks locally - timing this procedure
  1199.           -- will time 1 procedure call and N task activations/terminations
  1200.     Ada Benchmark Suite Version 1.0                              Page A-15
  1201.  
  1202.  
  1203.  
  1204.           task type Empty_Task is
  1205.              entry Dont_Call_Me;
  1206.           end Empty_Task;
  1207.  
  1208.           Lots_Of_Tasks : array (1 .. N) of Empty_Task;
  1209.  
  1210.           task body Empty_Task is
  1211.           begin
  1212.             select
  1213.               accept Dont_Call_Me;
  1214.             or
  1215.               terminate;
  1216.             end select;
  1217.           end  Empty_Task;
  1218.  
  1219.         begin
  1220.           null;
  1221.         end Task_Activation2;
  1222.  
  1223.  
  1224.     begin  -- Do_Test
  1225.         PUT_LINE ("               Task Activation/Termination Test");
  1226.         NEW_LINE;
  1227.         PUT_LINE ("This test times task activation and termination under a ");
  1228.         PUT_LINE ("variety of circumstances.");
  1229.  
  1230.                   --------------------------------------------
  1231.  
  1232.         NEW_LINE (2);
  1233.         PUT_LINE ("In this test an array of tasks is declared locally to a");
  1234.         PUT_LINE ("procedure.  Both the procedure and the task have null bodies.");
  1235.         NEW_LINE;
  1236.  
  1237.         declare
  1238.           package Local_Array_Pkg is new Benchmark 
  1239.                   (Item_Of_Interest => Task_Activation);
  1240.         begin
  1241.           Local_Array_Pkg.Timer;
  1242.         end;
  1243.  
  1244.                   --------------------------------------------
  1245.  
  1246.         NEW_LINE (2);
  1247.         PUT_LINE ("In this test an array of tasks is declared locally to a");
  1248.         PUT_LINE ("procedure.  The task uses the terminate option in a select");
  1249.         PUT_LINE ("statement to terminate.  The task is never called");
  1250.         NEW_LINE;
  1251.  
  1252.         declare
  1253.           package Terminate_Array_Pkg is new Benchmark
  1254.                   (Item_Of_Interest => Task_Activation2);
  1255.         begin
  1256.     Ada Benchmark Suite Version 1.0                              Page A-16
  1257.  
  1258.  
  1259.           Terminate_Array_Pkg.Timer;
  1260.         end;
  1261.  
  1262.                  ----------------------------------------
  1263.  
  1264.         NEW_LINE (2);
  1265.         PUT_LINE ("In this test an access type to a task is used to create a");
  1266.         PUT_LINE ("series of tasks.  The timing should include both allocation");
  1267.         PUT_LINE ("and deallocation of the task as well as activation and");
  1268.         PUT_LINE ("termination.");
  1269.         NEW_LINE;
  1270.  
  1271.         declare
  1272.           package Access_Type_Pkg is new Benchmark
  1273.                   (Item_Of_Interest => Task_Allocation);
  1274.         begin
  1275.           Access_Type_Pkg.Timer;
  1276.         end;
  1277.  
  1278.  
  1279.     exception
  1280.       when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  1281.       when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  1282.       when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  1283.       when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  1284.       when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  1285.       when others           => PUT_LINE ("*** test aborted due to exception");
  1286.  
  1287.     end Do_Test;
  1288.  
  1289.     end Part1;
  1290.     Ada Benchmark Suite Version 1.0                              Page A-17
  1291.  
  1292.  
  1293.     A.11  PART2SPEC.ADA
  1294.  
  1295.     The following is a listing of the specification for the package Part_2:
  1296.  
  1297.  
  1298.  
  1299.     ---- test section 2
  1300.  
  1301.     package Part2 is
  1302.       Title : constant STRING := "task communication";
  1303.       procedure Do_Test;
  1304.     end Part2;
  1305.     Ada Benchmark Suite Version 1.0                              Page A-18
  1306.  
  1307.  
  1308.     A.12  PART2.ADA
  1309.  
  1310.     The following is a listing of the body for the package Part_2:
  1311.  
  1312.  
  1313.  
  1314.     --- test section 2  --  task communication
  1315.     with TEXT_IO, Benchmark;
  1316.     use  TEXT_IO;
  1317.     package body Part2 is
  1318.  
  1319.     -- define the continue and terminate conditions for the tasks
  1320.     Continue_Item : constant := 1;
  1321.     Terminate_Item : constant := -1;
  1322.  
  1323.  
  1324.     procedure Do_Test is
  1325.  
  1326.  
  1327.       -- task types that are used in several tests
  1328.  
  1329.       task type Buffer_Type is
  1330.         entry Take_Item (Item : in INTEGER);
  1331.         entry Provide_Item (Item : out INTEGER);
  1332.       end Buffer_Type;
  1333.  
  1334.       task type Called_Consumer_Type is
  1335.             -- consumer is to take items until 
  1336.             -- a value of Terminate_Item is accepted. 
  1337.         entry Take_Item (Item : in INTEGER);
  1338.       end Called_Consumer_Type;
  1339.  
  1340.     pragma PAGE;
  1341.       
  1342.       task body Buffer_Type is
  1343.          type Buffer_Count is range 0 .. 2;
  1344.          subtype Buffer_Index is Buffer_Count range 1 .. Buffer_Count'LAST;
  1345.          Buf : array (Buffer_Index) of INTEGER;
  1346.          Head, Tail : Buffer_Index := Buffer_Index'FIRST;
  1347.          Count : Buffer_Count := 0;
  1348.       begin
  1349.         loop
  1350.           select
  1351.             when Count > 0 =>
  1352.             accept Provide_Item (Item : out INTEGER) do
  1353.               Item := Buf (Tail);
  1354.               Tail := (Tail mod Buffer_Index'LAST) + 1;
  1355.               Count := Count - 1;
  1356.             end Provide_Item;
  1357.           or
  1358.             when Count < Buffer_Count'LAST =>
  1359.             accept Take_Item (Item : in INTEGER) do
  1360.               Buf (Head) := Item;
  1361.     Ada Benchmark Suite Version 1.0                              Page A-19
  1362.  
  1363.  
  1364.               Head := (Head mod Buffer_Index'LAST) + 1;
  1365.               Count := Count + 1;
  1366.             end Take_Item;
  1367.           or
  1368.             terminate;
  1369.           end select;
  1370.         end loop;
  1371.       end Buffer_Type;
  1372.  
  1373.  
  1374.  
  1375.       task body Called_Consumer_Type is
  1376.         Item : INTEGER;
  1377.       begin
  1378.         loop
  1379.           accept Take_Item (Item : in INTEGER) do
  1380.             Called_Consumer_Type.Item := Item;
  1381.           end Take_Item;
  1382.  
  1383.           exit when Item = Terminate_Item;
  1384.  
  1385.         end loop;
  1386.       end Called_Consumer_Type;
  1387.     pragma PAGE;
  1388.  
  1389.     procedure Time_PC is
  1390.       Consumer : Called_Consumer_Type;
  1391.  
  1392.     begin
  1393.       NEW_LINE (2);
  1394.       PUT_LINE ("SIMPLE PC");
  1395.       PUT_LINE ("In this test the main task calls a consumer task.");
  1396.       PUT_LINE ("A simple integer value is the only data transferred");
  1397.       PUT_LINE ("and the consumer simply loops on the accept.");
  1398.       PUT_LINE ("Task activation/termination time is not included in the timing.");
  1399.       NEW_LINE;
  1400.  
  1401.       declare
  1402.         procedure Send_Item (Iterations : in NATURAL) is
  1403.         begin
  1404.           for J in 1..Iterations loop
  1405.             Consumer.Take_Item (Continue_Item);
  1406.           end loop;
  1407.         end Send_Item;
  1408.  
  1409.         package PC_Pkg is new Benchmark
  1410.                 (Item_Of_Interest => Send_Item);
  1411.       begin
  1412.         PC_Pkg.Timer;
  1413.         Consumer.Take_Item (Terminate_Item);
  1414.       end;
  1415.  
  1416.     exception
  1417.     Ada Benchmark Suite Version 1.0                              Page A-20
  1418.  
  1419.  
  1420.       when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  1421.       when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  1422.       when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  1423.       when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  1424.       when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  1425.       when others           => PUT_LINE ("*** test aborted due to exception");
  1426.     end Time_PC;
  1427.     pragma PAGE;
  1428.  
  1429.     procedure Time_PC2 is
  1430.  
  1431.       task type Called_Consumer_Type_With_Select is
  1432.             -- consumer is to take items until 
  1433.             -- a value of Terminate_Item is accepted. 
  1434.         entry Take_Item (Item : in INTEGER);
  1435.         entry Stop;  -- alternate entry for Take_Item
  1436.       end Called_Consumer_Type_With_Select;
  1437.  
  1438.       Consumer : Called_Consumer_Type_With_Select;
  1439.  
  1440.  
  1441.  
  1442.       task body Called_Consumer_Type_With_Select is
  1443.         Item : INTEGER;
  1444.       begin
  1445.         loop
  1446.           select
  1447.             accept Take_Item (Item : in INTEGER) do
  1448.               Called_Consumer_Type_With_Select.Item := Item;
  1449.             end Take_Item;
  1450.           or
  1451.             accept Stop do
  1452.                Item := Item;
  1453.             end Stop;
  1454.           end select;
  1455.  
  1456.           exit when Item = Terminate_Item;
  1457.  
  1458.         end loop;
  1459.       end Called_Consumer_Type_With_Select;
  1460.  
  1461.  
  1462.     begin
  1463.       NEW_LINE (2);
  1464.       PUT_LINE ("SELECTIVE WAIT");
  1465.       PUT_LINE ("In this test the main task calls a consumer task that");
  1466.       PUT_LINE ("consumes more than one type of item.");
  1467.       PUT_LINE ("A simple integer value is the only data transferred");
  1468.       PUT_LINE ("and the consumer simply loops on the selective accept.");
  1469.       PUT_LINE ("This test differs from the previous test in that the consumer");
  1470.       PUT_LINE ("uses a select statement to take the entry call where the");
  1471.       PUT_LINE ("select has two open alternatives.  In the previous case");
  1472.       PUT_LINE ("there was no select statement.");
  1473.     Ada Benchmark Suite Version 1.0                              Page A-21
  1474.  
  1475.  
  1476.       NEW_LINE;
  1477.  
  1478.       declare
  1479.         procedure Send_Item (Iterations : in NATURAL) is
  1480.         begin
  1481.           for J in 1..Iterations loop
  1482.             Consumer.Take_Item (Continue_Item);
  1483.           end loop;
  1484.         end Send_Item;
  1485.  
  1486.         package PC2_Pkg is new Benchmark
  1487.                 (Item_Of_Interest => Send_Item);
  1488.       begin
  1489.         PC2_Pkg.Timer;
  1490.         Consumer.Take_Item (Terminate_Item);
  1491.       end;
  1492.  
  1493.     exception
  1494.       when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  1495.       when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  1496.       when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  1497.       when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  1498.       when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  1499.       when others           => PUT_LINE ("*** test aborted due to exception");
  1500.     end Time_PC2;
  1501.     pragma PAGE;
  1502.  
  1503.     procedure Time_PC3 is
  1504.       Consumer : Called_Consumer_Type;
  1505.  
  1506.       task Producer is
  1507.            -- producer terminates upon accepting Terminate_Item.
  1508.         entry Produce (Num : in INTEGER);
  1509.         entry Have_Finished;
  1510.         
  1511.         -- Calls
  1512.            -- Consumer.Take_Item
  1513.       end Producer;
  1514.  
  1515.  
  1516.       task body Producer is
  1517.         Count : INTEGER;
  1518.       begin
  1519.         loop
  1520.           accept Produce (Num : in INTEGER) do
  1521.             Count := Num;
  1522.           end Produce;
  1523.  
  1524.           exit when Count = Terminate_Item;
  1525.  
  1526.           for I in 1 .. Count loop
  1527.             Consumer.Take_Item (Continue_Item);
  1528.           end loop;
  1529.     Ada Benchmark Suite Version 1.0                              Page A-22
  1530.  
  1531.  
  1532.  
  1533.           accept Have_Finished;
  1534.         end loop;
  1535.       end Producer;
  1536.  
  1537.       
  1538.     begin
  1539.       NEW_LINE (2);
  1540.       PUT_LINE ("PC");
  1541.       PUT_LINE ("In this test a producer task communicates with a consumer task");
  1542.       PUT_LINE ("directly. This timing should be similar to the simple PC tests.");
  1543.       PUT_LINE ("Interaction with the main task takes place only at the beginning");
  1544.       PUT_LINE ("and at the end.");
  1545.       PUT_LINE ("Total number of task interactions is N+2");
  1546.       NEW_LINE;
  1547.  
  1548.       declare
  1549.         procedure Tell_Producer (Iterations : in NATURAL) is
  1550.         begin
  1551.           Producer.Produce (Iterations);
  1552.           Producer.Have_Finished;
  1553.         end Tell_Producer;
  1554.  
  1555.         package PC3_Pkg is new Benchmark
  1556.                 (Item_Of_Interest => Tell_Producer);
  1557.  
  1558.       begin
  1559.         PC3_Pkg.Timer;
  1560.         Producer.Produce (Terminate_Item);
  1561.         Consumer.Take_Item (Terminate_Item);
  1562.       end;
  1563.  
  1564.     exception
  1565.       when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  1566.       when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  1567.       when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  1568.       when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  1569.       when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  1570.       when others           => PUT_LINE ("*** test aborted due to exception");
  1571.     end Time_PC3;
  1572.     pragma PAGE;
  1573.  
  1574.     procedure Time_PBC is
  1575.       Buffer : Buffer_Type;
  1576.  
  1577.  
  1578.       task type Calling_Consumer_Type is
  1579.             -- consumer is to take items until 
  1580.             -- a value of Terminate_Item is received. 
  1581.         entry Stop_On_Number (Num : in INTEGER); 
  1582.  
  1583.         -- Calls
  1584.            -- Buffer.Provide_Item
  1585.     Ada Benchmark Suite Version 1.0                              Page A-23
  1586.  
  1587.  
  1588.       end Calling_Consumer_Type;
  1589.  
  1590.       Consumer : Calling_Consumer_Type;
  1591.  
  1592.  
  1593.       task Producer is
  1594.         entry Produce (Num : in INTEGER);
  1595.         entry Have_Finished;
  1596.         -- Calls
  1597.            -- Buffer.Take_Item
  1598.       end Producer;
  1599.  
  1600.  
  1601.       task body Producer is
  1602.         Count : INTEGER;
  1603.       begin
  1604.         loop
  1605.           accept Produce (Num : in INTEGER) do
  1606.             Count := Num;
  1607.           end Produce;
  1608.  
  1609.           exit when Count = Terminate_Item;
  1610.  
  1611.           for I in 1 .. Count loop
  1612.             Buffer.Take_Item (Continue_Item);
  1613.           end loop;
  1614.  
  1615.           accept Have_Finished;
  1616.         end loop;
  1617.       end Producer;
  1618.  
  1619.  
  1620.       task body Calling_Consumer_Type is
  1621.         Item,
  1622.         Count : INTEGER;
  1623.       begin
  1624.         loop
  1625.           Accept Stop_On_Number (Num : in INTEGER) do
  1626.             Count := Num;
  1627.           end Stop_On_Number;
  1628.  
  1629.           exit when Count = Terminate_Item;
  1630.  
  1631.           for I in 1..Count loop
  1632.             Buffer.Provide_Item (Item);
  1633.           end loop;
  1634.         end loop;
  1635.       end Calling_Consumer_Type;
  1636.  
  1637.  
  1638.     begin
  1639.       NEW_LINE (2);
  1640.       PUT_LINE ("PBC");
  1641.     Ada Benchmark Suite Version 1.0                              Page A-24
  1642.  
  1643.  
  1644.       PUT_LINE ("In this test a producer task communicates with a consumer task");
  1645.       PUT_LINE ("indirectly through a bounded buffer (buffer size = 2).");
  1646.       PUT_LINE ("Interaction with the main task takes place only at the beginning");
  1647.       PUT_LINE ("and at the end.");
  1648.       PUT_LINE ("Total number of task interactions is 2N+3.");
  1649.       NEW_LINE;
  1650.  
  1651.       declare
  1652.         procedure Tell_PC (Iterations : NATURAL) is
  1653.         begin
  1654.           Producer.Produce (Iterations);
  1655.           Consumer.Stop_On_Number (Iterations);
  1656.           Producer.Have_Finished;
  1657.         end Tell_PC;
  1658.  
  1659.         package PBC_Pkg is new Benchmark
  1660.                 (Item_Of_Interest => Tell_PC);
  1661.  
  1662.       begin
  1663.         PBC_Pkg.Timer;
  1664.         Producer.Produce (Terminate_Item);
  1665.         Consumer.Stop_On_Number (Terminate_Item);
  1666.       end;
  1667.  
  1668.     exception
  1669.       when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  1670.       when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  1671.       when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  1672.       when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  1673.       when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  1674.       when others           => PUT_LINE ("*** test aborted due to exception");
  1675.     end Time_PBC;
  1676.     pragma PAGE;
  1677.  
  1678.     procedure Time_PBTC is
  1679.       Buffer      : Buffer_Type;
  1680.       Consumer    : Called_Consumer_Type;
  1681.  
  1682.       task Producer is
  1683.         entry Produce (Num : in INTEGER);
  1684.         entry Have_Finished;
  1685.  
  1686.         -- Calls
  1687.            -- Buffer.Take_Item
  1688.       end Producer;
  1689.  
  1690.       
  1691.       task Transporter is
  1692.         -- Calls
  1693.            -- Buffer.Provide_Item
  1694.            -- Consumer.Take_Item
  1695.       end Transporter;
  1696.  
  1697.     Ada Benchmark Suite Version 1.0                              Page A-25
  1698.  
  1699.  
  1700.  
  1701.       task body Transporter is
  1702.         Item : INTEGER;
  1703.       begin
  1704.         loop
  1705.           Buffer.Provide_Item (Item);
  1706.           Consumer.Take_Item (Item);
  1707.         end loop;
  1708.       end Transporter;
  1709.  
  1710.  
  1711.       task body Producer is
  1712.         Count : INTEGER;
  1713.       begin
  1714.         loop
  1715.           accept Produce (Num : in INTEGER) do
  1716.             Count := Num;
  1717.           end Produce;
  1718.  
  1719.           exit when Count = Terminate_Item;
  1720.  
  1721.           for I in 1 .. Count loop
  1722.             Buffer.Take_Item (Continue_Item);
  1723.           end loop;
  1724.  
  1725.           accept Have_Finished;
  1726.         end loop;
  1727.       end Producer;
  1728.  
  1729.     begin
  1730.       NEW_LINE (2);
  1731.       PUT_LINE ("PBTC");
  1732.       PUT_LINE ("In this test a producer task communicates with a consumer task");
  1733.       PUT_LINE ("indirectly through a bounded buffer (buffer size = 2) with");
  1734.       PUT_LINE ("a transporter between the buffer and the consumer.");
  1735.       PUT_LINE ("Interaction with the main task takes place only at the beginning");
  1736.       PUT_LINE ("and at the end.");
  1737.       PUT_LINE ("Total number of task interactions is 3N+2.");
  1738.       NEW_LINE;
  1739.  
  1740.       declare
  1741.         procedure Tell_Producer (Iterations : in NATURAL) is
  1742.         begin
  1743.           Producer.Produce (Iterations);
  1744.           Producer.Have_Finished;
  1745.         end Tell_Producer;
  1746.  
  1747.         package PBTC_Pkg is new Benchmark
  1748.                 (Item_Of_Interest => Tell_Producer);
  1749.  
  1750.       begin
  1751.         PBTC_Pkg.Timer;
  1752.         Producer.Produce (Terminate_Item);         
  1753.     Ada Benchmark Suite Version 1.0                              Page A-26
  1754.  
  1755.  
  1756.         Consumer.Take_Item (Terminate_Item);  
  1757.         abort Transporter;            -- do this so buffer will die on its own
  1758.       end;
  1759.  
  1760.     exception
  1761.       when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  1762.       when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  1763.       when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  1764.       when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  1765.       when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  1766.       when others           => PUT_LINE ("*** test aborted due to exception");
  1767.     end Time_PBTC;
  1768.     pragma PAGE;
  1769.  
  1770.     procedure Time_PTBTC is
  1771.       Buffer      : Buffer_Type;
  1772.       Consumer    : Called_Consumer_Type;
  1773.  
  1774.       task Producer is
  1775.         entry Produce (Num : in INTEGER);
  1776.         entry Provide_Item (Item : out INTEGER);
  1777.         entry Have_Finished;
  1778.       end Producer;
  1779.  
  1780.       
  1781.       task C_Transporter is
  1782.         -- Calls
  1783.            -- Buffer.Provide_Item
  1784.            -- Consumer.Take_Item
  1785.       end C_Transporter;
  1786.  
  1787.  
  1788.       task body C_Transporter is
  1789.         Item : INTEGER;
  1790.       begin
  1791.         loop
  1792.           Buffer.Provide_Item (Item);
  1793.           Consumer.Take_Item (Item);
  1794.         end loop;
  1795.       end C_Transporter;
  1796.  
  1797.       
  1798.       task P_Transporter is
  1799.         -- Calls
  1800.            -- Producer.Provide_Item
  1801.            -- Buffer.Take_Item
  1802.       end P_Transporter;
  1803.  
  1804.  
  1805.       task body P_Transporter is
  1806.         Item : INTEGER;
  1807.       begin
  1808.         loop
  1809.     Ada Benchmark Suite Version 1.0                              Page A-27
  1810.  
  1811.  
  1812.           Producer.Provide_Item (Item);
  1813.           Buffer.Take_Item (Item);
  1814.         end loop;
  1815.       end P_Transporter;
  1816.  
  1817.  
  1818.       task body Producer is
  1819.         Count : INTEGER;
  1820.       begin
  1821.         loop
  1822.           accept Produce (Num : in INTEGER) do
  1823.             Count := Num;
  1824.           end Produce;
  1825.  
  1826.           exit when Count = Terminate_Item;
  1827.  
  1828.           for I in 1 .. Count loop
  1829.             accept Provide_Item (Item : out INTEGER) do
  1830.                Item := Continue_Item;
  1831.             end Provide_Item;
  1832.           end loop;
  1833.  
  1834.           accept Have_Finished;
  1835.  
  1836.         end loop;
  1837.       end Producer;
  1838.  
  1839.     begin
  1840.       NEW_LINE (2);
  1841.       PUT_LINE ("PTBTC");
  1842.       PUT_LINE ("In this test a producer task communicates with a consumer task");
  1843.       PUT_LINE ("indirectly through a bounded buffer (buffer size = 2) with");
  1844.       PUT_LINE ("a transporter for both the producer and the consumer.");
  1845.       PUT_LINE ("Interaction with the main task takes place only at the beginning");
  1846.       PUT_LINE ("and at the end.");
  1847.       PUT_LINE ("Total number of task interactions is 4N+2.");
  1848.       NEW_LINE;
  1849.  
  1850.       declare
  1851.         procedure Tell_Producer (Iterations : in NATURAL) is
  1852.         begin
  1853.           Producer.Produce (Iterations);
  1854.           Producer.Have_Finished;
  1855.         end Tell_Producer;
  1856.  
  1857.         package PTBTC_Pkg is new Benchmark
  1858.                 (Item_Of_Interest => Tell_Producer);
  1859.       begin
  1860.         PTBTC_Pkg.Timer;
  1861.         Producer.Produce (Terminate_Item);         
  1862.         Consumer.Take_Item (Terminate_Item); 
  1863.         abort P_Transporter, C_Transporter; -- do this so buffer will die on its own
  1864.       end;
  1865.     Ada Benchmark Suite Version 1.0                              Page A-28
  1866.  
  1867.  
  1868.  
  1869.     exception
  1870.       when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  1871.       when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  1872.       when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  1873.       when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  1874.       when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  1875.       when others           => PUT_LINE ("*** test aborted due to exception");
  1876.     end Time_PTBTC;
  1877.     pragma PAGE;
  1878.  
  1879.     procedure Time_Relay is
  1880.       Consumer    : Called_Consumer_Type;
  1881.       
  1882.  
  1883.       task Producer is
  1884.         entry Produce (Num : in INTEGER);
  1885.         entry Have_Finished;
  1886.  
  1887.         -- Calls
  1888.            -- Relay.Take_Item
  1889.       end Producer;
  1890.  
  1891.       
  1892.       task Relay is
  1893.         entry Take_Item (Item : in INTEGER);
  1894.  
  1895.         -- Calls
  1896.            -- Consumer.Take_Item
  1897.       end Relay;
  1898.  
  1899.  
  1900.       task body Relay is
  1901.         Item : INTEGER;
  1902.       begin
  1903.         loop
  1904.           accept Take_Item (Item : in INTEGER) do
  1905.             Relay.Item := Take_Item.Item;
  1906.           end Take_Item;
  1907.  
  1908.           exit when Item = Terminate_Item;
  1909.  
  1910.           Consumer.Take_Item (Item);
  1911.         end loop;
  1912.       end Relay;
  1913.  
  1914.  
  1915.       task body Producer is
  1916.         Count : INTEGER;
  1917.       begin
  1918.         loop
  1919.           accept Produce (Num : in INTEGER) do
  1920.             Count := Num;
  1921.     Ada Benchmark Suite Version 1.0                              Page A-29
  1922.  
  1923.  
  1924.           end Produce;
  1925.  
  1926.           exit when Count = Terminate_Item;
  1927.  
  1928.           for I in 1 .. Count loop
  1929.             Relay.Take_Item (Continue_Item);
  1930.           end loop;
  1931.      
  1932.           accept Have_Finished;
  1933.  
  1934.         end loop;
  1935.       end Producer;
  1936.  
  1937.     begin
  1938.       NEW_LINE (2);
  1939.       PUT_LINE ("RELAY");
  1940.       PUT_LINE ("In this test a producer task communicates with a consumer task");
  1941.       PUT_LINE ("indirectly through a relay.  In terms of the task communication");
  1942.       PUT_LINE ("model, this resembles the PBTC paradigm but in terms of");
  1943.       PUT_LINE ("performance it should resemble the PBC test.");
  1944.       PUT_LINE ("Interaction with the main task takes place only at the beginning");
  1945.       PUT_LINE ("and at the end.");
  1946.       PUT_LINE ("Total number of task interactions is 2N+2.");
  1947.       NEW_LINE;
  1948.  
  1949.       declare
  1950.         procedure Tell_Producer (Iterations : in NATURAL) is
  1951.         begin
  1952.           Producer.Produce (Iterations);
  1953.           Producer.Have_Finished;
  1954.         end Tell_Producer;
  1955.  
  1956.         package Relay_Pkg is new Benchmark
  1957.                 (Item_Of_Interest => Tell_Producer);
  1958.       begin
  1959.         Relay_Pkg.Timer;
  1960.         Producer.Produce (Terminate_Item);         
  1961.         Consumer.Take_Item (Terminate_Item);  
  1962.         Relay.Take_Item (Terminate_Item);          
  1963.       end;
  1964.  
  1965.     exception
  1966.       when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  1967.       when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  1968.       when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  1969.       when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  1970.       when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  1971.       when others           => PUT_LINE ("*** test aborted due to exception");
  1972.     end Time_Relay;
  1973.     pragma PAGE;
  1974.  
  1975.     begin
  1976.       PUT_LINE ("               Task Communication");
  1977.     Ada Benchmark Suite Version 1.0                              Page A-30
  1978.  
  1979.  
  1980.       NEW_LINE;
  1981.       PUT_LINE ("This test times task to task communication in order to determine");
  1982.       PUT_LINE ("the cost of the various task communication models.  Task");
  1983.       PUT_LINE ("activation and termination is not included in the timings.");
  1984.       Time_PC;
  1985.       Time_PC2;
  1986.       Time_PC3;
  1987.       Time_PBC;
  1988.       Time_PBTC;
  1989.       Time_PTBTC;
  1990.       Time_Relay;
  1991.  
  1992.     exception
  1993.       when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  1994.       when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  1995.       when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  1996.       when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  1997.       when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  1998.       when others           => PUT_LINE ("*** test aborted due to exception");
  1999.  
  2000.     end Do_Test;
  2001.  
  2002.     end Part2;
  2003.  
  2004.     Ada Benchmark Suite Version 1.0                              Page A-31
  2005.  
  2006.  
  2007.     A.13  PART3SPEC.ADA
  2008.  
  2009.     The following is a listing of the specification for the package Part_3:
  2010.  
  2011.  
  2012.  
  2013.     ---- test section 3
  2014.  
  2015.     package Part3 is
  2016.       Title : constant STRING := "task optimization";
  2017.       procedure Do_Test;
  2018.     end Part3;
  2019.     Ada Benchmark Suite Version 1.0                              Page A-32
  2020.  
  2021.  
  2022.     A.14  PART3.ADA
  2023.  
  2024.     The following is a listing of the body for the package Part_3:
  2025.  
  2026.  
  2027.  
  2028.     ------ test section 3 - task optimization techniques
  2029.     with TEXT_IO, Benchmark;
  2030.     use  TEXT_IO;
  2031.     package body Part3 is
  2032.  
  2033.     -- define the continue and terminate conditions for the tasks.
  2034.     Continue_Item : constant := 1;
  2035.     Terminate_Item : constant := -1;
  2036.  
  2037.     procedure Do_Test is
  2038.  
  2039.     procedure Time_Monitor is
  2040.  
  2041.       task General_Task is
  2042.         entry Take_Item (Item : in INTEGER);
  2043.         entry Provide_Item (Item : out INTEGER);
  2044.       end General_Task;
  2045.  
  2046.       task Monitor is
  2047.         entry Take_Item (Item : in INTEGER);
  2048.         entry Provide_Item (Item : out INTEGER);
  2049.       end Monitor;
  2050.  
  2051.       
  2052.       task body General_Task is
  2053.         Local : INTEGER;
  2054.       begin
  2055.         loop
  2056.           select
  2057.             accept Take_Item (Item : in INTEGER) do
  2058.               Local := Item;
  2059.             end Take_Item;
  2060.             Local := Local + 1;  -- the only difference is where this line is
  2061.           or
  2062.             accept Provide_Item (Item : out INTEGER) do
  2063.               Item := Local;
  2064.             end Provide_Item;
  2065.           or
  2066.             terminate;
  2067.           end select;
  2068.         end loop;
  2069.       end General_Task;
  2070.  
  2071.       
  2072.       task body Monitor is
  2073.         Local : INTEGER;
  2074.       begin
  2075.     Ada Benchmark Suite Version 1.0                              Page A-33
  2076.  
  2077.  
  2078.         loop
  2079.           select
  2080.             accept Take_Item (Item : in INTEGER) do
  2081.               Local := Item;
  2082.               Local := Local + 1;  -- the only difference is where this line is
  2083.             end Take_Item;
  2084.           or
  2085.             accept Provide_Item (Item : out INTEGER) do
  2086.               Item := Local;
  2087.             end Provide_Item;
  2088.           or
  2089.             terminate;
  2090.           end select;
  2091.         end loop;
  2092.       end Monitor;
  2093.  
  2094.  
  2095.     begin
  2096.       NEW_LINE (2);
  2097.       PUT_LINE ("MONITOR");
  2098.       PUT_LINE ("A task that contains no code outside of the accept bodies");
  2099.       PUT_LINE ("is considered to be a monitor.  It is possible to eliminate");
  2100.       PUT_LINE ("such a task by protecting the task entries with semaphores.");
  2101.       PUT_LINE ("In this test the main task interacts with a monitor and with");
  2102.       PUT_LINE ("a more general task in order to determine if this optimization");
  2103.       PUT_LINE ("is performed.  The monitor is the overhead item and the general");
  2104.       PUT_LINE ("task is the tested item.  If the net cpu is negative or near");
  2105.       PUT_LINE ("zero, it can be assumed that the optimization is not done.");
  2106.       NEW_LINE;
  2107.  
  2108.       declare
  2109.         procedure Send_To_Monitor (Iterations : in NATURAL) is
  2110.         begin
  2111.           for J in 1..Iterations loop
  2112.             Monitor.Take_Item (Continue_Item);
  2113.           end loop;
  2114.         end Send_To_Monitor;
  2115.  
  2116.         procedure Send_To_General (Iterations : in NATURAL) is
  2117.         begin
  2118.           for J in 1..Iterations loop
  2119.             General_Task.Take_Item (Continue_Item);
  2120.           end loop;
  2121.         end Send_To_General;
  2122.  
  2123.         package Monitor_Pkg is new Benchmark
  2124.                 (Overhead => Send_To_Monitor,
  2125.                  Item_Of_Interest => Send_To_General);
  2126.  
  2127.       begin
  2128.         Monitor_Pkg.Timer;
  2129.       end;
  2130.     end Time_Monitor;
  2131.     Ada Benchmark Suite Version 1.0                              Page A-34
  2132.  
  2133.  
  2134.     pragma PAGE;
  2135.  
  2136.     procedure Time_Single_Accept_Body is
  2137.  
  2138.       task Single_Accept is
  2139.         entry Take_Item (Item : in INTEGER);
  2140.         entry Stop;
  2141.       end Single_Accept;
  2142.  
  2143.       task body Single_Accept is
  2144.       begin
  2145.         loop
  2146.           select 
  2147.             accept Take_Item (Item : in INTEGER) do
  2148.               if Item = 0 then
  2149.                 PUT_LINE ("error in test (single accept)");
  2150.               end if;
  2151.             end Take_Item;
  2152.           or
  2153.             accept Stop;
  2154.             exit;
  2155.           end select;
  2156.         end loop;
  2157.       end Single_Accept;
  2158.  
  2159.  
  2160.       task Multiple_Accept is
  2161.         entry Take_Item (Item : in INTEGER);
  2162.         entry Stop;
  2163.       end Multiple_Accept;
  2164.  
  2165.       task body Multiple_Accept is
  2166.       begin
  2167.         loop
  2168.           select 
  2169.             accept Take_Item (Item : in INTEGER) do
  2170.               if Item = 0 then
  2171.                 PUT_LINE ("error in test (single accept)");
  2172.               end if;
  2173.             end Take_Item;
  2174.           or
  2175.             accept Stop;
  2176.             exit;
  2177.           end select;
  2178.  
  2179.              -- repeat select statement to create the multiple accept bodies
  2180.           select 
  2181.             accept Take_Item (Item : in INTEGER) do
  2182.               if Item = 0 then
  2183.                 PUT_LINE ("error in test (single accept)");
  2184.               end if;
  2185.             end Take_Item;
  2186.           or
  2187.     Ada Benchmark Suite Version 1.0                              Page A-35
  2188.  
  2189.  
  2190.             accept Stop;
  2191.             exit;
  2192.           end select;
  2193.         end loop;
  2194.       end Multiple_Accept;
  2195.  
  2196.  
  2197.     begin
  2198.       NEW_LINE (2);
  2199.       PUT_LINE ("SINGLE ACCEPT BODIES");
  2200.       PUT_LINE ("In the case where a task entry has a single accept body there");
  2201.       PUT_LINE ("is no need for the indirect referencing that may be used when");
  2202.       PUT_LINE ("a single entry has multiple accept bodies.");
  2203.       PUT_LINE ("This test checks to see if calls to entrys that have a ");
  2204.       PUT_LINE ("single accept body are more efficient than when multiple ");
  2205.       PUT_LINE ("accept bodies are used.  The single accept body is the ");
  2206.       PUT_LINE ("overhead item and the multiple accept body is the tested item.");
  2207.       PUT_LINE ("If the net cpu is negative or near zero, it can be assumed ");
  2208.       PUT_LINE ("that the optimization is not done.");
  2209.       NEW_LINE;
  2210.  
  2211.       declare
  2212.         procedure Send_To_Single (Iterations : in NATURAL) is
  2213.         begin
  2214.           for J in 1..Iterations loop
  2215.             Single_Accept.Take_Item (Continue_Item);
  2216.           end loop;
  2217.         end Send_To_Single;
  2218.  
  2219.         procedure Send_To_Multiple (Iterations : in NATURAL) is
  2220.         begin
  2221.           for J in 1..Iterations loop
  2222.             Multiple_Accept.Take_Item (Continue_Item);
  2223.           end loop;
  2224.         end Send_To_Multiple;
  2225.  
  2226.         package Accept_Pkg is new Benchmark
  2227.                 (Overhead => Send_To_Single,
  2228.                  Item_Of_Interest => Send_To_Multiple);
  2229.  
  2230.       begin
  2231.         Accept_Pkg.Timer;
  2232.         Single_Accept.Stop;   -- kill off the tasks
  2233.         Multiple_Accept.Stop;
  2234.       end;
  2235.     end Time_Single_Accept_Body;
  2236.     pragma PAGE;
  2237.  
  2238.     begin  -- Do_Test
  2239.       PUT_LINE ("               Task Optimizations");
  2240.       NEW_LINE;
  2241.       PUT_LINE ("This test determines if the implementation optimizes various");
  2242.       PUT_LINE ("special cases of tasking.  The specific optimizations being");
  2243.     Ada Benchmark Suite Version 1.0                              Page A-36
  2244.  
  2245.  
  2246.       PUT_LINE ("tested for are machine independent optimizations that have been");
  2247.       PUT_LINE ("discussed in the Ada literature. For each specific optimization");
  2248.       PUT_LINE ("the general case and the special case is timed.");
  2249.       PUT_LINE ("If the special case is significantly");
  2250.       PUT_LINE ("faster than the general case then it is assumed that the");
  2251.       PUT_LINE ("optimization technique is employed.");
  2252.  
  2253.       Time_Monitor;
  2254.       Time_Single_Accept_Body;
  2255.  
  2256.  
  2257.     exception
  2258.       when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  2259.       when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  2260.       when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  2261.       when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  2262.       when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  2263.       when others           => PUT_LINE ("*** test aborted due to exception");
  2264.  
  2265.     end Do_Test;
  2266.     end Part3;
  2267.     Ada Benchmark Suite Version 1.0                              Page A-37
  2268.  
  2269.  
  2270.     A.15  PART4SPEC.ADA
  2271.  
  2272.     The following is a listing of the specification for the package Part_4:
  2273.  
  2274.  
  2275.  
  2276.     ---- test section 4 - exception propagation
  2277.  
  2278.     package Part4 is
  2279.       Title : constant STRING := "exception propagation";
  2280.       procedure Do_Test;
  2281.     end Part4;
  2282.     Ada Benchmark Suite Version 1.0                              Page A-38
  2283.  
  2284.  
  2285.     A.16  PART4.ADA
  2286.  
  2287.     The following is a listing of the body for the package Part_4:
  2288.  
  2289.  
  2290.  
  2291.     ---------- test section 4  -- exception propagation
  2292.     with TEXT_IO, Benchmark;
  2293.     use  TEXT_IO;
  2294.     package body Part4 is
  2295.  
  2296.     procedure Do_Test is
  2297.  
  2298.     procedure Time_Simple_Exception is
  2299.     begin
  2300.       NEW_LINE (2);
  2301.       PUT_LINE ("EXCEPTION IN BLOCK");
  2302.       PUT_LINE ("In this test an exception is raised and handled in the same");
  2303.       PUT_LINE ("block.  The user defined exception is declared local to the");
  2304.       PUT_LINE ("block where it is raised.  The same block is timed without");
  2305.       PUT_LINE ("the exception being raised so the exception handling time can");
  2306.       PUT_LINE ("be determined.");
  2307.  
  2308.       declare 
  2309.         procedure Do_Raise (Iterations : in NATURAL) is
  2310.         begin
  2311.           for J in 1..Iterations loop
  2312.             declare
  2313.               Exc : exception;
  2314.             begin
  2315.               raise Exc;
  2316.               PUT_LINE ("ERROR: exception not raised as it should.");
  2317.               raise PROGRAM_ERROR;
  2318.             exception
  2319.               when Exc =>
  2320.                    null;
  2321.             end;
  2322.           end loop;
  2323.         end Do_Raise;
  2324.  
  2325.         procedure Dont_Raise (Iterations : in NATURAL) is
  2326.         begin
  2327.           for J in 1..Iterations loop
  2328.             declare
  2329.               Exc : exception;
  2330.             begin
  2331.               null;
  2332.             exception
  2333.               when Exc =>
  2334.                 PUT_LINE ("ERROR: exception improperly raised.");
  2335.             end;
  2336.           end loop;
  2337.         end Dont_Raise;
  2338.     Ada Benchmark Suite Version 1.0                              Page A-39
  2339.  
  2340.  
  2341.  
  2342.         package Simple_Exception_Pkg is new Benchmark
  2343.                 (Overhead => Dont_Raise,
  2344.                  Item_Of_Interest => Do_Raise);
  2345.  
  2346.       begin
  2347.         Simple_Exception_Pkg.Timer;
  2348.       end;
  2349.     end Time_Simple_Exception;
  2350.     pragma PAGE;
  2351.  
  2352.     procedure Time_Procedure_Exception is
  2353.       Exc         : exception;
  2354.  
  2355.         -- raise Exc if the parameter is true otherwise do nothing
  2356.       procedure Raise_Exc (Do_It : in BOOLEAN) is
  2357.       begin
  2358.         if Do_It then
  2359.           raise Exc;
  2360.         end if;
  2361.  
  2362.         if Do_It then  -- make sure the exception was raised
  2363.           PUT_LINE ("ERROR: exception not properly raised.");
  2364.           raise PROGRAM_ERROR;
  2365.         end if;
  2366.       end Raise_Exc;
  2367.  
  2368.     begin
  2369.       NEW_LINE (2);
  2370.       PUT_LINE ("EXCEPTION WITHIN PROCEDURE");
  2371.       PUT_LINE ("In this test an exception is raised in a procedure and");
  2372.       PUT_LINE ("handled by the caller. The same procedure call is timed without");
  2373.       PUT_LINE ("the exception being raised so the exception handling time can");
  2374.       PUT_LINE ("be determined.");
  2375.  
  2376.       declare
  2377.         procedure Do_Raise (Iterations : in NATURAL) is
  2378.         begin
  2379.           for J in 1..Iterations loop
  2380.             begin
  2381.               Raise_Exc (TRUE);
  2382.             exception -- handle exception raised by the procedure
  2383.               when Exc =>
  2384.                     null;
  2385.             end;
  2386.           end loop;
  2387.         end Do_Raise;
  2388.  
  2389.         procedure Dont_Raise (Iterations : in NATURAL) is
  2390.         begin
  2391.           for J in 1..Iterations loop
  2392.             begin
  2393.               Raise_Exc (FALSE);
  2394.     Ada Benchmark Suite Version 1.0                              Page A-40
  2395.  
  2396.  
  2397.             exception
  2398.               when Exc =>
  2399.                 PUT_LINE ("ERROR: exception improperly raised.");
  2400.             end;
  2401.           end loop;
  2402.         end Dont_Raise;
  2403.  
  2404.         package Procedure_Exception_Pkg is new Benchmark
  2405.                 (Overhead => Dont_Raise,
  2406.                  Item_Of_Interest => Do_Raise);
  2407.  
  2408.       begin
  2409.         Procedure_Exception_Pkg.Timer;
  2410.       end;
  2411.     end Time_Procedure_Exception;
  2412.     pragma PAGE;
  2413.  
  2414.     procedure Time_Task_Propagation is
  2415.       Exc         : exception;
  2416.  
  2417.       task Some_Task is
  2418.         entry Raise_Exc (Do_It : in BOOLEAN);
  2419.       end Some_Task;
  2420.  
  2421.       task body Some_Task is
  2422.       begin
  2423.         loop
  2424.           begin
  2425.             select
  2426.               accept Raise_Exc (Do_It : in BOOLEAN) do
  2427.                 -- raise Exc if the parameter is true otherwise do nothing
  2428.                 if Do_It then
  2429.                   raise Exc;
  2430.                 end if;
  2431.       
  2432.                 if Do_It then  -- make sure the exception was raised
  2433.                   PUT_LINE ("ERROR: exception not properly raised.");
  2434.                   raise PROGRAM_ERROR;
  2435.                 end if;
  2436.               end Raise_Exc;
  2437.             or 
  2438.               terminate;
  2439.             end select;
  2440.           exception
  2441.             when Exc => null;
  2442.           end;
  2443.         end loop;
  2444.       end Some_Task;
  2445.  
  2446.     begin
  2447.       NEW_LINE (2);
  2448.       PUT_LINE ("EXCEPTION IN ENTRY");
  2449.       PUT_LINE ("In this test an exception is raised during a rendezvous.");
  2450.     Ada Benchmark Suite Version 1.0                              Page A-41
  2451.  
  2452.  
  2453.       PUT_LINE ("The exception is handled in both the calling environment and");
  2454.       PUT_LINE ("in the task.  The same entry is timed without");
  2455.       PUT_LINE ("the exception being raised so the exception handling time can");
  2456.       PUT_LINE ("be determined.");
  2457.  
  2458.       declare
  2459.         procedure Do_Raise (Iterations : in NATURAL) is
  2460.         begin
  2461.           for J in 1..Iterations loop
  2462.             begin
  2463.               Some_Task.Raise_Exc (TRUE);
  2464.             exception -- handle exception raised by the procedure
  2465.               when Exc =>
  2466.                     null;
  2467.             end;
  2468.           end loop;
  2469.         end Do_Raise;
  2470.  
  2471.         procedure Dont_Raise (Iterations : in NATURAL) is
  2472.         begin
  2473.           for J in 1..Iterations loop
  2474.             begin
  2475.               Some_Task.Raise_Exc (FALSE);
  2476.             exception
  2477.               when Exc =>
  2478.                 PUT_LINE ("ERROR: exception improperly raised.");
  2479.             end;
  2480.           end loop;
  2481.         end Dont_Raise;
  2482.  
  2483.         package Task_Exception_Pkg is new Benchmark
  2484.                 (Overhead => Dont_Raise,
  2485.                  Item_Of_Interest => Do_Raise);
  2486.  
  2487.       begin
  2488.         Task_Exception_Pkg.Timer;
  2489.       end;
  2490.     end Time_Task_Propagation;
  2491.     pragma PAGE;
  2492.  
  2493.     begin  -- Do_Test
  2494.       PUT_LINE ("               Exception Propagation");
  2495.       NEW_LINE;
  2496.       PUT_LINE ("This test times exception propagation in various contexts");
  2497.       PUT_LINE ("including propagating an exception to a calling task during a");
  2498.       PUT_LINE ("rendezvous.");
  2499.  
  2500.       Time_Simple_Exception;
  2501.       Time_Procedure_Exception;
  2502.       Time_Task_Propagation;
  2503.  
  2504.     exception
  2505.       when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  2506.     Ada Benchmark Suite Version 1.0                              Page A-42
  2507.  
  2508.  
  2509.       when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  2510.       when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  2511.       when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  2512.       when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  2513.       when others           => PUT_LINE ("*** test aborted due to exception");
  2514.     end Do_Test;
  2515.     end Part4;
  2516.     Ada Benchmark Suite Version 1.0                              Page A-43
  2517.  
  2518.  
  2519.     A.17  PART5SPEC.ADA
  2520.  
  2521.     The following is a listing of the specification for the package Part_5:
  2522.  
  2523.  
  2524.  
  2525.     ---- test section 5
  2526.  
  2527.     package Part5 is
  2528.       Title : constant STRING := "task interaction";
  2529.       procedure Do_Test;
  2530.     end Part5;
  2531.     Ada Benchmark Suite Version 1.0                              Page A-44
  2532.  
  2533.  
  2534.     A.18  PART5.ADA
  2535.  
  2536.     The following is a listing of the body for the package Part_5:
  2537.  
  2538.  
  2539.  
  2540.     --- test section 5  --  task interaction
  2541.     with TEXT_IO, Benchmark;
  2542.     use  TEXT_IO;
  2543.     package body Part5 is
  2544.  
  2545.       -- define the continue and terminate conditions for the tasks
  2546.       Continue_Item : constant := 1;
  2547.       Terminate_Item : constant := -1;
  2548.  
  2549.       -- task types that are common to several tests
  2550.  
  2551.       task type Called_Consumer_Type_1 is
  2552.             -- consumer is to take items until 
  2553.             -- a value of Terminate_Item is accepted.
  2554.         entry Take_Item (Item : in INTEGER);
  2555.       end Called_Consumer_Type_1;
  2556.  
  2557.  
  2558.       task type Called_Consumer_Type_2 is
  2559.             -- consumer is to take items until 
  2560.             -- a value of Terminate_Item is accepted.
  2561.             -- However, enabling takes must be done first.
  2562.         entry Take_Item (Item : in INTEGER);
  2563.         entry Enable_Takes;
  2564.       end Called_Consumer_Type_2;
  2565.  
  2566.  
  2567.       task body Called_Consumer_Type_1 is
  2568.         Item : INTEGER;
  2569.       begin
  2570.         loop   
  2571.           accept Take_Item (Item : in INTEGER) do
  2572.             Called_Consumer_Type_1.Item := Item;
  2573.           end Take_Item;
  2574.  
  2575.           exit when Item = Terminate_Item;
  2576.  
  2577.         end loop;
  2578.       end Called_Consumer_Type_1;
  2579.  
  2580.       task body Called_Consumer_Type_2 is
  2581.         Item : INTEGER;
  2582.       begin
  2583.         accept Enable_Takes;
  2584.         loop   
  2585.           accept Take_Item (Item : in INTEGER) do
  2586.             Called_Consumer_Type_2.Item := Item;
  2587.     Ada Benchmark Suite Version 1.0                              Page A-45
  2588.  
  2589.  
  2590.           end Take_Item;
  2591.  
  2592.           exit when Item = Terminate_Item;
  2593.  
  2594.         end loop;
  2595.       end Called_Consumer_Type_2;
  2596.     pragma PAGE;
  2597.  
  2598.     procedure Do_Test is
  2599.  
  2600.     procedure Time_Procedure_Calls is
  2601.       Finished    : BOOLEAN := FALSE;
  2602.  
  2603.       procedure Take_Number (Num : in INTEGER) is
  2604.       begin
  2605.         -- note that Num is never 0.  The conditional recursion is to help
  2606.         -- prevent the compiler from making this procedure implicitly inline.
  2607.         if Num <= 0 then
  2608.            Take_Number (Num + 1);
  2609.         else
  2610.           Finished := Num = 1;
  2611.         end if;
  2612.       end Take_Number;
  2613.  
  2614.       procedure Give_Number (Iterations : in NATURAL) is
  2615.       begin
  2616.         for J in 1..Iterations loop
  2617.           Take_Number (1);
  2618.         end loop;
  2619.       end Give_Number;
  2620.  
  2621.     begin
  2622.       NEW_LINE (2);
  2623.       PUT_LINE ("PROCEDURE CALLING");
  2624.       PUT_LINE ("In this test the time to do a procedure call is measured");
  2625.       PUT_LINE ("so it can be compared to a task entry call.  The procedure");
  2626.       PUT_LINE ("contains a minimum amount of code - just enough to keep a");
  2627.       PUT_LINE ("compiler from thinking it can be eliminated.");
  2628.       NEW_LINE;
  2629.  
  2630.       declare
  2631.         package Procedure_Pkg is new Benchmark
  2632.                 (Item_Of_Interest => Give_Number);
  2633.       begin
  2634.         Procedure_Pkg.Timer;
  2635.       end;
  2636.  
  2637.     exception
  2638.       when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  2639.       when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  2640.       when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  2641.       when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  2642.       when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  2643.     Ada Benchmark Suite Version 1.0                              Page A-46
  2644.  
  2645.  
  2646.       when others           => PUT_LINE ("*** test aborted due to exception");
  2647.     end Time_Procedure_Calls;
  2648.     pragma PAGE;
  2649.  
  2650.     procedure Time_Conditional_Entry is
  2651.       Enabled_Task   : Called_Consumer_Type_1;
  2652.       Disabled_Task  : Called_Consumer_Type_2;
  2653.       Not_Accepted_Err,
  2654.       Accepted_Err : INTEGER := 0;
  2655.  
  2656.       procedure Not_Accepted (Iterations : in NATURAL) is
  2657.       begin
  2658.         for J in 1..Iterations-1 loop  -- -1 to account for Enable call
  2659.           select
  2660.             Disabled_Task.Take_Item (Continue_Item);
  2661.             Not_Accepted_Err := Not_Accepted_Err + 1;
  2662.           else
  2663.             null;
  2664.           end select;
  2665.         end loop;
  2666.       end Not_Accepted;
  2667.  
  2668.       procedure Accepted (Iterations : in NATURAL) is
  2669.       begin
  2670.         for J in 1..Iterations-1 loop  -- -1 to account for Enable call
  2671.           select
  2672.             Enabled_Task.Take_Item (Continue_Item);
  2673.           else
  2674.             Accepted_Err := Accepted_Err + 1;
  2675.           end select;
  2676.         end loop;
  2677.       end Accepted;
  2678.  
  2679.     begin
  2680.       NEW_LINE (2);
  2681.       PUT_LINE ("CONDITIONAL ENTRY");
  2682.       PUT_LINE ("In this test the main task calls a consumer task with a");
  2683.       PUT_LINE ("conditional entry call.  The test tries calls that are not");
  2684.       PUT_LINE ("accepted then tries calls that are accepted.");
  2685.       PUT_LINE ("Since the consumer is the same type of consumer used in the");
  2686.       PUT_LINE ("other producer/consumer tests these results can be compared");
  2687.       PUT_LINE ("to the simple producer/consumer test.");
  2688.       NEW_LINE;
  2689.                                                                        
  2690.       declare
  2691.         package Conditional_Pkg is new Benchmark
  2692.                 (Overhead => Not_Accepted,
  2693.                  Item_Of_Interest => Accepted);
  2694.       begin
  2695.         Conditional_Pkg.Timer;
  2696.         Enabled_Task.Take_Item (Terminate_Item);  -- kill off the tasks
  2697.         Disabled_Task.Enable_Takes;
  2698.         Disabled_Task.Take_Item (Terminate_Item);  
  2699.     Ada Benchmark Suite Version 1.0                              Page A-47
  2700.  
  2701.  
  2702.       end;
  2703.  
  2704.     exception
  2705.       when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  2706.       when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  2707.       when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  2708.       when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  2709.       when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  2710.       when others           => PUT_LINE ("*** test aborted due to exception");
  2711.     end Time_Conditional_Entry;
  2712.     pragma PAGE;
  2713.  
  2714.     procedure Time_Timed_Entry is
  2715.       Enabled_Task   : Called_Consumer_Type_1;
  2716.       Disabled_Task   : Called_Consumer_Type_2;
  2717.       Not_Accepted_Err,
  2718.       Accepted_Err : INTEGER := 0;
  2719.  
  2720.       procedure Not_Accepted (Iterations : in NATURAL) is
  2721.       begin
  2722.         for J in 1..Iterations loop
  2723.           select
  2724.             Disabled_Task.Take_Item (Continue_Item);
  2725.             Not_Accepted_Err := Not_Accepted_Err + 1;
  2726.           or
  2727.             delay 0.0;
  2728.           end select;
  2729.         end loop;
  2730.       end Not_Accepted;
  2731.  
  2732.       procedure Accepted (Iterations : in NATURAL) is
  2733.       begin
  2734.         for J in 1..Iterations loop
  2735.           select
  2736.             Enabled_Task.Take_Item (Continue_Item);
  2737.           or
  2738.             delay 0.0;
  2739.             Accepted_Err := Accepted_Err + 1;
  2740.           end select;
  2741.         end loop;
  2742.       end Accepted;
  2743.  
  2744.     begin
  2745.       NEW_LINE (2);
  2746.       PUT_LINE ("TIMED ENTRY");
  2747.       PUT_LINE ("In this test the main task calls a consumer task with a");
  2748.       PUT_LINE ("timed entry call with a time limit of 0.0.  The test tries");
  2749.       PUT_LINE ("calls that are not accepted then tries calls that are accepted.");
  2750.       PUT_LINE ("Since the consumer is the same type of consumer used in the");
  2751.       PUT_LINE ("other producer/consumer tests these results can be compared");
  2752.       PUT_LINE ("to the simple producer/consumer test.");
  2753.       NEW_LINE;
  2754.  
  2755.     Ada Benchmark Suite Version 1.0                              Page A-48
  2756.  
  2757.  
  2758.       declare
  2759.         package Timed_Entry_Pkg is new Benchmark
  2760.                 (Overhead => Not_Accepted,
  2761.                  Item_Of_Interest => Accepted);
  2762.       begin
  2763.         Timed_Entry_Pkg.Timer;
  2764.         Enabled_Task.Take_Item (Terminate_Item);  -- kill off the tasks
  2765.         Disabled_Task.Enable_Takes;
  2766.         Disabled_Task.Take_Item (Terminate_Item);
  2767.       end;
  2768.  
  2769.     exception
  2770.       when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  2771.       when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  2772.       when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  2773.       when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  2774.       when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  2775.       when others           => PUT_LINE ("*** test aborted due to exception");
  2776.     end Time_Timed_Entry;
  2777.     pragma PAGE;
  2778.  
  2779.     procedure Time_Family is
  2780.       
  2781.       type Family is range 1 .. 10;  -- size of entry family
  2782.       Family_Member : Family := 3;   -- this is the one we will use
  2783.  
  2784.       task Some_Task is
  2785.             -- consumer is to take items until 
  2786.             -- a value of Terminat_Item is accepted.
  2787.         entry Take_Item (Family)(Item : in INTEGER);
  2788.       end Some_Task;
  2789.  
  2790.  
  2791.       task body Some_Task is
  2792.         Item : INTEGER;
  2793.       begin
  2794.         loop
  2795.           accept Take_Item (Family_Member) (Item : in INTEGER) do
  2796.             Some_Task.Item := Item;
  2797.           end Take_Item;
  2798.  
  2799.           exit when Item = Terminate_Item;
  2800.  
  2801.         end loop;
  2802.       end Some_Task;
  2803.  
  2804.  
  2805.     begin
  2806.       NEW_LINE (2);
  2807.       PUT_LINE ("FAMILY OF ENTRIES");
  2808.       PUT_LINE ("This test is similar to the simple producer/consumer (SIMPLE PC)");
  2809.       PUT_LINE ("in that the main task produces integer values that are consumed");
  2810.       PUT_LINE ("by a consumer task.  The difference is that the consumer task");
  2811.     Ada Benchmark Suite Version 1.0                              Page A-49
  2812.  
  2813.  
  2814.       PUT_LINE ("uses a family of entries instead of a single entry.");
  2815.       NEW_LINE;
  2816.  
  2817.       declare
  2818.         procedure Send_Item (Iterations : in NATURAL) is
  2819.         begin
  2820.           for J in 1..Iterations Loop
  2821.             Some_Task.Take_Item (Family_Member) (Continue_Item);
  2822.           end loop;
  2823.         end Send_Item;
  2824.  
  2825.         package Family_Pkg is new Benchmark
  2826.                 (Item_Of_Interest => Send_Item);
  2827.  
  2828.       begin
  2829.         Family_Pkg.Timer;
  2830.         Some_Task.Take_Item (Family_Member) (Terminate_Item);
  2831.       end;
  2832.  
  2833.     exception
  2834.       when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  2835.       when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  2836.       when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  2837.       when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  2838.       when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  2839.       when others           => PUT_LINE ("*** test aborted due to exception");
  2840.     end Time_Family;
  2841.     pragma PAGE;
  2842.  
  2843.     procedure Time_Simple_Sync is
  2844.       task Sync is
  2845.         entry Pass;
  2846.       end Sync;
  2847.  
  2848.       task body Sync is
  2849.       begin
  2850.         loop
  2851.           accept Pass;
  2852.         end loop;
  2853.       end Sync;
  2854.  
  2855.     begin
  2856.       NEW_LINE (2);
  2857.       PUT_LINE ("SIMPLE SYNCHRONIZATION");
  2858.       PUT_LINE ("This test times the use of a simple synchronization task entry.");
  2859.       PUT_LINE ("In this type of task interaction no parameters are passed to the");
  2860.       PUT_LINE ("task entry and there is no body for the accept. The called task");
  2861.       PUT_LINE ("loops on an unconditional accept.");
  2862.       NEW_LINE;
  2863.  
  2864.       declare
  2865.         procedure Call_Sync (Iterations : in NATURAL) is
  2866.         begin
  2867.     Ada Benchmark Suite Version 1.0                              Page A-50
  2868.  
  2869.  
  2870.           for J in 1..Iterations loop
  2871.             Sync.Pass;
  2872.           end loop;
  2873.         end Call_Sync;
  2874.  
  2875.         package Simple_Sync_Pkg is new Benchmark
  2876.                 (Item_Of_Interest => Call_Sync);
  2877.  
  2878.       begin
  2879.         Simple_Sync_Pkg.Timer;
  2880.         abort Sync;   -- kill off the task
  2881.       end;
  2882.  
  2883.     exception
  2884.       when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  2885.       when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  2886.       when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  2887.       when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  2888.       when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  2889.       when others           => PUT_LINE ("*** test aborted due to exception");
  2890.     end Time_Simple_Sync;
  2891.     pragma PAGE;
  2892.  
  2893.     procedure Time_Sync_With_Term is
  2894.       task Sync is
  2895.         entry Pass;
  2896.       end Sync;
  2897.  
  2898.       task body Sync is
  2899.       begin
  2900.         loop
  2901.           select
  2902.             accept Pass;
  2903.           or
  2904.             terminate;
  2905.           end select;
  2906.         end loop;
  2907.       end Sync;
  2908.  
  2909.     begin
  2910.       NEW_LINE (2);
  2911.       PUT_LINE ("SYNCHRONIZATION WITH TERMINATION");
  2912.       PUT_LINE ("This test times the use of a simple synchronization task entry.");
  2913.       PUT_LINE ("In this type of task interaction no parameters are passed to the");
  2914.       PUT_LINE ("task entry and there is no body for the accept. The called task");
  2915.       PUT_LINE ("loops on an select statement containing an accept and a");
  2916.       PUT_LINE ("terminate alternative.");
  2917.       NEW_LINE;
  2918.  
  2919.       declare
  2920.         procedure Call_Sync (Iterations : in NATURAL) is
  2921.         begin
  2922.           for J in 1..Iterations loop
  2923.     Ada Benchmark Suite Version 1.0                              Page A-51
  2924.  
  2925.  
  2926.             Sync.Pass;
  2927.           end loop;
  2928.         end Call_Sync;
  2929.  
  2930.         package Sync_Term_Pkg is new Benchmark
  2931.                 (Item_Of_Interest => Call_Sync);
  2932.  
  2933.       begin
  2934.         Sync_Term_Pkg.Timer;
  2935.       end;
  2936.  
  2937.     exception
  2938.       when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  2939.       when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  2940.       when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  2941.       when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  2942.       when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  2943.       when others           => PUT_LINE ("*** test aborted due to exception");
  2944.     end Time_Sync_With_Term;
  2945.     pragma PAGE;
  2946.  
  2947.     procedure Time_Term_Option is
  2948.       Open_Terminate : BOOLEAN := FALSE;
  2949.  
  2950.       task Sync is
  2951.         entry Pass;
  2952.       end Sync;
  2953.  
  2954.       task body Sync is
  2955.       begin
  2956.         loop
  2957.           select
  2958.             accept Pass;
  2959.           or
  2960.             when Open_Terminate =>
  2961.             terminate;
  2962.           end select;
  2963.         end loop;
  2964.       end Sync;
  2965.  
  2966.     begin
  2967.       NEW_LINE (2);
  2968.       PUT_LINE ("TERMINATE OPTION");
  2969.       PUT_LINE ("This test times the use of a simple synchronization task entry");
  2970.       PUT_LINE ("both without and with a terminate option.  The overhead test");
  2971.       PUT_LINE ("is for the time without the terminate option.");
  2972.       PUT_LINE ("In this type of task interaction no parameters are passed to the");
  2973.       PUT_LINE ("task entry and there is no body for the accept. The called task");
  2974.       PUT_LINE ("loops on an select statement containing an accept and a");
  2975.       PUT_LINE ("conditional terminate alternative.");
  2976.       NEW_LINE;
  2977.  
  2978.       declare
  2979.     Ada Benchmark Suite Version 1.0                              Page A-52
  2980.  
  2981.  
  2982.         procedure Closed_Terminate (Iterations : in NATURAL) is
  2983.         begin
  2984.           for J in 1..Iterations loop
  2985.             Sync.Pass;
  2986.           end loop;
  2987.         end Closed_Terminate;
  2988.  
  2989.         procedure Opened_Terminate (Iterations : in NATURAL) is
  2990.         begin         
  2991.           Open_Terminate := TRUE;
  2992.           for J in 1..Iterations loop
  2993.             Sync.Pass;
  2994.           end loop;
  2995.         end Opened_Terminate;
  2996.  
  2997.         package Term_Option_Pkg is new Benchmark
  2998.                 (Overhead => Closed_Terminate,
  2999.                  Item_Of_Interest => Opened_Terminate);
  3000.  
  3001.       begin
  3002.         Term_Option_Pkg.Timer;
  3003.       end;
  3004.  
  3005.     exception
  3006.       when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  3007.       when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  3008.       when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  3009.       when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  3010.       when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  3011.       when others           => PUT_LINE ("*** test aborted due to exception");
  3012.     end Time_Term_Option;
  3013.     pragma PAGE;
  3014.  
  3015.     begin
  3016.       PUT_LINE ("               Task Interaction");
  3017.       NEW_LINE;
  3018.       PUT_LINE ("This test times various task interactions in order to determine");
  3019.       PUT_LINE ("their relative cost. These tests are related to the task");
  3020.       PUT_LINE ("communication tests and in many cases the output should be");
  3021.       PUT_LINE ("compared to those tests (see each test for details).");
  3022.  
  3023.       Time_Procedure_Calls;
  3024.       Time_Conditional_Entry;
  3025.       Time_Timed_Entry;
  3026.       Time_Family;
  3027.       Time_Simple_Sync;
  3028.       Time_Sync_With_Term;
  3029.       Time_Term_Option;
  3030.  
  3031.     exception
  3032.       when CONSTRAINT_ERROR => PUT_LINE ("*** test aborted due to constraint err");
  3033.       when NUMERIC_ERROR    => PUT_LINE ("*** test aborted due to numeric error");
  3034.       when PROGRAM_ERROR    => PUT_LINE ("*** test aborted due to program error");
  3035.     Ada Benchmark Suite Version 1.0                              Page A-53
  3036.  
  3037.  
  3038.       when STORAGE_ERROR    => PUT_LINE ("*** test aborted due to storage error");
  3039.       when TASKING_ERROR    => PUT_LINE ("*** test aborted due to tasking error");
  3040.       when others           => PUT_LINE ("*** test aborted due to exception");
  3041.  
  3042.     end Do_Test;
  3043.  
  3044.     end Part5;
  3045.  
  3046.     Ada Benchmark Suite Version 1.0                              Page A-54
  3047.  
  3048.  
  3049.     A.19  DRIVER.ADA
  3050.  
  3051.     The following is a listing of the driver for the Tasking benchmark:
  3052.  
  3053.  
  3054.  
  3055.     ---------------- tasking benchmark main driver -----------------------
  3056.  
  3057.     ------------------ note that SYSTEM is included so that system dependent
  3058.     ------------------ characteristics can be displayed.
  3059.     with TEXT_IO, SYSTEM, CALENDAR;
  3060.     use  TEXT_IO;
  3061.  
  3062.     ------------------ all the tests are in packages PartN procedure Do_Test
  3063.     ------------------ where N ranges from 1 to the number of test sections
  3064.     with Part1, Part2, Part3, Part4, Part5;
  3065.  
  3066.     procedure Driver is
  3067.       Version : constant STRING := "August 1, 1986"; -- last modification date
  3068.  
  3069.  
  3070.       Quiet : BOOLEAN;  -- true implies no further prompting on each test
  3071.                         -- and that each test is to be run.
  3072.  
  3073.       Results : FILE_TYPE;     -- file where test results are written.
  3074.                                -- Do not use this file directly.  Instead, use
  3075.                                -- standard output for user messages and 
  3076.                                -- current output for test results.
  3077.  
  3078.     procedure Print_Header_Info is
  3079.     use SYSTEM;
  3080.     begin
  3081.       PUT_LINE ("                      Tasking Benchmark");
  3082.       NEW_LINE;
  3083.       PUT_LINE ("Benchmark Version of " & Version);
  3084.       PUT_LINE ("System is " & SYSTEM.NAME'IMAGE (SYSTEM_NAME));
  3085.  
  3086.       declare
  3087.         use CALENDAR;
  3088.         Yr : YEAR_NUMBER;
  3089.         Mo : MONTH_NUMBER;
  3090.         Da : DAY_NUMBER;
  3091.         Se : DAY_DURATION;
  3092.         Hr  : INTEGER range 0 .. 23;
  3093.         Min : INTEGER range 0 .. 59;
  3094.         Sec : INTEGER range 0 .. 86_400;  -- seconds in a day
  3095.       begin
  3096.         SPLIT (CLOCK, Yr, Mo, Da, Se);
  3097.         Sec := INTEGER (Se);
  3098.         Hr := Sec / 3600;
  3099.         Min := (Sec - Hr * 3600) / 60;
  3100.         PUT      ("Benchmark run on ");
  3101.         case Mo is
  3102.     Ada Benchmark Suite Version 1.0                              Page A-55
  3103.  
  3104.  
  3105.           when  1 => PUT ("January");
  3106.           when  2 => PUT ("February");
  3107.           when  3 => PUT ("March");
  3108.           when  4 => PUT ("April");
  3109.           when  5 => PUT ("May");
  3110.           when  6 => PUT ("June");
  3111.           when  7 => PUT ("July");
  3112.           when  8 => PUT ("August");
  3113.           when  9 => PUT ("September");
  3114.           when 10 => PUT ("October");
  3115.           when 11 => PUT ("November");
  3116.           when 12 => PUT ("December");
  3117.         end case;
  3118.         PUT_LINE (INTEGER'IMAGE (Da) & "," & INTEGER'IMAGE (Yr) & "   " & 
  3119.                   INTEGER'IMAGE (Hr * 100 + Min));
  3120.       end;
  3121.  
  3122.       declare
  3123.         package Float_Text_IO is new FLOAT_IO (FLOAT);
  3124.         X : FLOAT;
  3125.       begin
  3126.         PUT ("Basic Clock Period (SYSTEM.TICK) is ");
  3127.         X := FLOAT (TICK);
  3128.         Float_Text_IO.DEFAULT_EXP := 0;  -- dont want scientific notation
  3129.         Float_Text_IO.PUT (X);
  3130.         PUT_LINE (" seconds.");
  3131.       end;
  3132.  
  3133.       PUT_LINE ("INTEGER is represented with" & INTEGER'IMAGE (INTEGER'SIZE) &
  3134.                 " bits.");
  3135.       
  3136.       declare
  3137.         task type T;
  3138.         task body T is begin null; end T;
  3139.       begin
  3140.         PUT_LINE ("An empty task is allocated" & INTEGER'IMAGE (T'STORAGE_SIZE) &
  3141.                   " storage units.");
  3142.       end;
  3143.     end Print_Header_Info;
  3144.  
  3145.  
  3146.     function Ask (Question : STRING) return BOOLEAN is
  3147.       Ch : CHARACTER;
  3148.     begin
  3149.       PUT (STANDARD_OUTPUT, Question & " (Y/N)? ");
  3150.       loop
  3151.         GET (Ch);
  3152.         if (Ch = 'Y') or (Ch = 'y') then
  3153.           return TRUE;
  3154.         elsif (Ch = 'N') or (Ch = 'n') then
  3155.           return FALSE;
  3156.         end if;
  3157.       end loop;
  3158.     Ada Benchmark Suite Version 1.0                              Page A-56
  3159.  
  3160.  
  3161.     end Ask;
  3162.  
  3163.  
  3164.     procedure Open_Files is
  3165.       -- this procedure opens the output file for the results and makes
  3166.       -- this file the default output file.
  3167.  
  3168.       Name : STRING (1 .. 80);
  3169.       Len  : INTEGER range 0 .. Name'LAST;
  3170.     begin
  3171.       Try_To_Open:
  3172.       loop
  3173.         PUT ("File name for results (<cr> for console) ");
  3174.         GET_LINE (Name, Len);
  3175.         exit Try_To_Open when Len = 0;
  3176.           
  3177.         begin
  3178.           CREATE (Results, NAME => Name (1 .. Len));
  3179.           SET_OUTPUT (Results);
  3180.           exit Try_To_Open;
  3181.         exception
  3182.           when NAME_ERROR | USE_ERROR => PUT_LINE ("Cannot create file");
  3183.         end;
  3184.       end loop Try_To_Open;
  3185.     end Open_Files;
  3186.  
  3187.     begin  -- Driver
  3188.       PUT_LINE ("Tasking Benchmark");
  3189.       Open_Files;
  3190.       Quiet := Ask ("Do you wish to run all the tests");
  3191.  
  3192.       Print_Header_Info;
  3193.  
  3194.       if Quiet or else Ask ("Run " & Part1.Title & " timings") then
  3195.         NEW_PAGE;
  3196.         Part1.Do_Test;
  3197.       end if;
  3198.  
  3199.       if Quiet or else Ask ("Run " & Part2.Title & " timings") then
  3200.         NEW_PAGE;
  3201.         Part2.Do_Test;
  3202.       end if;
  3203.  
  3204.       if Quiet or else Ask ("Run " & Part3.Title & " timings") then
  3205.         NEW_PAGE;
  3206.         Part3.Do_Test;
  3207.       end if;
  3208.  
  3209.       if Quiet or else Ask ("Run " & Part4.Title & " timings") then
  3210.         NEW_PAGE;
  3211.         Part4.Do_Test;
  3212.       end if;
  3213.  
  3214.     Ada Benchmark Suite Version 1.0                              Page A-57
  3215.  
  3216.  
  3217.       if Quiet or else Ask ("Run " & Part5.Title & " timings") then
  3218.         NEW_PAGE;
  3219.         Part5.Do_Test;
  3220.       end if;
  3221.  
  3222.  
  3223.       -- other tests go here
  3224.  
  3225.  
  3226.       if LINE > 50 then
  3227.         NEW_PAGE;
  3228.       else
  3229.         NEW_LINE (10);
  3230.       end if;
  3231.  
  3232.       PUT_LINE (STANDARD_OUTPUT, "Test Complete");
  3233.     end Driver;
  3234.