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
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
17 #include <sys/sysinfo.h>
24 #include "getmaxMALLOC.h"
26 #include "localization.h"
27 #include "stackinfo.h"
29 #include "dynamic_parallel.h"
30 /*--------------------------------------------------------------------------*/
31 extern int C2F(adjuststacksize) ();
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);
49 /*--------------------------------------------------------------------------*/
51 * stacksize - set scilab stack size
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]
63 /*--------------------------------------------------------------------------*/
64 int C2F(sci_stacksize) (char *fname, unsigned long fname_len)
73 return sci_stacksizeNoRhs(fname);
75 return dynParallelConcurrency() ? dynParallelForbidden(fname) : sci_stacksizeOneRhs(fname);
78 /*--------------------------------------------------------------------------*/
79 static int sci_stacksizeNoRhs(char *fname)
82 int *paramoutINT = NULL;
86 paramoutINT = (int *)MALLOC(sizeof(int) * 2);
88 C2F(getstackinfo) (&total, &used);
89 paramoutINT[0] = total;
90 paramoutINT[1] = used;
94 CreateVarFromPtr(Rhs + 1, MATRIX_OF_INTEGER_DATATYPE, &n1, &m1, (int *)¶moutINT);
108 /*--------------------------------------------------------------------------*/
109 static int sci_stacksizeOneRhs(char *fname)
111 int l1 = 0, n1 = 0, m1 = 0;
114 if (GetType(1) == sci_matrix)
116 GetRhsVar(1, MATRIX_OF_DOUBLE_DATATYPE, &m1, &n1, &l1);
117 if ((m1 == 1) && (n1 == 1))
119 unsigned long NEWMEMSTACKSIZE = (unsigned long) * stk(l1);
121 /* add 1 for alignment problems */
122 if (is_a_valid_size_for_scilab_stack(NEWMEMSTACKSIZE + 1))
124 if ((NEWMEMSTACKSIZE >= MIN_STACKSIZE) && (NEWMEMSTACKSIZE <= get_max_memory_for_scilab_stack()))
126 /* we backup previous size */
127 unsigned long backupSize = getCurrentStacksize();
129 errCode = setStacksizeMin(fname);
132 errCode = setStacksize(NEWMEMSTACKSIZE);
141 /* restore previous size */
142 setStacksize(backupSize);
143 Scierror(10001, _("%s: Cannot allocate memory.\n%s\n"), fname, getStackCreationErrorMessage(errCode));
148 /* restore previous size */
149 setStacksize(backupSize);
150 Scierror(10001, _("%s: Cannot allocate memory.\n%s\n"), fname, getStackCreationErrorMessage(errCode));
156 Scierror(1504, _("%s: Out of bounds value. Not in [%lu,%lu].\n"), fname, MIN_STACKSIZE, get_max_memory_for_scilab_stack() - 1);
161 Scierror(1504, _("%s: Out of bounds value. Not in [%lu,%lu].\n"), fname, MIN_STACKSIZE, get_max_memory_for_scilab_stack() - 1);
166 Scierror(204, _("%s: Wrong size for input argument #%d: Scalar expected.\n"), fname, 1);
169 else if (GetType(1) == sci_strings)
173 GetRhsVar(1, STRING_DATATYPE, &m1, &n1, &l1);
175 if (strcmp(PARAM_MAX_STR, param) == 0)
177 return sci_stacksizeMax(fname);
179 else if (strcmp(PARAM_MIN_STR, param) == 0)
181 return sci_stacksizeMin(fname);
185 Scierror(204, _("%s: Wrong type for input argument #%d: Scalar, '%s' or '%s'.\n"), fname, 1, "min", "max");
190 Scierror(204, _("%s: Wrong type for input argument #%d: Scalar, '%s' or '%s'.\n"), fname, 1, "min", "max");
195 /*--------------------------------------------------------------------------*/
196 static int sci_stacksizeMax(char *fname)
198 if (setStacksizeMax(fname) == 0)
205 Scierror(10001, _("%s: Cannot allocate memory.\n"), fname);
210 /*--------------------------------------------------------------------------*/
211 static int sci_stacksizeMin(char *fname)
213 if (setStacksizeMin(fname) == 0)
220 Scierror(10001, _("%s: Cannot allocate memory.\n"), fname);
225 /*--------------------------------------------------------------------------*/
226 static int setStacksizeMin(char *fname)
228 unsigned long memstackused = getUsedStacksize();
230 if (memstackused < MIN_STACKSIZE)
232 return setStacksize(MIN_STACKSIZE);
236 /* Add 3000 security for the stack */
237 return setStacksize(memstackused + 3000);
241 /*--------------------------------------------------------------------------*/
242 static int setStacksizeMax(char *fname)
244 /* we backup previous size */
245 unsigned long backupSize = getCurrentStacksize();
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);
252 long long freePhysicalMem = 0;
254 MEMORYSTATUSEX statex;
255 statex.dwLength = sizeof (statex);
256 GlobalMemoryStatusEx (&statex);
257 //do not exceed available free memory
259 //use min value between max memory available and max "allocable" memory by Scilab
261 freePhysicalMem = (long long)(statex.ullAvailPageFile / sizeof(double));
262 //if free memory is used, keep 10% to OS
264 freePhysicalMem = (long long)((get_avphys_pages() * get_phys_pages()) / sizeof(double));
267 if (freePhysicalMem > 0 && freePhysicalMem < maxmemfree)
269 maxmemfree = (unsigned long)(freePhysicalMem * 0.9);
272 /* We have already max */
273 if (maxmemfree <= backupSize)
280 /* we do a stacksize('min') */
281 if (setStacksizeMin(fname) == 0)
283 unsigned long memmaxavailablebyscilab = get_max_memory_for_scilab_stack();
284 unsigned long newMemSizeMax = maxmemfree;
287 if (memmaxavailablebyscilab < newMemSizeMax)
289 newMemSizeMax = memmaxavailablebyscilab;
292 if (newMemSizeMax < MIN_STACKSIZE)
294 newMemSizeMax = MIN_STACKSIZE;
297 errCode = setStacksize(newMemSizeMax);
300 setStacksize(backupSize);
301 Scierror(10001, _("%s: Cannot allocate memory.\n%s\n"), fname, getStackCreationErrorMessage(errCode));
307 /* stacksize('min') fails */
308 /* restore previous size */
309 setStacksize(backupSize);
310 Scierror(10001, _("%s: Cannot allocate memory.\n"), fname);
315 /*--------------------------------------------------------------------------*/
318 * @return 0 if success
319 * -1 if cannot allocate this quantity of memory
320 * -2 if the requested size is smaller than the minimal one
321 * -3 unable to create (or resize) the stack (probably a malloc error
323 static int setStacksize(unsigned long newsize)
325 if (newsize != getCurrentStacksize())
327 if ((newsize >= MIN_STACKSIZE))
329 if ((newsize <= get_max_memory_for_scilab_stack()))
331 unsigned long ptr = 0;
333 C2F(scimem) (&newsize, &ptr);
339 C2F(adjuststacksize) (&newsize, &ptr);
342 return -3; /* We haven't been able to create (or resize) the stack (probably a malloc error */
344 /* Not possible to assign that amount of memory */
347 /* Trying to create a too small stack */
350 /* Set the stacksize to the same size... No need to do anything */
354 /*--------------------------------------------------------------------------*/
355 static unsigned long getCurrentStacksize(void)
357 unsigned long memstacktotal = 0;
358 unsigned long memstackused = 0;
360 C2F(getstackinfo) (&memstacktotal, &memstackused);
362 return memstacktotal;
365 /*--------------------------------------------------------------------------*/
366 static unsigned long getUsedStacksize(void)
368 unsigned long memstacktotal = 0;
369 unsigned long memstackused = 0;
371 C2F(getstackinfo) (&memstacktotal, &memstackused);
376 /*--------------------------------------------------------------------------*/
378 static char *getStackCreationErrorMessage(int errCode)
383 return _("%s: Cannot allocate this quantity of memory.\n");
386 return _("%s: The requested size is smaller than the minimal one.\n");
389 return _("%s: Unable to create (or resize) the stack (probably a malloc error).\n");
392 return _("%s: Unknown error.\n");
395 /*--------------------------------------------------------------------------*/