| -- C940A03.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 |
| -- controlling access to shared data through procedure parameters to |
| -- allow a specific maximum number of tasks to run and exclude all |
| -- others. |
| -- |
| -- TEST DESCRIPTION: |
| -- Declare a resource descriptor tagged type. Extend the type and |
| -- use the extended type in a protected data structure. |
| -- Implement a counting semaphore type that can be initialized to a |
| -- specific number of available resources. Declare an entry for |
| -- requesting a specific resource and an procedure for releasing the |
| -- same resource it. Declare an object of this (protected) 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. |
| -- |
| -- This test models a multi-user operating system that allows a limited |
| -- number of logins. Users requesting login are modeled by tasks. |
| -- |
| -- |
| -- TEST FILES: |
| -- This test depends on the following foundation code: |
| -- |
| -- F940A00 |
| -- |
| -- |
| -- CHANGE HISTORY: |
| -- 06 Dec 94 SAIC ACVC 2.0 |
| -- 13 Nov 95 SAIC Fixed bugs for ACVC 2.0.1 |
| -- |
| --! |
| |
| package C940A03_0 is |
| --Resource_Pkg |
| |
| -- General type declarations that will be extended to model available |
| -- logins |
| |
| type Resource_ID_Type is range 0..10; |
| type Resource_Type is tagged record |
| Id : Resource_ID_Type := 0; |
| end record; |
| |
| end C940A03_0; |
| --Resource_Pkg |
| |
| --======================================-- |
| -- no body for C940A3_0 |
| --======================================-- |
| |
| with F940A00; -- Interlock_Foundation |
| with C940A03_0; -- Resource_Pkg; |
| |
| package C940A03_1 is |
| -- Semaphores |
| |
| -- Models a counting semaphore that will allow up to a specific |
| -- number of logins |
| -- Users (tasks) request a login slot by calling the Request_Login |
| -- entry and logout by calling the Release_Login procedure |
| |
| Max_Logins : constant Integer := 2; |
| |
| |
| type Key_Type is range 0..100; |
| -- When a user requests a login, an |
| -- identifying key will be returned |
| Init_Key : constant Key_Type := 0; |
| |
| type Login_Record_Type is new C940A03_0.Resource_Type with record |
| Key : Key_Type := Init_Key; |
| end record; |
| |
| |
| protected type Login_Semaphore_Type (Resources_Available : Integer :=1) is |
| |
| entry Request_Login (Resource_Key : in out Login_Record_Type); |
| procedure Release_Login; |
| function Available return Integer; -- how many logins are available? |
| private |
| Logins_Avail : Integer := Resources_Available; |
| Next_Key : Key_Type := Init_Key; |
| |
| end Login_Semaphore_Type; |
| |
| Login_Semaphore : Login_Semaphore_Type (Max_Logins); |
| |
| --====== machinery for the test, not the model =====-- |
| TC_Control_Message : F940A00.Interlock_Type; |
| function TC_Key_Val (Login_Rec : Login_Record_Type) return Integer; |
| |
| |
| end C940A03_1; |
| -- Semaphores; |
| |
| --=========================================================-- |
| |
| package body C940A03_1 is |
| -- Semaphores is |
| |
| protected body Login_Semaphore_Type is |
| |
| entry Request_Login (Resource_Key : in out Login_Record_Type) |
| when Logins_Avail > 0 is |
| begin |
| Next_Key := Next_Key + 1; -- login process returns a key |
| Resource_Key.Key := Next_Key; -- to the requesting user |
| Logins_Avail := Logins_Avail - 1; |
| end Request_Login; |
| |
| procedure Release_Login is |
| begin |
| Logins_Avail := Logins_Avail + 1; |
| end Release_Login; |
| |
| function Available return Integer is |
| begin |
| return Logins_Avail; |
| end Available; |
| |
| end Login_Semaphore_Type; |
| |
| function TC_Key_Val (Login_Rec : Login_Record_Type) return Integer is |
| begin |
| return Integer (Login_Rec.Key); |
| end TC_Key_Val; |
| |
| end C940A03_1; |
| -- Semaphores; |
| |
| --=========================================================-- |
| |
| with C940A03_0; -- Resource_Pkg, |
| with C940A03_1; -- Semaphores; |
| |
| package C940A03_2 is |
| -- Task_Pkg |
| |
| package Semaphores renames C940A03_1; |
| |
| task type User_Task_Type is |
| |
| entry Login (user_id : C940A03_0.Resource_Id_Type); |
| -- instructs the task to ask for a login |
| entry Logout; -- instructs the task to release the login |
| --=======================-- |
| -- this entry is used to get information to verify test operation |
| entry Get_Status (User_Record : out Semaphores.Login_Record_Type); |
| |
| end User_Task_Type; |
| |
| end C940A03_2; |
| -- Task_Pkg |
| |
| --=========================================================-- |
| |
| with Report; |
| with C940A03_0; -- Resource_Pkg, |
| with C940A03_1; -- Semaphores, |
| with F940A00; -- Interlock_Foundation; |
| |
| package body C940A03_2 is |
| -- Task_Pkg |
| |
| -- This task models a user requesting a login from the system |
| -- For control of this test, we can ask the task to login, logout, or |
| -- give us the current user record (containing login information) |
| |
| task body User_Task_Type is |
| Rec : Semaphores.Login_Record_Type; |
| begin |
| loop |
| select |
| accept Login (user_id : C940A03_0.Resource_Id_Type) do |
| Rec.Id := user_id; |
| end Login; |
| |
| Semaphores.Login_Semaphore.Request_Login (Rec); |
| -- request a resource; if resource is not available, |
| -- task will be queued to wait |
| |
| --== following is test control machinery ==-- |
| F940A00.Counter.Increment; |
| Semaphores.TC_Control_Message.Post; |
| -- after resource is obtained, post message |
| |
| or |
| accept Logout do |
| Semaphores.Login_Semaphore.Release_Login; |
| -- release the resource |
| --== test control machinery ==-- |
| F940A00.Counter.Decrement; |
| end Logout; |
| exit; |
| |
| or |
| accept Get_Status (User_Record : out Semaphores.Login_Record_Type) do |
| User_Record := Rec; |
| end Get_Status; |
| |
| end select; |
| end loop; |
| |
| exception |
| when others => Report.Failed ("Exception raised in model user task"); |
| end User_Task_Type; |
| |
| end C940A03_2; |
| -- Task_Pkg |
| |
| --=========================================================-- |
| |
| with Report; |
| with ImpDef; |
| with C940A03_1; -- Semaphores, |
| with C940A03_2; -- Task_Pkg, |
| with F940A00; -- Interlock_Foundation; |
| |
| procedure C940A03 is |
| |
| package Semaphores renames C940A03_1; |
| package Users renames C940A03_2; |
| |
| Task1, Task2, Task3 : Users.User_Task_Type; |
| User_Rec : Semaphores.Login_Record_Type; |
| |
| begin -- Tasks start here |
| |
| Report.Test ("C940A03", "Check that a protected object can coordinate " & |
| "shared data access using procedure parameters"); |
| |
| if F940A00.Counter.Number /=0 then |
| Report.Failed ("Wrong initial conditions"); |
| end if; |
| |
| Task1.Login (1); -- request resource; request should be granted |
| Semaphores.TC_Control_Message.Consume; |
| -- ensure that task obtains resource by |
| -- waiting for task to post message |
| |
| -- Task 1 waiting for call to Logout |
| -- Others still available |
| Task1.Get_Status (User_Rec); |
| if (F940A00.Counter.Number /= 1) |
| or (Semaphores.Login_Semaphore.Available /=1) |
| or (Semaphores.TC_Key_Val (User_Rec) /= 1) then |
| Report.Failed ("Resource not assigned to task 1"); |
| end if; |
| |
| Task2.Login (2); -- Request for resource should be granted |
| Semaphores.TC_Control_Message.Consume; |
| -- ensure that task obtains resource by |
| -- waiting for task to post message |
| |
| Task2.Get_Status (User_Rec); |
| if (F940A00.Counter.Number /= 2) |
| or (Semaphores.Login_Semaphore.Available /=0) |
| or (Semaphores.TC_Key_Val (User_Rec) /= 2) then |
| Report.Failed ("Resource not assigned to task 2"); |
| end if; |
| |
| |
| Task3.Login (3); -- request for resource should be denied |
| -- and task queued |
| |
| |
| -- Tasks 1 and 2 holds resources |
| -- and are waiting for a call to Logout |
| -- Task 3 is queued |
| |
| if (F940A00.Counter.Number /= 2) |
| or (Semaphores.Login_Semaphore.Available /=0) then |
| Report.Failed ("Resource incorrectly assigned to task 3"); |
| end if; |
| |
| Task1.Logout; -- released resource should be given to |
| -- queued task |
| Semaphores.TC_Control_Message.Consume; |
| -- wait for confirming message from task |
| |
| -- Task 1 holds no resources |
| -- and is terminated (or will soon) |
| -- Tasks 2 and 3 hold resources |
| -- and are waiting for a call to Logout |
| |
| Task3.Get_Status (User_Rec); |
| if (F940A00.Counter.Number /= 2) |
| or (Semaphores.Login_Semaphore.Available /=0) |
| or (Semaphores.TC_Key_Val (User_Rec) /= 3) then |
| Report.Failed ("Resource not properly released/assigned to task 3"); |
| end if; |
| |
| Task2.Logout; -- no outstanding request for released |
| -- resource |
| -- Tasks 1 and 2 hold no resources |
| -- Task 3 holds a resource |
| -- and is waiting for a call to Logout |
| |
| if (F940A00.Counter.Number /= 1) |
| or (Semaphores.Login_Semaphore.Available /=1) then |
| Report.Failed ("Resource not properly released from task 2"); |
| end if; |
| |
| Task3.Logout; |
| |
| -- all resources have been returned |
| -- all tasks have terminated or will soon |
| |
| if (F940A00.Counter.Number /=0) |
| or (Semaphores.Login_Semaphore.Available /=2) then |
| Report.Failed ("Resource not properly released from task 3"); |
| end if; |
| |
| -- Ensure all tasks have terminated before calling Result |
| while not (Task1'terminated and |
| Task2'terminated and |
| Task3'terminated) loop |
| delay ImpDef.Minimum_Task_Switch; |
| end loop; |
| |
| Report.Result; |
| |
| end C940A03; |