1-- C940A03.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 protected object provides coordinated access to
28--      shared data.  Check that it can implement a semaphore-like construct
29--      controlling access to shared data through procedure parameters to
30--      allow a specific maximum number of tasks to run and exclude all
31--      others.
32--
33-- TEST DESCRIPTION:
34--      Declare a resource descriptor tagged type.  Extend the type and
35--      use the extended type in a protected data structure.
36--      Implement a counting semaphore type that can be initialized to a
37--      specific number of available resources.  Declare an entry for
38--      requesting a specific resource and an procedure for releasing the
39--      same resource it.  Declare an object of this (protected) type,
40--      initialized to two resources.  Declare and start three tasks each
41--      of which asks for a resource.  Verify that only two resources are
42--      granted and that the last task in is queued.
43--
44--      This test models a multi-user operating system that allows a limited
45--      number of logins.  Users requesting login are modeled by tasks.
46--
47--
48-- TEST FILES:
49--      This test depends on the following foundation code:
50--
51--         F940A00
52--
53--
54-- CHANGE HISTORY:
55--      06 Dec 94   SAIC    ACVC 2.0
56--      13 Nov 95   SAIC    Fixed bugs for ACVC 2.0.1
57--
58--!
59
60package C940A03_0 is
61      --Resource_Pkg
62
63  -- General type declarations that will be extended to model available
64  -- logins
65
66  type Resource_ID_Type is range 0..10;
67  type Resource_Type is tagged record
68    Id : Resource_ID_Type := 0;
69  end record;
70
71end C940A03_0;
72  --Resource_Pkg
73
74--======================================--
75-- no body for C940A3_0
76--======================================--
77
78with F940A00;     -- Interlock_Foundation
79with C940A03_0;   -- Resource_Pkg;
80
81package C940A03_1 is
82     -- Semaphores
83
84  -- Models a counting semaphore that will allow up to a specific
85  -- number of logins
86  -- Users (tasks) request a login slot by calling the Request_Login
87  -- entry and logout by calling the Release_Login procedure
88
89  Max_Logins : constant Integer := 2;
90
91
92  type Key_Type is range 0..100;
93                                      -- When a user requests a login, an
94                                      -- identifying key will be returned
95  Init_Key : constant Key_Type := 0;
96
97  type Login_Record_Type is new C940A03_0.Resource_Type with record
98    Key  : Key_Type := Init_Key;
99  end record;
100
101
102  protected type Login_Semaphore_Type (Resources_Available : Integer :=1) is
103
104    entry     Request_Login   (Resource_Key : in out Login_Record_Type);
105    procedure Release_Login;
106    function  Available return Integer;  -- how many logins are available?
107  private
108    Logins_Avail : Integer  := Resources_Available;
109    Next_Key     : Key_Type := Init_Key;
110
111  end Login_Semaphore_Type;
112
113  Login_Semaphore      : Login_Semaphore_Type (Max_Logins);
114
115  --====== machinery for the test, not the model =====--
116  TC_Control_Message : F940A00.Interlock_Type;
117  function TC_Key_Val (Login_Rec : Login_Record_Type) return Integer;
118
119
120end C940A03_1;
121 -- Semaphores;
122
123--=========================================================--
124
125package body C940A03_1 is
126          -- Semaphores is
127
128  protected body Login_Semaphore_Type is
129
130    entry Request_Login (Resource_Key : in out Login_Record_Type)
131                                             when Logins_Avail > 0 is
132    begin
133      Next_Key := Next_Key + 1;        -- login process returns a key
134      Resource_Key.Key := Next_Key;     -- to the requesting user
135      Logins_Avail := Logins_Avail - 1;
136    end Request_Login;
137
138    procedure Release_Login is
139    begin
140      Logins_Avail := Logins_Avail + 1;
141    end Release_Login;
142
143    function Available return Integer is
144      begin
145        return Logins_Avail;
146      end Available;
147
148  end Login_Semaphore_Type;
149
150  function TC_Key_Val (Login_Rec : Login_Record_Type) return Integer is
151    begin
152      return Integer (Login_Rec.Key);
153    end TC_Key_Val;
154
155end C940A03_1;
156 -- Semaphores;
157
158--=========================================================--
159
160with C940A03_0;    -- Resource_Pkg,
161with C940A03_1;    -- Semaphores;
162
163package C940A03_2 is
164     -- Task_Pkg
165
166  package Semaphores renames C940A03_1;
167
168  task type User_Task_Type is
169
170     entry Login  (user_id : C940A03_0.Resource_Id_Type);
171                      -- instructs the task to ask for a login
172     entry Logout;    -- instructs the task to release the login
173     --=======================--
174     -- this entry is used to get information to verify test operation
175     entry Get_Status (User_Record : out Semaphores.Login_Record_Type);
176
177  end User_Task_Type;
178
179end C940A03_2;
180 -- Task_Pkg
181
182--=========================================================--
183
184with Report;
185with C940A03_0;   -- Resource_Pkg,
186with C940A03_1;   -- Semaphores,
187with F940A00;     -- Interlock_Foundation;
188
189package body C940A03_2 is
190          -- Task_Pkg
191
192  -- This task models a user requesting a login from the system
193  -- For control of this test, we can ask the task to login, logout, or
194  -- give us the current user record (containing login information)
195
196  task body User_Task_Type is
197    Rec  : Semaphores.Login_Record_Type;
198  begin
199    loop
200      select
201        accept Login (user_id : C940A03_0.Resource_Id_Type) do
202          Rec.Id := user_id;
203        end Login;
204
205        Semaphores.Login_Semaphore.Request_Login (Rec);
206                      -- request a resource; if resource is not available,
207                      -- task will be queued to wait
208
209        --== following is test control machinery ==--
210        F940A00.Counter.Increment;
211        Semaphores.TC_Control_Message.Post;
212               -- after resource is obtained, post message
213
214      or
215        accept Logout do
216          Semaphores.Login_Semaphore.Release_Login;
217                      -- release the resource
218          --== test control machinery ==--
219          F940A00.Counter.Decrement;
220        end Logout;
221        exit;
222
223      or
224        accept Get_Status (User_Record : out Semaphores.Login_Record_Type) do
225          User_Record := Rec;
226        end Get_Status;
227
228      end select;
229    end loop;
230
231  exception
232    when others => Report.Failed ("Exception raised in model user task");
233  end User_Task_Type;
234
235end C940A03_2;
236 -- Task_Pkg
237
238--=========================================================--
239
240with Report;
241with ImpDef;
242with C940A03_1;   -- Semaphores,
243with C940A03_2;   -- Task_Pkg,
244with F940A00;     -- Interlock_Foundation;
245
246procedure C940A03 is
247
248  package Semaphores renames C940A03_1;
249  package Users      renames C940A03_2;
250
251  Task1, Task2, Task3 : Users.User_Task_Type;
252  User_Rec            : Semaphores.Login_Record_Type;
253
254begin      -- Tasks start here
255
256  Report.Test ("C940A03", "Check that a protected object can coordinate " &
257                          "shared data access using procedure parameters");
258
259  if F940A00.Counter.Number /=0 then
260    Report.Failed ("Wrong initial conditions");
261  end if;
262
263  Task1.Login (1);               -- request resource; request should be granted
264  Semaphores.TC_Control_Message.Consume;
265                                 -- ensure that task obtains resource by
266                                 -- waiting for task to post message
267
268                                 -- Task 1 waiting for call to Logout
269                                 -- Others still available
270  Task1.Get_Status (User_Rec);
271  if (F940A00.Counter.Number /= 1)
272  or (Semaphores.Login_Semaphore.Available /=1)
273  or (Semaphores.TC_Key_Val (User_Rec) /= 1) then
274    Report.Failed ("Resource not assigned to task 1");
275  end if;
276
277  Task2.Login (2);               -- Request for resource should be granted
278  Semaphores.TC_Control_Message.Consume;
279                                 -- ensure that task obtains resource by
280                                 -- waiting for task to post message
281
282  Task2.Get_Status (User_Rec);
283  if (F940A00.Counter.Number /= 2)
284  or (Semaphores.Login_Semaphore.Available /=0)
285  or (Semaphores.TC_Key_Val (User_Rec) /= 2) then
286    Report.Failed ("Resource not assigned to task 2");
287  end if;
288
289
290  Task3.Login (3);               -- request for resource should be denied
291                                 -- and task queued
292
293
294                                 -- Tasks 1 and 2 holds resources
295                                 -- and are waiting for a call to Logout
296                                 -- Task 3 is queued
297
298  if (F940A00.Counter.Number /= 2)
299  or (Semaphores.Login_Semaphore.Available /=0) then
300    Report.Failed ("Resource incorrectly assigned to task 3");
301  end if;
302
303  Task1.Logout;                  -- released resource should be given to
304                                 -- queued task
305  Semaphores.TC_Control_Message.Consume;
306                                 -- wait for confirming message from task
307
308                                 -- Task 1 holds no resources
309                                 --   and is terminated (or will soon)
310                                 -- Tasks 2 and 3 hold resources
311                                 --   and are waiting for a call to Logout
312
313  Task3.Get_Status (User_Rec);
314  if (F940A00.Counter.Number /= 2)
315                      or (Semaphores.Login_Semaphore.Available /=0)
316                      or (Semaphores.TC_Key_Val (User_Rec) /= 3) then
317    Report.Failed ("Resource not properly released/assigned to task 3");
318  end if;
319
320  Task2.Logout;                  -- no outstanding request for released
321                                 -- resource
322                                 -- Tasks 1 and 2 hold no resources
323                                 -- Task 3 holds a resource
324                                 --   and is waiting for a call to Logout
325
326  if (F940A00.Counter.Number /= 1)
327                        or (Semaphores.Login_Semaphore.Available /=1) then
328    Report.Failed ("Resource not properly released from task 2");
329  end if;
330
331  Task3.Logout;
332
333                                 -- all resources have been returned
334                                 -- all tasks have terminated or will soon
335
336  if (F940A00.Counter.Number /=0)
337                          or (Semaphores.Login_Semaphore.Available /=2) then
338    Report.Failed ("Resource not properly released from task 3");
339  end if;
340
341  -- Ensure all tasks have terminated before calling Result
342  while not (Task1'terminated and
343             Task2'terminated and
344             Task3'terminated)     loop
345    delay ImpDef.Minimum_Task_Switch;
346  end loop;
347
348  Report.Result;
349
350end C940A03;
351