| -- C940002.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 a protected object provides coordinated access to shared |
| -- data. Check that it can implement a semaphore-like construct using a |
| -- parameterless procedure which allows a specific maximum number of tasks |
| -- to run and excludes all others |
| -- |
| -- TEST DESCRIPTION: |
| -- Implement a counting semaphore type that can be initialized to a |
| -- specific number of available resources. Declare an entry for |
| -- requesting a resource and a procedure for releasing it. Declare an |
| -- object of this type, initialized to two resources. Declare and start |
| -- three tasks each of which asks for a resource. Verify that only two |
| -- resources are granted and that the last task in is queued. |
| -- |
| -- |
| -- CHANGE HISTORY: |
| -- 06 Dec 94 SAIC ACVC 2.0 |
| -- |
| --! |
| |
| |
| package C940002_0 is |
| -- Semaphores |
| |
| protected type Semaphore_Type (Resources_Available : Integer :=1) is |
| entry Request; |
| procedure Release; |
| function Available return Integer; |
| private |
| Currently_Available : Integer := Resources_Available; |
| end Semaphore_Type; |
| |
| Max_Resources : constant Integer := 2; |
| Resource : Semaphore_Type (Max_Resources); |
| |
| end C940002_0; |
| -- Semaphores; |
| |
| |
| --========================================================-- |
| |
| |
| package body C940002_0 is |
| -- Semaphores |
| |
| protected body Semaphore_Type is |
| |
| entry Request when Currently_Available >0 is -- when granted, secures |
| begin -- a resource |
| Currently_Available := Currently_Available - 1; |
| end Request; |
| |
| procedure Release is -- when called, releases |
| begin -- a resource |
| Currently_Available := Currently_Available + 1; |
| end Release; |
| |
| function Available return Integer is -- returns number of |
| begin -- available resources |
| return Currently_Available; |
| end Available; |
| |
| end Semaphore_Type; |
| |
| end C940002_0; |
| -- Semaphores; |
| |
| |
| --========================================================-- |
| |
| |
| package C940002_1 is |
| -- Task_Pkg |
| |
| task type Requesting_Task is |
| entry Done; -- call on Done instructs the task |
| end Requesting_Task; -- to release resource |
| |
| type Task_Ptr is access Requesting_Task; |
| |
| protected Counter is |
| procedure Increment; |
| procedure Decrement; |
| function Number return integer; |
| private |
| Count : Integer := 0; |
| end Counter; |
| |
| protected Hold_Lock is |
| procedure Lock; |
| procedure Unlock; |
| function Locked return Boolean; |
| private |
| Lock_State : Boolean := true; -- starts out locked |
| end Hold_Lock; |
| |
| |
| end C940002_1; |
| -- Task_Pkg |
| |
| |
| --========================================================-- |
| |
| |
| with Report; |
| with C940002_0; |
| -- Semaphores; |
| |
| package body C940002_1 is |
| -- Task_Pkg is |
| |
| protected body Counter is |
| |
| procedure Increment is |
| begin |
| Count := Count + 1; |
| end Increment; |
| |
| procedure Decrement is |
| begin |
| Count := Count - 1; |
| end Decrement; |
| |
| function Number return Integer is |
| begin |
| return Count; |
| end Number; |
| |
| end Counter; |
| |
| |
| protected body Hold_Lock is |
| |
| procedure Lock is |
| begin |
| Lock_State := true; |
| end Lock; |
| |
| procedure Unlock is |
| begin |
| Lock_State := false; |
| end Unlock; |
| |
| function Locked return Boolean is |
| begin |
| return Lock_State; |
| end Locked; |
| |
| end Hold_Lock; |
| |
| |
| task body Requesting_Task is |
| begin |
| C940002_0.Resource.Request; -- request a resource |
| -- if resource is not available, |
| -- task will be queued to wait |
| Counter.Increment; -- add to count of resources obtained |
| Hold_Lock.Unlock; -- and unlock Lock - system is stable; |
| -- status may now be queried |
| |
| accept Done do -- hold resource until Done is called |
| C940002_0.Resource.Release; -- release the resource and |
| Counter.Decrement; -- note release |
| end Done; |
| |
| exception |
| when others => Report.Failed ("Unexpected Exception in Requesting_Task"); |
| end Requesting_Task; |
| |
| end C940002_1; |
| -- Task_Pkg; |
| |
| |
| --========================================================-- |
| |
| |
| with Report; |
| with ImpDef; |
| with C940002_0, |
| -- Semaphores, |
| C940002_1; |
| -- Task_Pkg; |
| |
| procedure C940002 is |
| |
| package Semaphores renames C940002_0; |
| package Task_Pkg renames C940002_1; |
| |
| Ptr1, |
| Ptr2, |
| Ptr3 : Task_Pkg.Task_Ptr; |
| Num : Integer; |
| |
| procedure Spinlock is |
| begin |
| -- loop until unlocked |
| while Task_Pkg.Hold_Lock.Locked loop |
| delay ImpDef.Minimum_Task_Switch; |
| end loop; |
| Task_Pkg.Hold_Lock.Lock; |
| end Spinlock; |
| |
| begin |
| |
| Report.Test ("C940002", "Check that a protected record can be used to " & |
| "control access to resources"); |
| |
| if (Task_Pkg.Counter.Number /=0) |
| or (Semaphores.Resource.Available /= 2) then |
| Report.Failed ("Wrong initial conditions"); |
| end if; |
| |
| Ptr1 := new Task_Pkg.Requesting_Task; -- newly allocated task requests |
| -- resource; request for resource should |
| -- be granted |
| Spinlock; -- ensure that task obtains resource |
| |
| -- Task 1 waiting for call to Done |
| -- One resource assigned to task 1 |
| -- One resource still available |
| if (Task_Pkg.Counter.Number /= 1) |
| or (Semaphores.Resource.Available /= 1) then |
| Report.Failed ("Resource not assigned to task 1"); |
| end if; |
| |
| Ptr2 := new Task_Pkg.Requesting_Task; -- newly allocated task requests |
| -- resource; request for resource should |
| -- be granted |
| Spinlock; -- ensure that task obtains resource |
| |
| -- Task 1 waiting for call to Done |
| -- Task 2 waiting for call to Done |
| -- Resources held by tasks 1 and 2 |
| -- No resources available |
| if (Task_Pkg.Counter.Number /= 2) |
| or (Semaphores.Resource.Available /= 0) then |
| Report.Failed ("Resource not assigned to task 2"); |
| end if; |
| |
| Ptr3 := new Task_Pkg.Requesting_Task; -- newly allocated task requests |
| -- resource; request for resource should |
| -- be denied and task queued to wait for |
| -- next available resource |
| |
| |
| Ptr1.all.Done; -- Task 1 releases resource and lock |
| -- Resource should be given to queued task |
| Spinlock; -- ensure that resource is released |
| |
| |
| -- Task 1 holds no resource |
| -- One resource still assigned to task 2 |
| -- One resource assigned to task 3 |
| -- No resources available |
| if (Task_Pkg.Counter.Number /= 2) |
| or (Semaphores.Resource.Available /= 0) then |
| Report.Failed ("Resource not properly released/assigned to task 3"); |
| end if; |
| |
| Ptr2.all.Done; -- Task 2 releases resource and lock |
| -- No outstanding request for resource |
| |
| -- Tasks 1 and 2 hold no resources |
| -- One resource assigned to task 3 |
| -- One resource available |
| if (Task_Pkg.Counter.Number /= 1) |
| or (Semaphores.Resource.Available /= 1) then |
| Report.Failed ("Resource not properly released from task 2"); |
| end if; |
| |
| Ptr3.all.Done; -- Task 3 releases resource and lock |
| |
| -- All resources released |
| -- All tasks terminated (or close) |
| -- Two resources available |
| if (Task_Pkg.Counter.Number /=0) |
| or (Semaphores.Resource.Available /= 2) then |
| Report.Failed ("Resource not properly released from task 3"); |
| end if; |
| |
| Report.Result; |
| |
| end C940002; |