3 -- Grant of Unlimited Rights
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
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.
27 -- Check that a protected record can be used to control access to
28 -- resources (data internal to the protected record).
31 -- Declare a resource descriptor tagged type. Extend the type and
32 -- use the extended type in a protected data structure.
33 -- Implement a binary semaphore type. Declare an entry for
34 -- requesting a specific resource and an procedure for releasing the
35 -- same resource. Declare an object of this (protected) type.
36 -- Declare and start three tasks each of which asks for a resource
37 -- when directed to. Verify that resources are properly allocated
43 -- 12 DEC 93 SAIC Initial PreRelease version
44 -- 23 JUL 95 SAIC Second PreRelease version
45 -- 16 OCT 95 SAIC ACVC 2.1
46 -- 13 MAR 03 RLB Fixed race condition in test.
53 type ID_Type
is new Integer range 0..10;
54 type User_Descriptor_Type
is tagged record
58 end C940004_0
; -- Resource_Pkg
60 --============================--
61 -- no body for C940004_0
62 --=============================--
64 with C940004_0
; -- Resource_Pkg
66 -- This generic package implements a semaphore to control a single resource
70 type Generic_Record_Type
is new C940004_0
.User_Descriptor_Type
74 -- Generic_Semaphore_Pkg
75 -- generic package extends the tagged formal generic
76 -- type with some implementation relevant details, and
77 -- it provides a semaphore with operations that work
79 type User_Rec_Type
is new Generic_Record_Type
with private;
81 protected type Semaphore_Type
is
82 function TC_Count
return Integer;
83 entry Request
(R
: in out User_Rec_Type
);
84 procedure Release
(R
: in out User_Rec_Type
);
86 In_Use
: Boolean := false;
89 function Has_Access
(R
: User_Rec_Type
) return Boolean;
93 type User_Rec_Type
is new Generic_Record_Type
with record
94 Access_To_Resource
: boolean := false;
97 end C940004_1
; -- Generic_Semaphore_Pkg
99 --===================================================--
101 package body C940004_1
is
102 -- Generic_Semaphore_Pkg
104 protected body Semaphore_Type
is
106 function TC_Count
return Integer is
108 return Request
'Count;
111 entry Request
(R
: in out User_Rec_Type
)
115 R
.Access_To_Resource
:= true;
118 procedure Release
(R
: in out User_Rec_Type
) is
121 R
.Access_To_Resource
:= false;
126 function Has_Access
(R
: User_Rec_Type
) return Boolean is
128 return R
.Access_To_Resource
;
131 end C940004_1
; -- Generic_Semaphore_Pkg
133 --=============================================--
136 with C940004_0
; -- Resource_Pkg,
137 with C940004_1
; -- Generic_Semaphore_Pkg;
142 -- Instantiate the generic to get code to manage a single printer;
143 -- User processes contend for the printer, asking for it by a call
144 -- to Request, and relinquishing it by a call to Release
146 -- This package extends a tagged type to customize it for the printer
147 -- in question, then it uses the type to instantiate the generic and
148 -- declare a semaphore specific to the particular resource
150 package Resource_Pkg
renames C940004_0
;
152 type User_Desc_Type
is new Resource_Pkg
.User_Descriptor_Type
with record
153 New_Details
: Integer := 0; -- for example
156 package Instantiation
is new C940004_1
-- Generic_Semaphore_Pkg
157 (Generic_Record_Type
=> User_Desc_Type
);
159 Printer_Access_Mgr
: Instantiation
.Semaphore_Type
;
162 end C940004_2
; -- Printer_Mgr_Pkg
164 --============================--
165 -- no body for C940004_2
166 --============================--
168 with C940004_0
; -- Resource_Pkg,
169 with C940004_2
; -- Printer_Mgr_Pkg;
174 -- This package models user tasks that will request and release
176 package Resource_Pkg
renames C940004_0
;
177 package Printer_Mgr_Pkg
renames C940004_2
;
179 task type User_Task_Type
(ID
: Resource_Pkg
.ID_Type
) is
180 entry Get_Printer
; -- instructs task to request resource
182 entry Release_Printer
-- instructs task to release printer
183 (Descriptor
: in out Printer_Mgr_pkg
.Instantiation
.User_Rec_Type
);
185 --==================--
186 -- Test management machinery
187 --==================--
188 entry TC_Get_Descriptor
-- returns descriptor
189 (Descriptor
: out Printer_Mgr_Pkg
.Instantiation
.User_Rec_Type
);
193 --==================--
194 -- Test management machinery
195 --==================--
196 TC_Times_Obtained
: Integer := 0;
197 TC_Times_Released
: Integer := 0;
199 end C940004_3
; -- User_Task_Pkg;
201 --==============================================--
204 with C940004_0
; -- Resource_Pkg,
205 with C940004_2
; -- Printer_Mgr_Pkg,
207 package body C940004_3
is
210 task body User_Task_Type
is
211 D
: Printer_Mgr_Pkg
.Instantiation
.User_Rec_Type
;
214 -----------------------------------
219 Printer_Mgr_Pkg
.Printer_Access_Mgr
.Request
(D
);
220 -- request resource; if resource is not available,
221 -- task will be queued to wait
222 --===================--
223 -- Test management machinery
224 --===================--
225 TC_Times_Obtained
:= TC_Times_Obtained
+ 1;
226 -- when request granted, note it and post a message
229 accept Release_Printer
(Descriptor
: in out
230 Printer_Mgr_Pkg
.Instantiation
.User_Rec_Type
) do
232 Printer_Mgr_Pkg
.Printer_Access_Mgr
.Release
(D
);
233 -- release the resource, note its release
234 TC_Times_Released
:= TC_Times_Released
+ 1;
240 accept TC_Get_Descriptor
(Descriptor
: out
241 Printer_Mgr_Pkg
.Instantiation
.User_Rec_Type
) do
244 end TC_Get_Descriptor
;
250 when others => Report
.Failed
("exception raised in User_Task");
253 end C940004_3
; -- User_Task_Pkg;
255 --==========================================================--
260 with C940004_0
; -- Resource_Pkg,
261 with C940004_2
; -- Printer_Mgr_Pkg,
262 with C940004_3
; -- User_Task_Pkg;
265 Verbose
: constant Boolean := False;
266 package Resource_Pkg
renames C940004_0
;
267 package Printer_Mgr_Pkg
renames C940004_2
;
268 package User_Task_Pkg
renames C940004_3
;
270 Task1
: User_Task_Pkg
.User_Task_Type
(1);
271 Task2
: User_Task_Pkg
.User_Task_Type
(2);
272 Task3
: User_Task_Pkg
.User_Task_Type
(3);
276 User_Rec_3
: Printer_Mgr_Pkg
.Instantiation
.User_Rec_Type
;
280 Report
.Test
("C940004", "Check that a protected record can be used to " &
281 "control access to resources");
283 if (User_Task_Pkg
.TC_Times_Obtained
/= 0)
284 or (User_Task_Pkg
.TC_Times_Released
/= 0)
285 or Printer_Mgr_Pkg
.Instantiation
.Has_Access
(User_Rec_1
)
286 or Printer_Mgr_Pkg
.Instantiation
.Has_Access
(User_Rec_2
)
287 or Printer_Mgr_Pkg
.Instantiation
.Has_Access
(User_Rec_3
) then
288 Report
.Failed
("Wrong initial conditions");
291 Task1
.Get_Printer
; -- ask for resource
292 -- request for resource should be granted
293 Task1
.TC_Get_Descriptor
(User_Rec_1
);-- wait here 'til task gets resource
295 if (User_Task_Pkg
.TC_Times_Obtained
/= 1)
296 or (User_Task_Pkg
.TC_Times_Released
/= 0)
297 or not Printer_Mgr_Pkg
.Instantiation
.Has_Access
(User_Rec_1
) then
298 Report
.Failed
("Resource not assigned to task 1");
301 Task2
.Get_Printer
; -- ask for resource
302 -- request for resource should be denied
303 -- and task queued to wait
305 -- Task 1 still waiting to accept Release_Printer, still holds resource
306 -- Task 2 queued on Semaphore.Request
308 -- Ensure that Task2 is queued before continuing to make checks and queue
309 -- Task3. We use a for loop here to avoid hangs in broken implementations.
310 for TC_Cnt
in 1 .. 20 loop
311 exit when Printer_Mgr_Pkg
.Printer_Access_Mgr
.TC_Count
>= 1;
312 delay Impdef
.Minimum_Task_Switch
;
315 if (User_Task_Pkg
.TC_Times_Obtained
/= 1)
316 or (User_Task_Pkg
.TC_Times_Released
/= 0) then
317 Report
.Failed
("Resource assigned to task 2");
320 Task3
.Get_Printer
; -- ask for resource
321 -- request for resource should be denied
322 -- and task 3 queued on Semaphore.Request
324 Task1
.Release_Printer
(User_Rec_1
);-- task 1 releases resource
325 -- released resource should be given to
328 Task2
.TC_Get_Descriptor
(User_Rec_2
);-- wait here for task 2
330 -- Task 1 has released resource and completed
331 -- Task 2 has seized the resource
332 -- Task 3 is queued on Semaphore.Request
334 if (User_Task_Pkg
.TC_Times_Obtained
/= 2)
335 or (User_Task_Pkg
.TC_Times_Released
/= 1)
336 or Printer_Mgr_Pkg
.Instantiation
.Has_Access
(User_Rec_1
)
337 or not Printer_Mgr_Pkg
.Instantiation
.Has_Access
(User_Rec_2
) then
338 Report
.Failed
("Resource not properly released/assigned" &
341 Report
.Comment
("TC_Times_Obtained: " &
342 Integer'Image (User_Task_Pkg
.TC_Times_Obtained
));
343 Report
.Comment
("TC_Times_Released: " &
344 Integer'Image (User_Task_Pkg
.TC_Times_Released
));
345 Report
.Comment
("User 1 Has_Access:" &
346 Boolean'Image (Printer_Mgr_Pkg
.Instantiation
.
347 Has_Access
(User_Rec_1
)));
348 Report
.Comment
("User 2 Has_Access:" &
349 Boolean'Image (Printer_Mgr_Pkg
.Instantiation
.
350 Has_Access
(User_Rec_2
)));
354 Task2
.Release_Printer
(User_Rec_2
);-- task 2 releases resource
356 -- task 3 is released from queue, and is given resource
358 Task3
.TC_Get_Descriptor
(User_Rec_3
);-- wait for task 3
360 if (User_Task_Pkg
.TC_Times_Obtained
/= 3)
361 or (User_Task_Pkg
.TC_Times_Released
/= 2)
362 or Printer_Mgr_Pkg
.Instantiation
.Has_Access
(User_Rec_2
)
363 or not Printer_Mgr_Pkg
.Instantiation
.Has_Access
(User_Rec_3
) then
364 Report
.Failed
("Resource not properly released/assigned " &
367 Report
.Comment
("TC_Times_Obtained: " &
368 Integer'Image (User_Task_Pkg
.TC_Times_Obtained
));
369 Report
.Comment
("TC_Times_Released: " &
370 Integer'Image (User_Task_Pkg
.TC_Times_Released
));
371 Report
.Comment
("User 1 Has_Access:" &
372 Boolean'Image (Printer_Mgr_Pkg
.Instantiation
.
373 Has_Access
(User_Rec_1
)));
374 Report
.Comment
("User 2 Has_Access:" &
375 Boolean'Image (Printer_Mgr_Pkg
.Instantiation
.
376 Has_Access
(User_Rec_2
)));
377 Report
.Comment
("User 3 Has_Access:" &
378 Boolean'Image (Printer_Mgr_Pkg
.Instantiation
.
379 Has_Access
(User_Rec_3
)));
383 Task3
.Release_Printer
(User_Rec_3
);-- task 3 releases resource
385 if (User_Task_Pkg
.TC_Times_Obtained
/=3)
386 or (User_Task_Pkg
.TC_Times_Released
/=3)
387 or Printer_Mgr_Pkg
.Instantiation
.Has_Access
(User_Rec_3
) then
388 Report
.Failed
("Resource not properly released by task 3");
390 Report
.Comment
("TC_Times_Obtained: " &
391 Integer'Image (User_Task_Pkg
.TC_Times_Obtained
));
392 Report
.Comment
("TC_Times_Released: " &
393 Integer'Image (User_Task_Pkg
.TC_Times_Released
));
394 Report
.Comment
("User 1 Has_Access:" &
395 Boolean'Image (Printer_Mgr_Pkg
.Instantiation
.
396 Has_Access
(User_Rec_1
)));
397 Report
.Comment
("User 2 Has_Access:" &
398 Boolean'Image (Printer_Mgr_Pkg
.Instantiation
.
399 Has_Access
(User_Rec_2
)));
400 Report
.Comment
("User 3 Has_Access:" &
401 Boolean'Image (Printer_Mgr_Pkg
.Instantiation
.
402 Has_Access
(User_Rec_3
)));
407 -- Ensure that all tasks have terminated before reporting the result
408 while not (Task1
'terminated
410 and Task3
'terminated) loop
411 delay ImpDef
.Minimum_Task_Switch
;