1 |
281 |
jeremybenn |
------------------------------------------------------------------------------
|
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-2009, 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 |
|
|
-- This unit (and shared passive partitions) are supported on all
|
40 |
|
|
-- GNAT implementations except on OpenVMS (where problems arise from
|
41 |
|
|
-- trying to share files, and with version numbers of files)
|
42 |
|
|
|
43 |
|
|
-- --------------------------
|
44 |
|
|
-- -- Shared Storage Model --
|
45 |
|
|
-- --------------------------
|
46 |
|
|
|
47 |
|
|
-- The basic model used is that each partition that references the
|
48 |
|
|
-- Shared_Passive package has a local copy of the package data that
|
49 |
|
|
-- is initialized in accordance with the declarations of the package
|
50 |
|
|
-- in the normal manner. The routines in System.Shared_Storage are
|
51 |
|
|
-- then used to ensure that the values in these separate copies are
|
52 |
|
|
-- properly synchronized with the state of the overall system.
|
53 |
|
|
|
54 |
|
|
-- In the GNAT implementation, this synchronization is ensured by
|
55 |
|
|
-- maintaining a set of files, in a designated directory. The
|
56 |
|
|
-- directory is designated by setting the environment variable
|
57 |
|
|
-- SHARED_MEMORY_DIRECTORY. This variable must be set for all
|
58 |
|
|
-- partitions. If the environment variable is not defined, then the
|
59 |
|
|
-- current directory is used.
|
60 |
|
|
|
61 |
|
|
-- There is one storage for each variable. The name is the fully
|
62 |
|
|
-- qualified name of the variable with all letters forced to lower
|
63 |
|
|
-- case. For example, the variable Var in the shared passive package
|
64 |
|
|
-- Pkg results in the storage name pkg.var.
|
65 |
|
|
|
66 |
|
|
-- If the storage does not exist, it indicates that no partition has
|
67 |
|
|
-- assigned a new value, so that the initial value is the correct
|
68 |
|
|
-- one. This is the critical component of the model. It means that
|
69 |
|
|
-- there is no system-wide synchronization required for initializing
|
70 |
|
|
-- the package, since the shared storages need not (and do not)
|
71 |
|
|
-- reflect the initial state. There is therefore no issue of
|
72 |
|
|
-- synchronizing initialization and read/write access.
|
73 |
|
|
|
74 |
|
|
-- -----------------------
|
75 |
|
|
-- -- Read/Write Access --
|
76 |
|
|
-- -----------------------
|
77 |
|
|
|
78 |
|
|
-- The approach is as follows:
|
79 |
|
|
|
80 |
|
|
-- For each shared variable, var, an instantiation of the below generic
|
81 |
|
|
-- package is created which provides Read and Write supporting procedures.
|
82 |
|
|
|
83 |
|
|
-- The routine Read in package System.Shared_Storage.Shared_Var_Procs
|
84 |
|
|
-- ensures to assign variable V to the last written value among processes
|
85 |
|
|
-- referencing it. A call to this procedure is generated by the expander
|
86 |
|
|
-- before each read access to the shared variable.
|
87 |
|
|
|
88 |
|
|
-- The routine Write in package System.Shared_Storage.Shared_Var_Proc
|
89 |
|
|
-- set a new value to the shared variable and, according to the used
|
90 |
|
|
-- implementation, propagate this value among processes referencing it.
|
91 |
|
|
-- A call to this procedure is generated by the expander after each
|
92 |
|
|
-- assignment of the shared variable.
|
93 |
|
|
|
94 |
|
|
-- Note: a special circuit allows the use of stream attributes Read and
|
95 |
|
|
-- Write for limited types (using the corresponding attribute for the
|
96 |
|
|
-- full type), but there are limitations on the data that can be placed
|
97 |
|
|
-- in shared passive partitions. See sem_smem.ads/adb for details.
|
98 |
|
|
|
99 |
|
|
-- ----------------------------------------------------------------
|
100 |
|
|
-- -- Handling of Protected Objects in Shared Passive Partitions --
|
101 |
|
|
-- ----------------------------------------------------------------
|
102 |
|
|
|
103 |
|
|
-- In the context of GNAT, during the execution of a protected
|
104 |
|
|
-- subprogram call, access is locked out using a locking mechanism
|
105 |
|
|
-- per protected object, as provided by the GNAT.Lock_Files
|
106 |
|
|
-- capability in the specific case of GNAT. This package contains the
|
107 |
|
|
-- lock and unlock calls, and the expander generates a call to the
|
108 |
|
|
-- lock routine before the protected call and a call to the unlock
|
109 |
|
|
-- routine after the protected call.
|
110 |
|
|
|
111 |
|
|
-- Within the code of the protected subprogram, the access to the
|
112 |
|
|
-- protected object itself uses the local copy, without any special
|
113 |
|
|
-- synchronization. Since global access is locked out, no other task
|
114 |
|
|
-- or partition can attempt to read or write this data as long as the
|
115 |
|
|
-- lock is held.
|
116 |
|
|
|
117 |
|
|
-- The data in the local copy does however need synchronizing with
|
118 |
|
|
-- the global values in the shared storage. This is achieved as
|
119 |
|
|
-- follows:
|
120 |
|
|
|
121 |
|
|
-- The protected object generates a read and assignment routine as
|
122 |
|
|
-- described for other shared passive variables. The code for the
|
123 |
|
|
-- 'Read and 'Write attributes (not normally allowed, but allowed
|
124 |
|
|
-- in this special case) simply reads or writes the values of the
|
125 |
|
|
-- components in the protected record.
|
126 |
|
|
|
127 |
|
|
-- The lock call is followed by a call to the shared read routine to
|
128 |
|
|
-- synchronize the local copy to contain the proper global value.
|
129 |
|
|
|
130 |
|
|
-- The unlock call in the procedure case only is preceded by a call
|
131 |
|
|
-- to the shared assign routine to synchronize the global shared
|
132 |
|
|
-- storages with the (possibly modified) local copy.
|
133 |
|
|
|
134 |
|
|
-- These calls to the read and assign routines, as well as the lock
|
135 |
|
|
-- and unlock routines, are inserted by the expander (see exp_smem.adb).
|
136 |
|
|
|
137 |
|
|
package System.Shared_Storage is
|
138 |
|
|
|
139 |
|
|
procedure Shared_Var_Lock (Var : String);
|
140 |
|
|
-- This procedure claims the shared storage lock. It is used for
|
141 |
|
|
-- protected types in shared passive packages. A call to this
|
142 |
|
|
-- locking routine is generated as the first operation in the code
|
143 |
|
|
-- for the body of a protected subprogram, and it busy waits if
|
144 |
|
|
-- the lock is busy.
|
145 |
|
|
|
146 |
|
|
procedure Shared_Var_Unlock (Var : String);
|
147 |
|
|
-- This procedure releases the shared storage lock obtained by a
|
148 |
|
|
-- prior call to the Shared_Var_Lock procedure, and is to be
|
149 |
|
|
-- generated as the last operation in the body of a protected
|
150 |
|
|
-- subprogram.
|
151 |
|
|
|
152 |
|
|
-- This generic package is instantiated for each shared passive
|
153 |
|
|
-- variable. It provides supporting procedures called upon each
|
154 |
|
|
-- read or write access by the expanded code.
|
155 |
|
|
|
156 |
|
|
generic
|
157 |
|
|
|
158 |
|
|
type Typ is limited private;
|
159 |
|
|
-- Shared passive variable type
|
160 |
|
|
|
161 |
|
|
V : in out Typ;
|
162 |
|
|
-- Shared passive variable
|
163 |
|
|
|
164 |
|
|
Full_Name : String;
|
165 |
|
|
-- Shared passive variable storage name
|
166 |
|
|
|
167 |
|
|
package Shared_Var_Procs is
|
168 |
|
|
|
169 |
|
|
procedure Read;
|
170 |
|
|
-- Shared passive variable access routine. Each reference to the
|
171 |
|
|
-- shared variable, V, is preceded by a call to the corresponding
|
172 |
|
|
-- Read procedure, which either leaves the initial value unchanged
|
173 |
|
|
-- if the storage does not exist, or reads the current value from
|
174 |
|
|
-- the shared storage.
|
175 |
|
|
|
176 |
|
|
procedure Write;
|
177 |
|
|
-- Shared passive variable assignment routine. Each assignment to
|
178 |
|
|
-- the shared variable, V, is followed by a call to the corresponding
|
179 |
|
|
-- Write procedure, which writes the new value to the shared storage.
|
180 |
|
|
|
181 |
|
|
end Shared_Var_Procs;
|
182 |
|
|
|
183 |
|
|
end System.Shared_Storage;
|