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