aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/ada/acats/tests/c9/c953002.a
blob: d821bb24e4e5d0c58d77ede85aeed56aa84e54d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
-- C953002.A
--
--                             Grant of Unlimited Rights
--
--     Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
--     F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained 
--     unlimited rights in the software and documentation contained herein.
--     Unlimited rights are defined in DFAR 252.227-7013(a)(19).  By making 
--     this public release, the Government intends to confer upon all 
--     recipients unlimited rights  equal to those held by the Government.  
--     These rights include rights to use, duplicate, release or disclose the 
--     released technical data and computer software in whole or in part, in 
--     any manner and for any purpose whatsoever, and to have or permit others 
--     to do so.
--
--                                    DISCLAIMER
--
--     ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
--     DISCLOSED ARE AS IS.  THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED 
--     WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
--     SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE 
--     OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
--     PARTICULAR PURPOSE OF SAID MATERIAL.
--*
--
-- OBJECTIVE:
--      Check that the servicing of entry queues of a protected object 
--      continues until there are no open entries with queued calls
--      and that this takes place as part of a single protected 
--      operation.
--
-- TEST DESCRIPTION:
--      This test enqueues a bunch of tasks on the entries of the
--      protected object Main_PO.  At the same time another bunch of
--      of tasks are queued on the single entry of protected object
--      Holding_Pen.
--      Once all the tasks have had time to block, the main procedure
--      opens all the entries for Main_PO by calling the 
--      Start_Protected_Operation protected procedure.  This should
--      process all the pending callers as part of a single protected
--      operation.
--      During this protected operation, the entries of Main_PO release
--      the tasks blocked on Holding_Pen by calling the protected 
--      procedure Release.
--      Once released from Holding_Pen, the task immediately calls
--      an entry in Main_PO.
--      These new calls should not gain access to Main_PO until
--      the initial protected operation on that object completes.
--      The order in which the entry calls on Main_PO are taken is
--      recorded in a global array and checked after all the tasks
--      have terminated.
--
--
-- CHANGE HISTORY:
--      25 OCT 95   SAIC    ACVC 2.1
--      15 JAN 95   SAIC    Fixed deadlock problem.
--
--!

with Report;
procedure C953002 is
  Verbose : constant Boolean := False;

  Half_Tasks : constant := 15;   -- how many tasks of each group 
  Max_Tasks : constant := Half_Tasks * 2;  -- total number of tasks

  Note_Order : array (1..Max_Tasks) of Integer := (1..Max_Tasks => 0);
  Note_Cnt : Integer := 0;
begin
  Report.Test ("C953002",
               "Check that the servicing of entry queues handles all" &
               " open entries as part of a single protected operation");
  declare
     task type Assault_PO is
        entry Take_ID (Id : Integer);
     end Assault_PO;

     First_Wave  : array (1 .. Half_Tasks) of Assault_PO;
     Second_Wave : array (1 .. Half_Tasks) of Assault_PO;

     protected Main_PO is
        entry E0 (Who : Integer);
        entry E1 (Who : Integer);
        entry E2 (Who : Integer);
        entry E3 (Who : Integer);
        entry All_Present;
        procedure Start_Protected_Operation;
     private
        Open : Boolean := False;
     end Main_PO;

     protected Holding_Pen is
        -- Note that Release is called by tasks executing in 
        -- the protected object Main_PO.
        entry Wait (Who : Integer);
        entry All_Present;
        procedure Release;
     private
        Open : Boolean := False;
     end Holding_Pen;

     
     protected body Main_PO is
        procedure Start_Protected_Operation is
        begin
           Open := True;
           -- at this point all the First_Wave tasks are
           -- waiting at the entries and all of them should
           -- be processed as part of the protected operation.
        end Start_Protected_Operation;

        entry All_Present when E0'Count + E1'Count + E2'Count + E3'Count =
                               Max_Tasks / 2  is
        begin
           null;   -- all tasks are waiting
        end All_Present; 

        entry E0 (Who : Integer) when Open is
        begin
           Holding_Pen.Release;
           -- note the order in which entry calls are handled.
           Note_Cnt := Note_Cnt + 1;
           Note_Order (Note_Cnt) := Who;
        end E0;

        entry E1 (Who : Integer) when Open is
        begin
           Holding_Pen.Release;
           Note_Cnt := Note_Cnt + 1;
           Note_Order (Note_Cnt) := Who;
        end E1;

        entry E2 (Who : Integer) when Open is
        begin
           Holding_Pen.Release;
           Note_Cnt := Note_Cnt + 1;
           Note_Order (Note_Cnt) := Who;
        end E2;

        entry E3 (Who : Integer) when Open is
        begin
           Holding_Pen.Release;
           Note_Cnt := Note_Cnt + 1;
           Note_Order (Note_Cnt) := Who;
        end E3;
     end Main_PO;


     protected body Holding_Pen is
        procedure Release is
        begin
           Open := True;
        end Release;

        entry All_Present when Wait'Count = Max_Tasks / 2 is
        begin
           null;  -- all tasks waiting
        end All_Present;

        entry Wait (Who : Integer) when Open is
        begin
           null;  -- unblock the task
        end Wait;
     end Holding_Pen;

     task body Assault_PO is
        Me : Integer;
     begin
        accept Take_Id (Id : Integer) do
           Me := Id;
        end Take_Id;
        if Me >= 200 then
           Holding_Pen.Wait (Me);
        end if;
        case Me mod 4 is
           when 0 => Main_PO.E0 (Me);
           when 1 => Main_PO.E1 (Me);
           when 2 => Main_PO.E2 (Me);
           when 3 => Main_PO.E3 (Me);
           when others => null;  -- cant happen
        end case;
        if Verbose then
           Report.Comment ("task" & Integer'Image (Me) &
                           " done");
        end if;
     exception
        when others =>
           Report.Failed ("exception in task");
     end Assault_PO;

  begin   -- test encapsulation
     for I in First_Wave'Range loop
        First_Wave (I).Take_ID (100 + I);
     end loop;
     for I in Second_Wave'Range loop
        Second_Wave (I).Take_ID (200 + I);
     end loop;
     
     -- let all the tasks get blocked
     Main_PO.All_Present;
     Holding_Pen.All_Present; 

     -- let the games begin
     if Verbose then
        Report.Comment ("starting protected operation");
     end if;
     Main_PO.Start_Protected_Operation;

     -- wait for all the tasks to complete
     if Verbose then
        Report.Comment ("waiting for tasks to complete");
     end if;
  end;

  -- make sure all tasks registered their order
  if Note_Cnt /= Max_Tasks then
     Report.Failed ("task registration count wrong. " &
                    Integer'Image (Note_Cnt));
  end if;

  -- check the order in which entries were handled.
  -- all the 100 level items should be handled as part of the
  -- first protected operation and thus should be completed
  -- before any 200 level item.

  if Verbose then
     for I in 1..Max_Tasks loop
        Report.Comment ("order" & Integer'Image (I) & " is" &
                        Integer'Image (Note_Order (I))); 
     end loop;
  end if;
  for I in 2 .. Max_Tasks loop
     if Note_Order (I)   <  200 and
        Note_Order (I-1) >= 200 then
        Report.Failed ("protected operation failure" &
                       Integer'Image (Note_Order (I-1)) &
                       Integer'Image (Note_Order (I)));
     end if;
  end loop;
  
  Report.Result;
end C953002;