1-- C940002.A
2--
3--
4--                             Grant of Unlimited Rights
5--
6--     Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
7--     F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
8--     unlimited rights in the software and documentation contained herein.
9--     Unlimited rights are defined in DFAR 252.227-7013(a)(19).  By making
10--     this public release, the Government intends to confer upon all
11--     recipients unlimited rights  equal to those held by the Government.
12--     These rights include rights to use, duplicate, release or disclose the
13--     released technical data and computer software in whole or in part, in
14--     any manner and for any purpose whatsoever, and to have or permit others
15--     to do so.
16--
17--                                    DISCLAIMER
18--
19--     ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
20--     DISCLOSED ARE AS IS.  THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
21--     WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
22--     SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
23--     OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
24--     PARTICULAR PURPOSE OF SAID MATERIAL.
25--*
26--
27-- OBJECTIVE:
28--      Check that a protected object provides coordinated access to shared
29--      data.  Check that it can implement a semaphore-like construct using a
30--      parameterless procedure which allows a specific maximum number of tasks
31--      to run and excludes all others
32--
33-- TEST DESCRIPTION:
34--      Implement a counting semaphore type that can be initialized to a
35--      specific number of available resources.  Declare an entry for
36--      requesting a resource and a procedure for releasing it.  Declare an
37--      object of this type, initialized to two resources.  Declare and start
38--      three tasks each of which asks for a resource.  Verify that only two
39--      resources are granted and that the last task in is queued.
40--
41--
42-- CHANGE HISTORY:
43--      06 Dec 94   SAIC    ACVC 2.0
44--
45--!
46
47
48package C940002_0 is
49     -- Semaphores
50
51  protected type Semaphore_Type (Resources_Available : Integer :=1) is
52    entry Request;
53    procedure Release;
54    function Available return Integer;
55  private
56    Currently_Available : Integer := Resources_Available;
57  end Semaphore_Type;
58
59  Max_Resources : constant Integer := 2;
60  Resource      : Semaphore_Type (Max_Resources);
61
62end C940002_0;
63 -- Semaphores;
64
65
66          --========================================================--
67
68
69package body C940002_0 is
70          -- Semaphores
71
72  protected body Semaphore_Type is
73
74    entry Request when Currently_Available >0 is  -- when granted, secures
75    begin                                         -- a resource
76      Currently_Available := Currently_Available - 1;
77    end Request;
78
79    procedure Release is                          -- when called, releases
80    begin                                         -- a resource
81      Currently_Available := Currently_Available + 1;
82    end Release;
83
84    function Available return Integer is          -- returns number of
85    begin                                         -- available resources
86      return Currently_Available;
87    end Available;
88
89  end Semaphore_Type;
90
91end C940002_0;
92 -- Semaphores;
93
94
95          --========================================================--
96
97
98package C940002_1 is
99     -- Task_Pkg
100
101  task type Requesting_Task is
102     entry Done;                        -- call on Done instructs the task
103  end Requesting_Task;                  -- to release resource
104
105  type Task_Ptr is access Requesting_Task;
106
107  protected Counter is
108    procedure Increment;
109    procedure Decrement;
110    function Number return integer;
111  private
112    Count : Integer := 0;
113  end Counter;
114
115  protected Hold_Lock is
116    procedure Lock;
117    procedure Unlock;
118    function  Locked return Boolean;
119  private
120    Lock_State  : Boolean := true;        -- starts out locked
121  end Hold_Lock;
122
123
124end C940002_1;
125 -- Task_Pkg
126
127
128          --========================================================--
129
130
131with Report;
132with C940002_0;
133  -- Semaphores;
134
135package body C940002_1 is
136          -- Task_Pkg is
137
138  protected body Counter is
139
140    procedure Increment is
141      begin
142        Count := Count + 1;
143      end Increment;
144
145    procedure Decrement is
146      begin
147        Count := Count - 1;
148      end Decrement;
149
150    function Number return Integer is
151      begin
152        return Count;
153      end Number;
154
155  end Counter;
156
157
158  protected body Hold_Lock is
159
160    procedure Lock is
161    begin
162      Lock_State := true;
163    end Lock;
164
165    procedure Unlock is
166    begin
167      Lock_State := false;
168    end Unlock;
169
170    function  Locked return Boolean is
171    begin
172      return Lock_State;
173    end Locked;
174
175  end Hold_Lock;
176
177
178  task body Requesting_Task is
179  begin
180    C940002_0.Resource.Request;        -- request a resource
181                                       -- if resource is not available,
182                                       -- task will be queued to wait
183    Counter.Increment;                 -- add to count of resources obtained
184    Hold_Lock.Unlock;                  -- and unlock Lock - system is stable;
185                                       -- status may now be queried
186
187    accept Done do                     -- hold resource until Done is called
188      C940002_0.Resource.Release;      -- release the resource and
189      Counter.Decrement;               -- note release
190    end Done;
191
192  exception
193    when others => Report.Failed ("Unexpected Exception in Requesting_Task");
194  end Requesting_Task;
195
196end C940002_1;
197 -- Task_Pkg;
198
199
200          --========================================================--
201
202
203with Report;
204with ImpDef;
205with C940002_0,
206  -- Semaphores,
207     C940002_1;
208  -- Task_Pkg;
209
210procedure C940002 is
211
212  package Semaphores renames C940002_0;
213  package Task_Pkg renames C940002_1;
214
215  Ptr1,
216  Ptr2,
217  Ptr3 : Task_Pkg.Task_Ptr;
218  Num  : Integer;
219
220  procedure Spinlock is
221    begin
222      -- loop until unlocked
223      while Task_Pkg.Hold_Lock.Locked loop
224        delay ImpDef.Minimum_Task_Switch;
225      end loop;
226      Task_Pkg.Hold_Lock.Lock;
227    end Spinlock;
228
229begin
230
231  Report.Test ("C940002", "Check that a protected record can be used to " &
232                          "control access to resources");
233
234  if (Task_Pkg.Counter.Number /=0)
235  or (Semaphores.Resource.Available /= 2) then
236    Report.Failed ("Wrong initial conditions");
237  end if;
238
239  Ptr1 := new Task_Pkg.Requesting_Task;   -- newly allocated task requests
240                                   -- resource; request for resource should
241                                   -- be granted
242  Spinlock;                        -- ensure that task obtains resource
243
244                                   -- Task 1 waiting for call to Done
245                                   -- One resource assigned to task 1
246                                   -- One resource still available
247  if (Task_Pkg.Counter.Number /= 1)
248  or (Semaphores.Resource.Available /= 1) then
249    Report.Failed ("Resource not assigned to task 1");
250  end if;
251
252  Ptr2 := new Task_Pkg.Requesting_Task;   -- newly allocated task requests
253                                   -- resource; request for resource should
254                                   -- be granted
255  Spinlock;                        -- ensure that task obtains resource
256
257                                   -- Task 1 waiting for call to Done
258                                   -- Task 2 waiting for call to Done
259                                   -- Resources held by tasks 1 and 2
260                                   -- No resources available
261  if (Task_Pkg.Counter.Number /= 2)
262  or (Semaphores.Resource.Available /= 0) then
263    Report.Failed ("Resource not assigned to task 2");
264  end if;
265
266  Ptr3 := new Task_Pkg.Requesting_Task;   -- newly allocated task requests
267                                   -- resource; request for resource should
268                                   -- be denied and task queued to wait for
269                                   -- next available resource
270
271
272  Ptr1.all.Done;                   -- Task 1 releases resource and lock
273                                   -- Resource should be given to queued task
274  Spinlock;                        -- ensure that resource is released
275
276
277                                   -- Task 1 holds no resource
278                                   -- One resource still assigned to task 2
279                                   -- One resource assigned to task 3
280                                   -- No resources available
281  if (Task_Pkg.Counter.Number /= 2)
282  or (Semaphores.Resource.Available /= 0) then
283    Report.Failed ("Resource not properly released/assigned to task 3");
284  end if;
285
286  Ptr2.all.Done;                   -- Task 2 releases resource and lock
287                                   -- No outstanding request for resource
288
289                                   -- Tasks 1 and 2 hold no resources
290                                   -- One resource assigned to task 3
291                                   -- One resource available
292  if (Task_Pkg.Counter.Number /= 1)
293  or (Semaphores.Resource.Available /= 1) then
294    Report.Failed ("Resource not properly released from task 2");
295  end if;
296
297  Ptr3.all.Done;                   -- Task 3 releases resource and lock
298
299                                   -- All resources released
300                                   -- All tasks terminated (or close)
301                                   -- Two resources available
302  if (Task_Pkg.Counter.Number /=0)
303  or (Semaphores.Resource.Available /= 2) then
304    Report.Failed ("Resource not properly released from task 3");
305  end if;
306
307  Report.Result;
308
309end C940002;
310