1-- C954A01.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 if a task requeued without abort on a protected entry queue
28--      is aborted, the abort is deferred until the entry call completes,
29--      after which the task becomes completed.
30--
31-- TEST DESCRIPTION:
32--      Declare a protected type which simulates a printer device driver
33--      (foundation code).
34--
35--      Declare a task which simulates a printer server for multiple printers.
36--
37--      For the protected type, declare an entry with a barrier that is set
38--      false by a protected procedure (which simulates starting a print job
39--      on the printer), and is set true by a second protected procedure (which
40--      simulates a handler called when the printer interrupts, indicating
41--      that printing is done).
42--
43--      For the task, declare an entry whose corresponding accept statement
44--      contains a call to first protected procedure of the protected type
45--      (which sets the barrier of the protected entry to false), followed by
46--      a requeue with abort to the protected entry. Declare a second entry
47--      which does nothing.
48--
49--      Declare a "requesting" task which calls the printer server task entry
50--      (and thus executes the requeue). Attempt to abort the requesting
51--      task. Verify that it is not aborted. Call the second protected
52--      procedure of the protected type (the interrupt handler) and verify that
53--      the protected entry completes for the requesting task. Verify that
54--      the requesting task is then aborted.
55--
56-- TEST FILES:
57--      This test depends on the following foundation code:
58--
59--         F954A00.A
60--
61--
62-- CHANGE HISTORY:
63--      06 Dec 94   SAIC    ACVC 2.0
64--      10 Oct 96   SAIC    Added pragma elaborate.
65--
66--!
67
68package C954A01_0 is  -- Printer server abstraction.
69
70   -- Simulate a system with multiple printers. The entry Print requests
71   -- that data be printed on the next available printer. The entry call
72   -- is accepted when a printer is available, and completes when printing
73   -- is done.
74
75
76   task Printer_Server is
77      entry Print (File_Name : String);        -- Test the requeue statement.
78      entry Verify_Results;                    -- Artifice for test purposes.
79   end Printer_Server;
80
81end C954A01_0;
82
83
84     --==================================================================--
85
86
87with Report;
88with ImpDef;
89
90with F954A00;              -- Printer device abstraction.
91use  F954A00;
92pragma Elaborate(F954A00);
93
94package body C954A01_0 is  -- Printer server abstraction.
95
96   task body Printer_Server is
97      Printers_Busy  : Boolean    := True;
98      Index          : Printer_ID := 1;
99      Print_Accepted : Boolean    := False;
100   begin
101
102      loop
103         -- Wait for a printer to become available:
104
105         while Printers_Busy loop
106            Printers_Busy := False;                        -- Exit loop if
107                                                           -- entry accepted.
108            select
109               Printer(Index).Done_Printing;               -- Accepted immed.
110                                                           -- when printer is
111                                                           -- available.
112            else
113               Index := 1 + (Index mod Number_Of_Printers);-- Entry not immed.
114               Printers_Busy := True;                      -- accepted; keep
115            end select;                                    -- looping.
116         end loop;
117                                                           -- Value of Index
118                                                           -- at loop exit
119                                                           -- identifies the
120                                                           -- avail. printer.
121
122         -- Wait for a print request or terminate:
123
124         select
125            accept Print (File_Name : String) do
126               Print_Accepted := True;                     -- Allow
127                                                           -- Verify_Results
128                                                           -- to be accepted.
129
130               Printer(Index).Start_Printing (File_Name);  -- Begin printing on
131                                                           -- the available
132               --                        --                -- printer.
133               -- Requeue is tested here --
134               --                        --
135                                                           -- Requeue caller so
136               requeue Printer(Index).Done_Printing;       -- server task free
137                                                           -- to accept other
138            end Print;                                     -- requests.
139         or
140            --  Guard ensures that Verify_Results cannot be accepted
141            --  until after Print has been accepted. This avoids a
142            --  race condition in the main program.
143
144            when Print_Accepted => accept Verify_Results;  -- Artifice for
145                                                           -- testing purposes.
146         or
147            terminate;
148         end select;
149
150         -- Allow other tasks to get control
151         delay ImpDef.Long_Minimum_Task_Switch;
152
153      end loop;
154
155   exception
156      when others =>
157         Report.Failed ("Exception raised in Printer_Server task");
158   end Printer_Server;
159
160
161end C954A01_0;
162
163
164     --==================================================================--
165
166
167with Report;
168with ImpDef;
169
170with F954A00;    -- Printer device abstraction.
171with C954A01_0;  -- Printer server abstraction.
172
173use  C954A01_0;
174use  F954A00;
175
176procedure C954A01 is
177
178   Long_Enough : constant Duration := ImpDef.Long_Switch_To_New_Task;
179
180               --==============================================--
181
182   task Print_Request;                       -- Send a print request.
183
184   task body Print_Request is
185      My_File : constant String := "MYFILE.DAT";
186   begin
187      Printer_Server.Print (My_File);          -- Invoke requeue statement.
188      Report.Failed ("Task continued execution following entry call");
189   exception
190      when others =>
191         Report.Failed ("Exception raised in Print_Request task");
192   end Print_Request;
193
194               --==============================================--
195
196begin  -- Main program.
197
198   Report.Test ("C954A01", "Requeue without abort - check that the abort " &
199            "is deferred until after the rendezvous completes. (Task to PO)");
200
201   --  To pass this test, the following must be true:
202   --
203   --     (A) The abort of Print_Request is deferred until after the
204   --         Done_Printing entry body completes.
205   --     (B) Print_Request aborts after the Done_Printing entry call
206   --         completes.
207   --
208   --  Call the entry Verify_Results. The entry call will not be accepted
209   --  until after Print_Request has been requeued to Done_Printing.
210
211   Printer_Server.Verify_Results;           -- Accepted after Print_Request is
212                                            -- requeued to Done_Printing.
213
214   -- Simulate an application which needs access to the printer within
215   -- a specified time, and which aborts the current printer job if time
216   -- runs out.
217
218   select
219      Printer(1).Done_Printing;             -- Wait for printer to come free.
220   or
221      delay Long_Enough;                    -- Print job took too long.
222      abort Print_Request;                  -- Abort print job.
223   end select;
224
225   Printer_Server.Verify_Results;           -- Abortion completion point: force
226                                            -- abort to complete (if it's going
227                                            -- to).
228
229   --  Verify that the Done_Printing entry body has not yet completed,
230   --  and thus that Print_Request has not been aborted.
231
232   if Printer(1).Is_Done then
233      Report.Failed ("Target entry of requeue executed prematurely");
234   elsif Print_Request'Terminated then
235      Report.Failed ("Caller was aborted before entry was complete");
236   else
237
238      Printer(1).Handle_Interrupt;          -- Simulate a printer interrupt,
239                                            -- signaling that printing is
240                                            -- done.
241
242      --  The Done_Printing entry body will complete before the next protected
243      --  action is called (Printer(1).Is_Done). Verify (A) and (B): that the
244      --  Print_Request is aborted.
245
246      Printer_Server.Verify_Results;        -- Abortion completion point: force
247                                            -- Print_Request abort to complete.
248
249      if not Printer(1).Is_Done then
250         Report.Failed ("Target entry of requeue did not complete");
251      end if;
252
253      if not Print_Request'Terminated then
254         Report.Failed ("Task not aborted following completion of entry call");
255         abort Print_Request;               -- Try to kill hung task.
256      end if;
257
258   end if;
259
260   Report.Result;
261
262end C954A01;
263