1------------------------------------------------------------------------------ 2-- -- 3-- GNAT COMPILER COMPONENTS -- 4-- -- 5-- S Y S T E M . S H A R E D _ S T O R A G E -- 6-- -- 7-- S p e c -- 8-- -- 9-- Copyright (C) 1998-2014, Free Software Foundation, Inc. -- 10-- -- 11-- GNAT is free software; you can redistribute it and/or modify it under -- 12-- terms of the GNU General Public License as published by the Free Soft- -- 13-- ware Foundation; either version 3, or (at your option) any later ver- -- 14-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- 15-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- 16-- or FITNESS FOR A PARTICULAR PURPOSE. -- 17-- -- 18-- As a special exception under Section 7 of GPL version 3, you are granted -- 19-- additional permissions described in the GCC Runtime Library Exception, -- 20-- version 3.1, as published by the Free Software Foundation. -- 21-- -- 22-- You should have received a copy of the GNU General Public License and -- 23-- a copy of the GCC Runtime Library Exception along with this program; -- 24-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- 25-- <http://www.gnu.org/licenses/>. -- 26-- -- 27-- GNAT was originally developed by the GNAT team at New York University. -- 28-- Extensive contributions were provided by Ada Core Technologies Inc. -- 29-- -- 30------------------------------------------------------------------------------ 31 32-- This package manages the shared/persistent storage required for 33-- full implementation of variables in Shared_Passive packages, more 34-- precisely variables whose enclosing dynamic scope is a shared 35-- passive package. This implementation is specific to GNAT and GLADE 36-- provides a more general implementation not dedicated to file 37-- storage. 38 39-- -------------------------- 40-- -- Shared Storage Model -- 41-- -------------------------- 42 43-- The basic model used is that each partition that references the 44-- Shared_Passive package has a local copy of the package data that 45-- is initialized in accordance with the declarations of the package 46-- in the normal manner. The routines in System.Shared_Storage are 47-- then used to ensure that the values in these separate copies are 48-- properly synchronized with the state of the overall system. 49 50-- In the GNAT implementation, this synchronization is ensured by 51-- maintaining a set of files, in a designated directory. The 52-- directory is designated by setting the environment variable 53-- SHARED_MEMORY_DIRECTORY. This variable must be set for all 54-- partitions. If the environment variable is not defined, then the 55-- current directory is used. 56 57-- There is one storage for each variable. The name is the fully 58-- qualified name of the variable with all letters forced to lower 59-- case. For example, the variable Var in the shared passive package 60-- Pkg results in the storage name pkg.var. 61 62-- If the storage does not exist, it indicates that no partition has 63-- assigned a new value, so that the initial value is the correct 64-- one. This is the critical component of the model. It means that 65-- there is no system-wide synchronization required for initializing 66-- the package, since the shared storages need not (and do not) 67-- reflect the initial state. There is therefore no issue of 68-- synchronizing initialization and read/write access. 69 70-- ----------------------- 71-- -- Read/Write Access -- 72-- ----------------------- 73 74-- The approach is as follows: 75 76-- For each shared variable, var, an instantiation of the below generic 77-- package is created which provides Read and Write supporting procedures. 78 79-- The routine Read in package System.Shared_Storage.Shared_Var_Procs 80-- ensures to assign variable V to the last written value among processes 81-- referencing it. A call to this procedure is generated by the expander 82-- before each read access to the shared variable. 83 84-- The routine Write in package System.Shared_Storage.Shared_Var_Proc 85-- set a new value to the shared variable and, according to the used 86-- implementation, propagate this value among processes referencing it. 87-- A call to this procedure is generated by the expander after each 88-- assignment of the shared variable. 89 90-- Note: a special circuit allows the use of stream attributes Read and 91-- Write for limited types (using the corresponding attribute for the 92-- full type), but there are limitations on the data that can be placed 93-- in shared passive partitions. See sem_smem.ads/adb for details. 94 95-- ---------------------------------------------------------------- 96-- -- Handling of Protected Objects in Shared Passive Partitions -- 97-- ---------------------------------------------------------------- 98 99-- In the context of GNAT, during the execution of a protected 100-- subprogram call, access is locked out using a locking mechanism 101-- per protected object, as provided by the GNAT.Lock_Files 102-- capability in the specific case of GNAT. This package contains the 103-- lock and unlock calls, and the expander generates a call to the 104-- lock routine before the protected call and a call to the unlock 105-- routine after the protected call. 106 107-- Within the code of the protected subprogram, the access to the 108-- protected object itself uses the local copy, without any special 109-- synchronization. Since global access is locked out, no other task 110-- or partition can attempt to read or write this data as long as the 111-- lock is held. 112 113-- The data in the local copy does however need synchronizing with 114-- the global values in the shared storage. This is achieved as 115-- follows: 116 117-- The protected object generates a read and assignment routine as 118-- described for other shared passive variables. The code for the 119-- 'Read and 'Write attributes (not normally allowed, but allowed 120-- in this special case) simply reads or writes the values of the 121-- components in the protected record. 122 123-- The lock call is followed by a call to the shared read routine to 124-- synchronize the local copy to contain the proper global value. 125 126-- The unlock call in the procedure case only is preceded by a call 127-- to the shared assign routine to synchronize the global shared 128-- storages with the (possibly modified) local copy. 129 130-- These calls to the read and assign routines, as well as the lock 131-- and unlock routines, are inserted by the expander (see exp_smem.adb). 132 133package System.Shared_Storage is 134 135 procedure Shared_Var_Lock (Var : String); 136 -- This procedure claims the shared storage lock. It is used for 137 -- protected types in shared passive packages. A call to this 138 -- locking routine is generated as the first operation in the code 139 -- for the body of a protected subprogram, and it busy waits if 140 -- the lock is busy. 141 142 procedure Shared_Var_Unlock (Var : String); 143 -- This procedure releases the shared storage lock obtained by a 144 -- prior call to the Shared_Var_Lock procedure, and is to be 145 -- generated as the last operation in the body of a protected 146 -- subprogram. 147 148 -- This generic package is instantiated for each shared passive 149 -- variable. It provides supporting procedures called upon each 150 -- read or write access by the expanded code. 151 152 generic 153 154 type Typ is limited private; 155 -- Shared passive variable type 156 157 V : in out Typ; 158 -- Shared passive variable 159 160 Full_Name : String; 161 -- Shared passive variable storage name 162 163 package Shared_Var_Procs is 164 165 procedure Read; 166 -- Shared passive variable access routine. Each reference to the 167 -- shared variable, V, is preceded by a call to the corresponding 168 -- Read procedure, which either leaves the initial value unchanged 169 -- if the storage does not exist, or reads the current value from 170 -- the shared storage. 171 172 procedure Write; 173 -- Shared passive variable assignment routine. Each assignment to 174 -- the shared variable, V, is followed by a call to the corresponding 175 -- Write procedure, which writes the new value to the shared storage. 176 177 end Shared_Var_Procs; 178 179end System.Shared_Storage; 180