1% BEGIN LICENSE BLOCK
2% Version: CMPL 1.1
3%
4% The contents of this file are subject to the Cisco-style Mozilla Public
5% License Version 1.1 (the "License"); you may not use this file except
6% in compliance with the License.  You may obtain a copy of the License
7% at www.eclipse-clp.org/license.
8% 
9% Software distributed under the License is distributed on an "AS IS"
10% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
11% the License for the specific language governing rights and limitations
12% under the License. 
13% 
14% The Original Code is  The ECLiPSe Constraint Logic Programming System. 
15% The Initial Developer of the Original Code is  Cisco Systems, Inc. 
16% Portions created by the Initial Developer are
17% Copyright (C) 2006 Cisco Systems, Inc.  All Rights Reserved.
18% 
19% Contributor(s): 
20% 
21% END LICENSE BLOCK
22\chapter{Global State}
23
24%----------------------------------------------------------------------
25\section{Memory Management}
26Memory management in \eclipse\ is designed for a parallel
27shared memory system (where several processes work on a piece of
28shared memory), although this functionality is not
29supported by IC-Parc.
30The memory areas are:
31\begin{description}
32\item[shared heap]
33    Most of the non-logical data is here:
34    \begin{itemize}
35    \item dictionary and everything related, e.g.
36    \item abstract machine code
37    \item heap terms
38    \end{itemize}
39\item[private heap]
40    In a non-parallel \eclipse\ this is the same as the shared heap\footnote{
41    In parallel \eclipse\ the private heap is private to each worker, while
42    the shared heap is shared between workers}.
43    \begin{itemize}
44    \item temporary storage
45    \item data that must be local to a process
46    \item memory allocated by third party code, e.g. Cplex.
47    \end{itemize}
48\item[stack]
49    The abstract machine stacks. They are allocated in pairs
50    that grow towards each other from both ends of the allocated
51    area:
52    \begin{itemize}
53    \item global-trail stack
54    \item control-local stack
55    \end{itemize}
56\end{description}
57
58\subsection{Heap Management}
59
60The heap management (for shared memory, but the code is also used
61in the non-parallel case) is in the subsystem {\bf Shm}.
62To use the library\footnote{
63In parallel \eclipse, this library was used to share memory between
64workers and the worker manager process.},
65include the following header files:
66\begin{verbatim}
67#include "memman.h"
68\end{verbatim}
69and link your program with libshm.a
70
71The type generic_ptr is normally (void *). On compilers that don't
72support it (char *) is used instead.
73For the following, it is useful to know the ideas behind the UNIX
74mmap() system call, on which the API is based.
75
76\subsubsection{Initialisation}
77
78\begin{verbatim}
79char *shared_mem_init(
80        int create_flag,        specifies if we create (!=0) or if we
81                                    attach to (==0) existing shared memory.
82        char* mapfile,          the filename of the mapfile or NULL for
83                                    anonymous mapping into the swap space.
84        char* start,            the address where the shared memory is
85                                    mapped at. If NULL, the system chooses an
86                                    address (during create) or uses the same
87                                    address as the creator (during attach).
88        int size,               maximum size of shared memory (0=default size),
89                                    only used when create_flag is set.
90        int increment,          minimum amount of bytes the shared memory is
91                                    extended by on overflows (0=default).
92        void (*panic_fct)()     function to call when out of memory. If NULL,
93                                    the allocation functions return NULL
94                                    instead.
95        struct heap_descriptor *
96                                this descriptor must exist and is filled
97                                    by the function. It is used in further
98                                    memory operations.
99    );
100\end{verbatim}
101
102    The return value is equal to the specified start address if everything
103    goes well, -1 otherwise.
104
105    The first word of the shared memory is reserved for the application:
106    The idea is to store here a pointer to some kind of toplevel data
107    structure of the application.
108
109    The panic function takes two descriptive arguments and may look
110    as follows:
111
112\begin{verbatim}
113    void
114    panic(what, where)
115    char *what, *where;
116    {
117            printf("Panic: %s in %s\n", what, where);
118            exit(-1);
119    }
120\end{verbatim}
121
122
123\begin{verbatim}
124void shared_mem_release(struct heap_descriptor *);
125\end{verbatim}
126
127    Should be called before a process using the shared memory exits.
128    When the releasing process is the last attached one, the mapfile
129    is removed.
130
131
132\subsubsection{Header-less allocation}
133
134These functions should be used when the caller can remember the size of the
135allocated area, or when the size is implicit in the allocated data.
136This allocation has no memory overhead, so e.g. allocating 8192 bytes
137will use up exactly 8k of memory and no more.
138
139\begin{verbatim}
140generic_ptr     alloc_size(struct heap_descriptor *, int size);
141\end{verbatim}
142
143    Allocate size bytes of shared memory and return its address.
144    If the allocation fails, the panic-function is called, if any,
145    otherwise NULL is returned.
146
147\begin{verbatim}
148void            free_size(struct heap_descriptor *, generic_ptr addr, int size);
149\end{verbatim}
150
151    Free the memory at addr which was allocated previously with
152    alloc_size(size). Size should be the same as on allocation,
153    otherwise the result is undefined.
154
155\begin{verbatim}
156generic_ptr     realloc_size(struct heap_descriptor *,
157                        generic_ptr addr, int oldsize, int newsize);
158\end{verbatim}
159
160    Resize an allocated area. The new address may differ from the old one,
161    the old contents are copied.
162
163
164\subsubsection{Header-full allocation}
165This is a standard malloc()-style interface, where the allocated memory
166block remembers its own size, so it does not have to be passed as an
167argument when the block gets freed. This implies some bookkeeping overhead.
168Implementation is on top of the header-less primitives above.
169
170\begin{verbatim}
171generic_ptr     h_alloc(struct heap_descriptor *, int size);
172\end{verbatim}
173
174    Allocate size bytes of shared memory and return its address.
175    If the allocation fails, the panic-function is called, if any,
176    otherwise NULL is returned.
177
178\begin{verbatim}
179void            h_free(struct heap_descriptor *, generic_ptr addr);
180\end{verbatim}
181
182    Free the memory at addr which was allocated previously with h_alloc().
183
184\begin{verbatim}
185generic_ptr     h_realloc(struct heap_descriptor *,
186                        generic_ptr addr, int newsize);
187\end{verbatim}
188
189    Resize an allocated area. The new address may differ from the old one,
190    the old contents are copied.
191
192
193\subsubsection{Other}
194
195\begin{verbatim}
196int             alloc_statistics(struct heap_descriptor *, int what);
197\end{verbatim}
198
199    Return statistics about bytes of allocated memory.
200    Values for what: HEAP_STAT_ALLOCATED and HEAP_STAT_USED.
201
202
203\subsubsection{Spin locks}
204
205Locks are of type a_mutex_t (declared in memman.h).
206Functions are:
207
208\begin{verbatim}
209int             a_mutex_init(a_mutex_t *);
210int             a_mutex_lock(a_mutex_t *);
211int             a_mutex_unlock(a_mutex_t *);
212int             a_mutex_destroy(a_mutex_t *);
213\end{verbatim}
214
215
216\subsubsection{Interrupts}
217
218Motivation: Interrupts must be disabled before grabbing a lock,
219otherwise the following can happen:
220\begin{enumerate}
221   \item grab a lock
222   \item interrupt
223   \item handler tries to get the lock again
224   \item -> deadlock
225\end{enumerate}
226
227User interrupt handlers that might need locks should therefore
228not be executed while a lock is being held.
229The InterruptsDisabled condition flags this situation,
230so these handlers should have the following structure:
231
232\begin{verbatim}
233signal_handler(n)
234{
235    if (InterruptsDisabled)
236    {
237        <remember n>
238        Set_Interrupts_Pending();
239        return;
240    }
241    <process the signal>
242}
243
244delayed_signal_handler()
245{
246    <get n back>
247    Clr_Interrupts_Pending();
248    <process the signal>
249}
250\end{verbatim}
251
252
253The delayed signal handler is specified using the function
254
255\begin{verbatim}
256void irq_lock_init(void (*delayed_irq_fct)());
257\end{verbatim}
258
259
260A couple of macros is provided:
261
262\begin{verbatim}
263#define InterruptsDisabled      it_disabled_
264#define Disable_Int()           it_disabled_++;
265#define Enable_Int()    \
266        { if (--it_disabled_ == 0 && delayed_it_) (*delayed_irq_func)(); }
267
268#define InterruptsPending       delayed_it_
269#define Set_Interrupts_Pending() delayed_it_ = 1;
270#define Clr_Interrupts_Pending() delayed_it_ = 0;
271\end{verbatim}
272
273a_mutex_lock() internally calls Disable_Int().
274a_mutex_unlock() internally calls Enable_Int().
275Disable_Int() and Enable_Int() can also be called directly
276delay interrupts.
277
278
279\subsubsection{Private memory allocation}
280
281Initialisation:
282
283\begin{verbatim}
284private_mem_init(void (*)() panic_fct);
285\end{verbatim}
286
287To allocate and free private memory, use the generic allocation functions
288with the descriptor argument \&private_heap.
289
290
291