0eab2ce4cc143c3e2c217a3d2f4a786295f09ff1
[scilab.git] / scilab / modules / core / src / c / getmemory.c
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2005 - INRIA - Allan CORNET
4  * Copyright (C) 2009 - Dan McMahill (Fix of bug 4299 and 4312)
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
14 /* References
15 @sa http://nixdoc.net/man-pages/Tru64/man2/getsysinfo.2.html
16 @sa http://www.opensource.apple.com/darwinsource/projects/other/gccfast-1621.1/libiberty/physmem.c
17 @sa http://lists.gnu.org/archive/html/bug-gnulib/2003-08/msg00102.html
18 @sa http://netbsd.gw.com/cgi-bin/man-cgi?sysctl+3+NetBSD-4.0
19 @sa http://cvsweb.netbsd.org/bsdweb.cgi/pkgsrc/math/scilab/patches/patch-aj?annotate=1.9
20 */
21
22 #if defined(__linux__)
23 #define _GNU_SOURCE /* Bug 5673 fix: avoid dependency on GLIBC_2.7 */
24 #endif
25
26 #include "getmemory.h"
27
28 #ifdef _MSC_VER
29 #include <windows.h>
30 #endif
31
32 #if defined(__NetBSD__) || defined(__DragonFly__)
33 #include <sys/param.h>
34 #include <sys/sysctl.h>
35 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
36 #define PAGESHIFT_UNDEF -100
37 #elif defined(__FreeBSD__)
38 #include <sys/param.h>
39 #include <sys/sysctl.h>
40 #endif
41
42
43 #include <string.h>
44 #include <stdio.h>
45 #define kooctet 1024
46 int getfreememory(void)
47 {
48
49 #if defined(_MSC_VER)
50     {
51         MEMORYSTATUS stat;
52         GlobalMemoryStatus (&stat);
53         return (int)(stat.dwAvailPhys / kooctet);
54     }
55 #elif defined(hpux)
56     {
57         struct pst_static pst;
58         /*        pstat_getstatic(&pst, sizeof(pst), (size_t) 1, 0);
59               memorysizeKO=(pst.psd_free)/kooctet;*/
60         return 0;
61     }
62 #elif defined(__APPLE__)
63     {
64         vm_statistics_data_t page_info;
65         vm_size_t pagesize;
66         mach_msg_type_number_t count;
67         kern_return_t kret;
68
69         pagesize = 0;
70         kret = host_page_size (mach_host_self(), &pagesize);
71         count = HOST_VM_INFO_COUNT;
72
73         kret = host_statistics (mach_host_self(), HOST_VM_INFO, (host_info_t)&page_info, &count);
74         return page_info.free_count * pagesize / 1024;
75     }
76 #elif HAVE_TABLE && defined TBL_VMSTATS
77     {
78         /* This works on Tru64 UNIX V4/5.  */
79         struct tbl_vmstats vmstats;
80
81         if (table (TBL_VMSTATS, 0, &vmstats, 1, sizeof (vmstats)) == 1)
82         {
83             double pages = vmstats.free_count;
84             double pagesize = vmstats.pagesize;
85
86             if (0 <= pages && 0 <= pagesize)
87             {
88                 return pages * pagesize;
89             }
90             else
91             {
92                 return 0;
93             }
94         }
95     }
96 #elif defined(__linux__)
97     {
98         char field[9]  = {0};
99         long long data =  0;
100         char unit[4]   = {0};
101
102         long long free    = -1,
103                   buffers = -1,
104                   cached  = -1;
105
106         FILE *fp = fopen("/proc/meminfo", "r");
107         if (fp != NULL)
108         {
109             /* Read Cached, Buffers and MemFree from /proc/meminfo */
110             while (fscanf(fp, "%8s %lld %3s\n", field, &data, unit) != EOF)
111             {
112                 if (!strncmp("MemFree:", field, 8))
113                 {
114                     free = data;
115                 }
116                 else if (!strncmp("Buffers:", field, 8))
117                 {
118                     buffers = data;
119                 }
120                 else if (!strncmp("Cached:", field, 8))
121                 {
122                     cached = data;
123                 }
124             }
125             fclose(fp);
126
127             /* Read successful, convert unit and return the result */
128             if (buffers >= 0 && cached >= 0 && free >= 0)
129             {
130                 free += cached + buffers;
131                 switch (unit[0])
132                 {
133                     case 'g':
134                     case 'G':
135                         free *= kooctet;
136                     case 'm':
137                     case 'M':
138                         free *= kooctet;
139                         break;
140                     case 'o':
141                     case 'O':
142                         free /= kooctet;
143                 }
144                 return (int)free;
145             }
146         }
147
148         /* Strange, /proc not mounted ? new and unknown format ?
149            fall back to inaccurate sysconf() */
150         return (sysconf(_SC_AVPHYS_PAGES) * sysconf(_SC_PAGESIZE)) / kooctet;
151     }
152 #elif defined(__NetBSD__) || defined(__DragonFly__)
153     {
154         /* This works on *bsd.  */
155         int mib[2];
156         struct uvmexp_sysctl uvmexp;
157         long freemem;
158         size_t lenu = sizeof uvmexp;
159         unsigned int pagesize;
160         static int pageshift = PAGESHIFT_UNDEF;
161         size_t lenp = sizeof pagesize;
162
163         mib[0] = CTL_HW;
164         if (pageshift == PAGESHIFT_UNDEF)
165         {
166             /* Figure out the page size */
167             mib[1] = HW_PAGESIZE;
168             if (sysctl (mib, ARRAY_SIZE (mib), &pagesize, &lenp, NULL, 0) != 0 || lenp != sizeof (pagesize) )
169             {
170                 /* sysctl failed -- what to do?? */
171                 return 0;
172             }
173             pageshift = 0;
174             while (pagesize > 1)
175             {
176                 pageshift++;
177                 pagesize >>= 1;
178             }
179
180             /* convert to kB */
181             pageshift -= 10;
182         }
183
184         mib[0] = CTL_VM;
185         mib[1] = VM_UVMEXP2;
186         if ( (sysctl (mib, ARRAY_SIZE (mib), &uvmexp, &lenu, NULL, 0) == 0) && (lenu == sizeof (uvmexp)) )
187         {
188             return  (uvmexp.free << pageshift);
189         }
190
191         return 0;
192     }
193 #elif defined(__FreeBSD__)
194     int avphys_pages;
195     size_t oldlenp = sizeof (avphys_pages);
196     sysctlbyname("vm.stats.vm.v_free_count", &avphys_pages, &oldlenp, NULL, NULL);
197     return (avphys_pages / kooctet) * sysconf(_SC_PAGESIZE);
198
199 #else
200     /* Solaris and others assumed*/
201     return (sysconf(_SC_AVPHYS_PAGES) / kooctet) * sysconf(_SC_PAGESIZE);
202 #endif
203 }
204 /*--------------------------------------------------------------------------*/
205 int getmemorysize()
206 {
207 #if defined(_MSC_VER)
208     {
209         MEMORYSTATUS stat;
210         GlobalMemoryStatus (&stat);
211         return (int)(stat.dwTotalPhys / kooctet);
212     }
213 #elif defined(hpux)
214     {
215         struct pst_static pst;
216         pstat_getstatic(&pst, sizeof(pst), (size_t) 1, 0);
217         return (int)((pst.physical_memory) / kooctet);
218     }
219 #elif defined(__APPLE__) || defined(__NetBSD__) || defined(__DragonFly__)
220     {
221         /* this works on *bsd and darwin */
222         size_t len;
223         int total;
224         int mib[2];
225
226         mib[0] = CTL_HW;
227         mib[1] = HW_PHYSMEM;
228         len = sizeof (total);
229
230         sysctl(mib, 2, &total, &len, NULL, 0);
231         return  total / 1024;
232     }
233 #elif HAVE_GETSYSINFO && defined GSI_PHYSMEM
234     {
235         /* This works on Tru64 UNIX V4/5.  */
236         int physmem;
237
238         if (getsysinfo (GSI_PHYSMEM, (caddr_t) &physmem, sizeof (physmem),
239         NULL, NULL, NULL) == 1)
240         {
241             double kbytes = physmem;
242
243             if (0 <= kbytes)
244             {
245                 return kbytes * 1024.0;
246             }
247             else
248             {
249                 return 0;
250             }
251         }
252     }
253 #else
254     /* Linux ,Solaris and others */
255     return (sysconf(_SC_PHYS_PAGES) / kooctet) * sysconf(_SC_PAGESIZE);
256 #endif
257 }
258 /*--------------------------------------------------------------------------*/