Fix stacksize max for Mac OS X
[scilab.git] / scilab / modules / core / sci_gateway / c / sci_stacksize.c
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2006 - INRIA - Allan CORNET
4 * Copyright (C) 2009-2010 - DIGITEO - Allan CORNET
5 *
6 * This file must be used under the terms of the CeCILL.
7 * This source file is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution.  The terms
9 * are also available at
10 * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
11 *
12 */
13 #ifdef _MSC_VER
14 #include <Windows.h>
15 #else
16 #include <unistd.h>
17 #endif
18 #include <stdio.h>
19
20 #include "gw_core.h"
21 #include "stack-c.h"
22 #include "MALLOC.h"
23 #include "getmaxMALLOC.h"
24 #include "scimem.h"
25 #include "localization.h"
26 #include "stackinfo.h"
27 #include "Scierror.h"
28 #include "sciprint.h"
29 #include "dynamic_parallel.h"
30 /*--------------------------------------------------------------------------*/
31 extern int C2F(adjuststacksize) ();
32
33 /*--------------------------------------------------------------------------*/
34 #define MIN_STACKSIZE 180000
35 #define PARAM_MAX_STR "max"
36 #define PARAM_MIN_STR "min"
37 /*--------------------------------------------------------------------------*/
38 static int sci_stacksizeNoRhs(char *fname);
39 static int sci_stacksizeOneRhs(char *fname);
40 static int sci_stacksizeMax(char *fname);
41 static int sci_stacksizeMin(char *fname);
42 static int setStacksizeMin(char *fname);
43 static int setStacksizeMax(char *fname);
44 static int setStacksize(unsigned long newsize);
45 static unsigned long getCurrentStacksize(void);
46 static unsigned long getUsedStacksize(void);
47 static char *getStackCreationErrorMessage(int errCode);
48
49 /*--------------------------------------------------------------------------*/
50 /**
51 * stacksize - set scilab stack size
52 * Calling Sequence
53 * stacksize(n)
54 * stacksize('max')
55 * stacksize('min')
56 * sz=stacksize()
57 * Parameters
58 * n : integer, the required stack size given in number of double precision words
59 * 'max' : try to allocate the maximum of memory
60 * 'max' : allocate the minimum of memory
61 * sz : 2-vector [total used]
62 */
63 /*--------------------------------------------------------------------------*/
64 int C2F(sci_stacksize) (char *fname, unsigned long fname_len)
65 {
66
67     Rhs = Max(0, Rhs);
68     CheckRhs(0, 1);
69     CheckLhs(0, 1);
70
71     if (Rhs == 0)
72     {
73         return sci_stacksizeNoRhs(fname);
74     }
75     return dynParallelConcurrency() ? dynParallelForbidden(fname) : sci_stacksizeOneRhs(fname);
76 }
77
78 /*--------------------------------------------------------------------------*/
79 static int sci_stacksizeNoRhs(char *fname)
80 {
81     int n1 = 0, m1 = 0;
82     int *paramoutINT = NULL;
83     int total = 0;
84     int used = 0;
85
86     paramoutINT = (int *)MALLOC(sizeof(int) * 2);
87
88     C2F(getstackinfo) (&total, &used);
89     paramoutINT[0] = total;
90     paramoutINT[1] = used;
91
92     n1 = 1;
93     m1 = 2;
94     CreateVarFromPtr(Rhs + 1, MATRIX_OF_INTEGER_DATATYPE, &n1, &m1, (int *)&paramoutINT);
95
96     LhsVar(1) = Rhs + 1;
97
98     if (paramoutINT)
99     {
100         FREE(paramoutINT);
101         paramoutINT = NULL;
102     }
103
104     PutLhsVar();
105     return 0;
106 }
107
108 /*--------------------------------------------------------------------------*/
109 static int sci_stacksizeOneRhs(char *fname)
110 {
111     int l1 = 0, n1 = 0, m1 = 0;
112     int errCode = 0;
113
114     if (GetType(1) == sci_matrix)
115     {
116         GetRhsVar(1, MATRIX_OF_DOUBLE_DATATYPE, &m1, &n1, &l1);
117         if ((m1 == 1) && (n1 == 1))
118         {
119             unsigned long NEWMEMSTACKSIZE = (unsigned long) * stk(l1);
120
121             /* add 1 for alignment problems */
122             if (is_a_valid_size_for_scilab_stack(NEWMEMSTACKSIZE + 1))
123             {
124                 if ((NEWMEMSTACKSIZE >= MIN_STACKSIZE) && (NEWMEMSTACKSIZE <= get_max_memory_for_scilab_stack()))
125                 {
126                     /* we backup previous size */
127                     unsigned long backupSize = getCurrentStacksize();
128
129                     errCode = setStacksizeMin(fname);
130                     if (errCode == 0)
131                     {
132                         errCode = setStacksize(NEWMEMSTACKSIZE);
133                         if (errCode == 0)
134                         {
135                             LhsVar(1) = 0;
136                             PutLhsVar();
137                             return 0;
138                         }
139                         else
140                         {
141                             /* restore previous size */
142                             setStacksize(backupSize);
143                             Scierror(10001, _("%s: Cannot allocate memory.\n%s\n"), fname, getStackCreationErrorMessage(errCode));
144                         }
145                     }
146                     else
147                     {
148                         /* restore previous size */
149                         setStacksize(backupSize);
150                         Scierror(10001, _("%s: Cannot allocate memory.\n%s\n"), fname, getStackCreationErrorMessage(errCode));
151                     }
152
153                 }
154                 else
155                 {
156                     Scierror(1504, _("%s: Out of bounds value. Not in [%lu,%lu].\n"), fname, MIN_STACKSIZE, get_max_memory_for_scilab_stack() - 1);
157                 }
158             }
159             else
160             {
161                 Scierror(1504, _("%s: Out of bounds value. Not in [%lu,%lu].\n"), fname, MIN_STACKSIZE, get_max_memory_for_scilab_stack() - 1);
162             }
163         }
164         else
165         {
166             Scierror(204, _("%s: Wrong size for input argument #%d: Scalar expected.\n"), fname, 1);
167         }
168     }
169     else if (GetType(1) == sci_strings)
170     {
171         char *param = NULL;
172
173         GetRhsVar(1, STRING_DATATYPE, &m1, &n1, &l1);
174         param = cstk(l1);
175         if (strcmp(PARAM_MAX_STR, param) == 0)
176         {
177             return sci_stacksizeMax(fname);
178         }
179         else if (strcmp(PARAM_MIN_STR, param) == 0)
180         {
181             return sci_stacksizeMin(fname);
182         }
183         else
184         {
185             Scierror(204, _("%s: Wrong type for input argument #%d: Scalar, '%s' or '%s'.\n"), fname, 1, "min", "max");
186         }
187     }
188     else
189     {
190         Scierror(204, _("%s: Wrong type for input argument #%d: Scalar, '%s' or '%s'.\n"), fname, 1, "min", "max");
191     }
192     return 0;
193 }
194
195 /*--------------------------------------------------------------------------*/
196 static int sci_stacksizeMax(char *fname)
197 {
198     if (setStacksizeMax(fname) == 0)
199     {
200         LhsVar(1) = 0;
201         PutLhsVar();
202     }
203     else
204     {
205         Scierror(10001, _("%s: Cannot allocate memory.\n"), fname);
206     }
207     return 0;
208 }
209
210 /*--------------------------------------------------------------------------*/
211 static int sci_stacksizeMin(char *fname)
212 {
213     if (setStacksizeMin(fname) == 0)
214     {
215         LhsVar(1) = 0;
216         PutLhsVar();
217     }
218     else
219     {
220         Scierror(10001, _("%s: Cannot allocate memory.\n"), fname);
221     }
222     return 0;
223 }
224
225 /*--------------------------------------------------------------------------*/
226 static int setStacksizeMin(char *fname)
227 {
228     unsigned long memstackused = getUsedStacksize();
229
230     if (memstackused < MIN_STACKSIZE)
231     {
232         return setStacksize(MIN_STACKSIZE);
233     }
234     else
235     {
236         /* Add 3000 security for the stack */
237         return setStacksize(memstackused + 3000);
238     }
239 }
240
241 /*--------------------------------------------------------------------------*/
242 static int setStacksizeMax(char *fname)
243 {
244     /* we backup previous size */
245     unsigned long backupSize = getCurrentStacksize();
246
247     /* Bug 5495 on Windows 2000 -- WONT FIX GetLargestFreeMemoryRegion */
248     /* it works on XP, Vista, S7ven */
249     /* GetLargestFreeMemoryRegion() returns a superior size to real value */
250     unsigned long maxmemfree = (GetLargestFreeMemoryRegion()) / sizeof(double);
251
252     /* We have already max */
253     if (maxmemfree <= backupSize)
254     {
255         LhsVar(1) = 0;
256         PutLhsVar();
257         return 0;
258     }
259
260     /* we do a stacksize('min') */
261     if (setStacksizeMin(fname) == 0)
262     {
263         int errCode = 0;
264         if (maxmemfree < MIN_STACKSIZE)
265         {
266             maxmemfree = MIN_STACKSIZE;
267         }
268
269         errCode = setStacksize(maxmemfree);
270         if (errCode != 0)
271         {
272             setStacksize(backupSize);
273             Scierror(10001, _("%s: Cannot allocate memory.\n%s\n"), fname, getStackCreationErrorMessage(errCode));
274         }
275         return 0;
276     }
277     else
278     {
279         /* stacksize('min') fails */
280         /* restore previous size */
281         setStacksize(backupSize);
282         Scierror(10001, _("%s: Cannot allocate memory.\n"), fname);
283     }
284     return 0;
285 }
286
287 /*--------------------------------------------------------------------------*/
288 /*
289  *
290  * @return 0 if success
291  *         -1 if cannot allocate this quantity of memory
292  *         -2 if the requested size is smaller than the minimal one
293  *         -3 unable to create (or resize) the stack (probably a malloc error
294  */
295 static int setStacksize(unsigned long newsize)
296 {
297     if (newsize != getCurrentStacksize())
298     {
299         if ((newsize >= MIN_STACKSIZE))
300         {
301             if ((newsize <= get_max_memory_for_scilab_stack()))
302             {
303                 unsigned long ptr = 0;
304
305                 C2F(scimem) (&newsize, &ptr);
306                 if (ptr)
307                 {
308                     LhsVar(1) = 0;
309                     C2F(putlhsvar) ();
310
311                     C2F(adjuststacksize) (&newsize, &ptr);
312                     return 0;
313                 }
314                 //sciprint("  malloc error\n");
315                 return -3;      /* We haven't been able to create (or resize) the stack (probably a malloc error */
316             }
317             /* Not possible to assign that amount of memory */
318             //sciprint("  Not Enough Minerals !\n");
319             return -1;
320         }
321         /* Trying to create a too small stack */
322         //sciprint("  < MIN_STACKSIZE\n");
323         return -2;
324     }
325     /* Set the stacksize to the same size... No need to do anything */
326     //sciprint("  same size\n");
327     return 0;
328 }
329
330 /*--------------------------------------------------------------------------*/
331 static unsigned long getCurrentStacksize(void)
332 {
333     unsigned long memstacktotal = 0;
334     unsigned long memstackused = 0;
335
336     C2F(getstackinfo) (&memstacktotal, &memstackused);
337
338     return memstacktotal;
339 }
340
341 /*--------------------------------------------------------------------------*/
342 static unsigned long getUsedStacksize(void)
343 {
344     unsigned long memstacktotal = 0;
345     unsigned long memstackused = 0;
346
347     C2F(getstackinfo) (&memstacktotal, &memstackused);
348
349     return memstackused;
350 }
351
352 /*--------------------------------------------------------------------------*/
353
354 static char *getStackCreationErrorMessage(int errCode)
355 {
356     switch (errCode)
357     {
358         case -1:
359             return _("%s: Cannot allocate this quantity of memory.\n");
360             break;
361         case -2:
362             return _("%s: The requested size is smaller than the minimal one.\n");
363             break;
364         case -3:
365             return _("%s: Unable to create (or resize) the stack (probably a malloc error).\n");
366             break;
367     }
368     return _("%s: Unknown error.\n");
369 }
370
371 /*--------------------------------------------------------------------------*/