summaryrefslogtreecommitdiff
path: root/gcc/ada/s-shasto.ads
blob: 77cfa7b64210f7a37e292445eff765cb7bb226bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
------------------------------------------------------------------------------
--                                                                          --
--                         GNAT COMPILER COMPONENTS                         --
--                                                                          --
--                 S Y S T E M . S H A R E D _ S T O R A G E                --
--                                                                          --
--                                 S p e c                                  --
--                                                                          --
--          Copyright (C) 1998-2006, Free Software Foundation, Inc.         --
--                                                                          --
-- GNAT is free software;  you can  redistribute it  and/or modify it under --
-- terms of the  GNU General Public License as published  by the Free Soft- --
-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
-- for  more details.  You should have  received  a copy of the GNU General --
-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
-- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
-- Boston, MA 02110-1301, USA.                                              --
--                                                                          --
-- As a special exception,  if other files  instantiate  generics from this --
-- unit, or you link  this unit with other files  to produce an executable, --
-- this  unit  does not  by itself cause  the resulting  executable  to  be --
-- covered  by the  GNU  General  Public  License.  This exception does not --
-- however invalidate  any other reasons why  the executable file  might be --
-- covered by the  GNU Public License.                                      --
--                                                                          --
-- GNAT was originally developed  by the GNAT team at  New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
--                                                                          --
------------------------------------------------------------------------------

--  This package manages the shared/persistant storage required for
--  full implementation of variables in Shared_Passive packages, more
--  precisely variables whose enclosing dynamic scope is a shared
--  passive package. This implementation is specific to GNAT and GLADE
--  provides a more general implementation not dedicated to file
--  storage.

--  This unit (and shared passive partitions) are supported on all
--  GNAT implementations except on OpenVMS (where problems arise from
--  trying to share files, and with version numbers of files)

--  --------------------------
--  -- Shared Storage Model --
--  --------------------------

--  The basic model used is that each partition that references the
--  Shared_Passive package has a local copy of the package data that
--  is initialized in accordance with the declarations of the package
--  in the normal manner. The routines in System.Shared_Storage are
--  then used to ensure that the values in these separate copies are
--  properly synchronized with the state of the overall system.

--  In the GNAT implementation, this synchronization is ensured by
--  maintaining a set of files, in a designated directory. The
--  directory is designated by setting the environment variable
--  SHARED_MEMORY_DIRECTORY. This variable must be set for all
--  partitions. If the environment variable is not defined, then the
--  current directory is used.

--  There is one storage for each variable. The name is the fully
--  qualified name of the variable with all letters forced to lower
--  case. For example, the variable Var in the shared passive package
--  Pkg results in the storage name pkg.var.

--  If the storage does not exist, it indicates that no partition has
--  assigned a new value, so that the initial value is the correct
--  one. This is the critical component of the model. It means that
--  there is no system-wide synchronization required for initializing
--  the package, since the shared storages need not (and do not)
--  reflect the initial state. There is therefore no issue of
--  synchronizing initialization and read/write access.

--  -----------------------
--  -- Read/Write Access --
--  -----------------------

--  The approach is as follows:

--    For each shared variable, var, an access routine varR is created whose
--    body has the following form (this example is for Pkg.Var):

--      procedure varR is
--         S : Ada.Streams.Stream_IO.Stream_Access;
--      begin
--         S := Shared_Var_ROpen ("pkg.var");
--         if S /= null then
--            typ'Read (S);
--            Shared_Var_Close (S);
--         end if;
--      end varR;

--    The routine Shared_Var_ROpen in package System.Shared_Storage
--    either returns null if the storage does not exist, or otherwise a
--    Stream_Access value that references the corresponding shared
--    storage, ready to read the current value.

--    Each reference to the shared variable, var, is preceded by a
--    call to the corresponding varR procedure, which either leaves the
--    initial value unchanged if the storage does not exist, or reads
--    the current value from the shared storage.

--    In addition, for each shared variable, var, an assignment routine
--    is created whose body has the following form (again for Pkg.Var)

--      procedure VarA is
--         S : Ada.Streams.Stream_IO.Stream_Access;
--      begin
--         S := Shared_Var_WOpen ("pkg.var");
--         typ'Write (S, var);
--         Shared_Var_Close (S);
--      end VarA;

--    The routine Shared_Var_WOpen in package System.Shared_Storage
--    returns a Stream_Access value that references the corresponding
--    shared storage, ready to write the new value.

--    Each assignment to the shared variable, var, is followed by a call
--    to the corresponding varA procedure, which writes the new value to
--    the shared storage.

--    Note that there is no general synchronization for these storage
--    read and write operations, since it is assumed that a correctly
--    operating programs will provide appropriate synchronization. In
--    particular, variables can be protected using protected types with
--    no entries.

--    The routine Shared_Var_Close is called to indicate the end of a
--    read/write operations. This can be useful even in the context of
--    the GNAT implementation. For instance, when a read operation and a
--    write operation occur at the same time on the same partition, as
--    the same stream is used simultaneously, both operations can
--    terminate abruptly by raising exception Mode_Error because the
--    stream has been opened in read mode and then in write mode and at
--    least used by the read opartion. To avoid this unexpected
--    behaviour, we introduce a synchronization at the partition level.

--  Note: a special circuit allows the use of stream attributes Read and
--  Write for limited types (using the corresponding attribute for the
--  full type), but there are limitations on the data that can be placed
--  in shared passive partitions. See sem_smem.ads/adb for details.

--  ----------------------------------------------------------------
--  -- Handling of Protected Objects in Shared Passive Partitions --
--  ----------------------------------------------------------------

--  In the context of GNAT, during the execution of a protected
--  subprogram call, access is locked out using a locking mechanism
--  per protected object, as provided by the GNAT.Lock_Files
--  capability in the specific case of GNAT. This package contains the
--  lock and unlock calls, and the expander generates a call to the
--  lock routine before the protected call and a call to the unlock
--  routine after the protected call.

--  Within the code of the protected subprogram, the access to the
--  protected object itself uses the local copy, without any special
--  synchronization.  Since global access is locked out, no other task
--  or partition can attempt to read or write this data as long as the
--  lock is held.

--  The data in the local copy does however need synchronizing with
--  the global values in the shared storage. This is achieved as
--  follows:

--    The protected object generates a read and assignment routine as
--    described for other shared passive variables. The code for the
--    'Read and 'Write attributes (not normally allowed, but allowed
--    in this special case) simply reads or writes the values of the
--    components in the protected record.

--    The lock call is followed by a call to the shared read routine to
--    synchronize the local copy to contain the proper global value.

--    The unlock call in the procedure case only is preceded by a call
--    to the shared assign routine to synchronize the global shared
--    storages with the (possibly modified) local copy.

--    These calls to the read and assign routines, as well as the lock
--    and unlock routines, are inserted by the expander (see exp_smem.adb).

with Ada.Streams.Stream_IO;

package System.Shared_Storage is

   package SIO renames Ada.Streams.Stream_IO;

   function Shared_Var_ROpen (Var : String) return SIO.Stream_Access;
   --  As described above, this routine returns null if the
   --  corresponding shared storage does not exist, and otherwise, if
   --  the storage does exist, a Stream_Access value that references
   --  the shared storage, ready to read the current value.

   function Shared_Var_WOpen (Var : String) return SIO.Stream_Access;
   --  As described above, this routine returns a Stream_Access value
   --  that references the shared storage, ready to write the new
   --  value. The storage is created by this call if it does not
   --  already exist.

   procedure Shared_Var_Close (Var : SIO.Stream_Access);
   --  This routine signals the end of a read/assign operation. It can
   --  be useful to embrace a read/write operation between a call to
   --  open and a call to close which protect the whole operation.
   --  Otherwise, two simultaneous operations can result in the
   --  raising of exception Data_Error by setting the access mode of
   --  the variable in an incorrect mode.

   procedure Shared_Var_Lock (Var : String);
   --  This procedure claims the shared storage lock. It is used for
   --  protected types in shared passive packages. A call to this
   --  locking routine is generated as the first operation in the code
   --  for the body of a protected subprogram, and it busy waits if
   --  the lock is busy.

   procedure Shared_Var_Unlock (Var : String);
   --  This procedure releases the shared storage lock obtaind by a
   --  prior call to the Shared_Mem_Lock procedure, and is to be
   --  generated as the last operation in the body of a protected
   --  subprogram.

end System.Shared_Storage;