1-- C954010.A 2-- 3-- Grant of Unlimited Rights 4-- 5-- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687, 6-- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained 7-- unlimited rights in the software and documentation contained herein. 8-- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making 9-- this public release, the Government intends to confer upon all 10-- recipients unlimited rights equal to those held by the Government. 11-- These rights include rights to use, duplicate, release or disclose the 12-- released technical data and computer software in whole or in part, in 13-- any manner and for any purpose whatsoever, and to have or permit others 14-- to do so. 15-- 16-- DISCLAIMER 17-- 18-- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR 19-- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED 20-- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE 21-- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE 22-- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A 23-- PARTICULAR PURPOSE OF SAID MATERIAL. 24--* 25-- 26-- OBJECTIVE: 27-- Check that a requeue within an accept statement does not block. 28-- This test uses: Requeue to an entry in a different task 29-- Parameterless call 30-- Requeue with abort 31-- 32-- TEST DESCRIPTION: 33-- In the Distributor task, requeue two successive calls on the entries 34-- of two separate target tasks. Verify that the target tasks are 35-- run in parallel proving that the first requeue does not block 36-- while the first target rendezvous takes place. 37-- 38-- This series of tests uses a simulation of a transaction driven 39-- processing system. Line Drivers accept input from an external source 40-- and build them into transaction records. These records are then 41-- encapsulated in message tasks which remain extant for the life of the 42-- transaction in the system. The message tasks put themselves on the 43-- input queue of a Distributor which, from information in the 44-- transaction and/or system load conditions forwards them to other 45-- operating tasks. These in turn might forward the transactions to yet 46-- other tasks for further action. The routing is, in real life, 47-- dynamic and unpredictable at the time of message generation. All 48-- rerouting in this model is done by means of requeues. 49-- 50-- This test is directed towards the BLOCKING of the REQUEUE only 51-- If the original caller does not block, the outcome of the test will 52-- not be affected. If the original caller does not continue after 53-- the return, the test will not pass. 54-- If the requeue gets placed on the wrong entry a failing test could 55-- pass (eg. if the first message is delivered to the second 56-- computation task and the second message to the first) - a check for 57-- this condition is made in other tests 58-- 59-- 60-- CHANGE HISTORY: 61-- 06 Dec 94 SAIC ACVC 2.0 62-- 63--! 64 65with Report; 66with ImpDef; 67 68procedure C954010 is 69 70 -- Mechanism to count the number of Message tasks completed 71 protected TC_Tasks_Completed is 72 procedure Increment; 73 function Count return integer; 74 private 75 Number_Complete : integer := 0; 76 end TC_Tasks_Completed; 77 -- 78 TC_Expected_To_Complete : constant integer := 2; 79 80 81 task type Message_Task; 82 type acc_Message_Task is access Message_Task; 83 84 task Line_Driver is 85 entry Start; 86 end Line_Driver; 87 88 task Distributor is 89 entry Input; 90 end Distributor; 91 92 task Credit_Computation is 93 entry Input; 94 end Credit_Computation; 95 96 task Debit_Computation is 97 entry Input; 98 entry TC_Artificial_Rendezvous_1; -- test purposes only 99 entry TC_Artificial_Rendezvous_2; -- test purposes only 100 end Debit_Computation; 101 102 103 -- Mechanism to count the number of Message tasks completed 104 protected body TC_Tasks_Completed is 105 procedure Increment is 106 begin 107 Number_Complete := Number_Complete + 1; 108 end Increment; 109 110 function Count return integer is 111 begin 112 return Number_Complete; 113 end Count; 114 end TC_Tasks_Completed; 115 116 117 118 -- Assemble messages received from an external source 119 -- Creates a message task for each and sends this to a Distributor 120 -- for appropriate disposal around the network of tasks 121 -- Such a task would normally be designed to loop continuously 122 -- creating the messages as input is received. Simulate this 123 -- but limit it to two dummy messages for this test and allow it 124 -- to terminate at that point 125 -- 126 task body Line_Driver is 127 128 begin 129 130 accept Start; -- Wait for trigger from main 131 132 for i in 1..2 loop 133 declare 134 -- create a new message task 135 N : acc_Message_Task := new Message_Task; 136 begin 137 -- preparation code 138 null; -- stub 139 140 end; -- declare 141 end loop; 142 143 exception 144 when others => 145 Report.Failed ("Unexpected exception in Line_Driver"); 146 end Line_Driver; 147 148 149 task body Message_Task is 150 begin 151 -- Queue up on Distributor's Input queue 152 Distributor.Input; 153 154 -- After the required computations have been performed 155 -- return the message appropriately (probably to an output 156 -- line driver 157 null; -- stub 158 159 -- Increment to show completion of this task 160 TC_Tasks_Completed.Increment; 161 162 exception 163 when others => 164 Report.Failed ("Unexpected exception in Message_Task"); 165 166 end Message_Task; 167 168 169 -- Dispose each input message to the appropriate computation tasks 170 -- Normally this would be according to some parameters in the entry 171 -- but this simple test is using parameterless entries. 172 -- 173 task body Distributor is 174 Last_was_for_Credit_Computation : Boolean := false; -- switch 175 begin 176 loop 177 select 178 accept Input do 179 -- Determine to which task the message should be 180 -- distributed 181 -- For this test arbitrarily send the first to 182 -- Credit_Computation and the second to Debit_Computation 183 if Last_was_for_Credit_Computation then 184 requeue Debit_Computation.Input with abort; 185 else 186 Last_was_for_Credit_Computation := true; 187 requeue Credit_Computation.Input with abort; 188 end if; 189 end Input; 190 or 191 terminate; 192 end select; 193 end loop; 194 195 exception 196 when others => 197 Report.Failed ("Unexpected exception in Distributor"); 198 end Distributor; 199 200 201 -- Computation task. After the computation is performed the rendezvous 202 -- in the original message task is completed. 203 task body Credit_Computation is 204 begin 205 loop 206 select 207 accept Input do 208 -- Perform the computations required for this message 209 -- 210 null; -- stub 211 212 -- For the test: 213 -- Artificially rendezvous with Debit_Computation. 214 -- If the first requeue in Distributor has blocked 215 -- waiting for the current rendezvous to complete then the 216 -- second message will not be sent to Debit_Computation 217 -- which will still be waiting on its Input accept. 218 -- This task will HANG 219 -- 220 Debit_Computation.TC_Artificial_Rendezvous_1; 221 -- 222 end Input; 223 or 224 terminate; 225 end select; 226 end loop; 227 exception 228 when others => 229 Report.Failed ("Unexpected exception in Credit_Computation"); 230 end Credit_Computation; 231 232 233 -- Computation task. After the computation is performed the rendezvous 234 -- in the original message task is completed. 235 task body Debit_Computation is 236 Message_Count : integer := 0; 237 TC_AR1_is_complete : Boolean := false; 238 begin 239 loop 240 select 241 accept Input do 242 -- Perform the computations required for this message 243 null; -- stub 244 end Input; 245 Message_Count := Message_Count + 1; 246 or 247 -- Guard until the rendezvous with the message for this task 248 -- has completed 249 when Message_Count > 0 => 250 accept TC_Artificial_Rendezvous_1; -- see comments in 251 -- Credit_Computation above 252 TC_AR1_is_complete := true; 253 or 254 -- Completion rendezvous with the main procedure 255 when TC_AR1_is_complete => 256 accept TC_Artificial_Rendezvous_2; 257 or 258 terminate; 259 end select; 260 end loop; 261 exception 262 when others => 263 Report.Failed ("Unexpected exception in Debit_Computation"); 264 265 266 end Debit_Computation; 267 268 269begin -- c954010 270 Report.Test ("C954010", "Requeue in an accept body does not block"); 271 272 Line_Driver.Start; 273 274 -- Ensure that both messages were delivered to the computation tasks 275 -- This shows that both requeues were effective. 276 -- 277 Debit_Computation.TC_Artificial_Rendezvous_2; 278 279 -- Ensure that the message tasks completed 280 while (TC_Tasks_Completed.Count < TC_Expected_To_Complete) loop 281 delay ImpDef.Minimum_Task_Switch; 282 end loop; 283 284 Report.Result; 285 286end C954010; 287