b68c6576b0bdd1df9a0e89523262289b3d814122
[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 <stdio.h>
44 #define kooctet 1024
45 int getfreememory(void)
46 {
47
48 #if defined(_MSC_VER)
49     {
50         MEMORYSTATUS stat;
51         GlobalMemoryStatus (&stat);
52         return (int)(stat.dwAvailPhys / kooctet);
53     }
54 #elif defined(hpux)
55     {
56         struct pst_static pst;
57         /*        pstat_getstatic(&pst, sizeof(pst), (size_t) 1, 0);
58               memorysizeKO=(pst.psd_free)/kooctet;*/
59         return 0;
60     }
61 #elif defined(__APPLE__)
62     {
63         vm_statistics_data_t page_info;
64         vm_size_t pagesize;
65         mach_msg_type_number_t count;
66         kern_return_t kret;
67
68         pagesize = 0;
69         kret = host_page_size (mach_host_self(), &pagesize);
70         count = HOST_VM_INFO_COUNT;
71
72         kret = host_statistics (mach_host_self(), HOST_VM_INFO, (host_info_t)&page_info, &count);
73         return page_info.free_count * pagesize / 1024;
74     }
75 #elif HAVE_TABLE && defined TBL_VMSTATS
76     {
77         /* This works on Tru64 UNIX V4/5.  */
78         struct tbl_vmstats vmstats;
79
80         if (table (TBL_VMSTATS, 0, &vmstats, 1, sizeof (vmstats)) == 1)
81         {
82             double pages = vmstats.free_count;
83             double pagesize = vmstats.pagesize;
84
85             if (0 <= pages && 0 <= pagesize)
86             {
87                 return pages * pagesize;
88             }
89             else
90             {
91                 return 0;
92             }
93         }
94     }
95 #elif defined(__linux__)
96     {
97         char field[9]  = {0};
98         long long data =  0;
99         char unit[4]   = {0};
100
101         long long free    = -1,
102                   buffers = -1,
103                   cached  = -1;
104
105         FILE *fp = fopen("/proc/meminfo", "r");
106         if (fp != NULL)
107         {
108             /* Read Cached, Buffers and MemFree from /proc/meminfo */
109             while (fscanf(fp, "%8s %lld %3s\n", field, &data, unit) != EOF)
110             {
111                 if (!strncmp("MemFree:", field, 8))
112                 {
113                     free = data;
114                 }
115                 else if (!strncmp("Buffers:", field, 8))
116                 {
117                     buffers = data;
118                 }
119                 else if (!strncmp("Cached:", field, 8))
120                 {
121                     cached = data;
122                 }
123             }
124             fclose(fp);
125
126             /* Read successful, convert unit and return the result */
127             if (buffers >= 0 && cached >= 0 && free >= 0)
128             {
129                 free += cached + buffers;
130                 switch (unit[0])
131                 {
132                     case 'g':
133                     case 'G':
134                         free *= kooctet;
135                     case 'm':
136                     case 'M':
137                         free *= kooctet;
138                         break;
139                     case 'o':
140                     case 'O':
141                         free /= kooctet;
142                 }
143                 return (int)free;
144             }
145         }
146
147         /* Strange, /proc not mounted ? new and unknown format ?
148            fall back to inaccurate sysconf() */
149         return (sysconf(_SC_AVPHYS_PAGES) * sysconf(_SC_PAGESIZE)) / kooctet;
150     }
151 #elif defined(__NetBSD__) || defined(__DragonFly__)
152     {
153         /* This works on *bsd.  */
154         int mib[2];
155         struct uvmexp_sysctl uvmexp;
156         long freemem;
157         size_t lenu = sizeof uvmexp;
158         unsigned int pagesize;
159         static int pageshift = PAGESHIFT_UNDEF;
160         size_t lenp = sizeof pagesize;
161
162         mib[0] = CTL_HW;
163         if (pageshift == PAGESHIFT_UNDEF)
164         {
165             /* Figure out the page size */
166             mib[1] = HW_PAGESIZE;
167             if (sysctl (mib, ARRAY_SIZE (mib), &pagesize, &lenp, NULL, 0) != 0 || lenp != sizeof (pagesize) )
168             {
169                 /* sysctl failed -- what to do?? */
170                 return 0;
171             }
172             pageshift = 0;
173             while (pagesize > 1)
174             {
175                 pageshift++;
176                 pagesize >>= 1;
177             }
178
179             /* convert to kB */
180             pageshift -= 10;
181         }
182
183         mib[0] = CTL_VM;
184         mib[1] = VM_UVMEXP2;
185         if ( (sysctl (mib, ARRAY_SIZE (mib), &uvmexp, &lenu, NULL, 0) == 0) && (lenu == sizeof (uvmexp)) )
186         {
187             return  (uvmexp.free << pageshift);
188         }
189
190         return 0;
191     }
192 #elif defined(__FreeBSD__)
193     int avphys_pages;
194     size_t oldlenp = sizeof (avphys_pages);
195     sysctlbyname("vm.stats.vm.v_free_count", &avphys_pages, &oldlenp, NULL, NULL);
196     return (avphys_pages / kooctet) * sysconf(_SC_PAGESIZE);
197
198 #else
199     /* Solaris and others assumed*/
200     return (sysconf(_SC_AVPHYS_PAGES) / kooctet) * sysconf(_SC_PAGESIZE);
201 #endif
202 }
203 /*--------------------------------------------------------------------------*/
204 int getmemorysize()
205 {
206 #if defined(_MSC_VER)
207     {
208         MEMORYSTATUS stat;
209         GlobalMemoryStatus (&stat);
210         return (int)(stat.dwTotalPhys / kooctet);
211     }
212 #elif defined(hpux)
213     {
214         struct pst_static pst;
215         pstat_getstatic(&pst, sizeof(pst), (size_t) 1, 0);
216         return (int)((pst.physical_memory) / kooctet);
217     }
218 #elif defined(__APPLE__) || defined(__NetBSD__) || defined(__DragonFly__)
219     {
220         /* this works on *bsd and darwin */
221         size_t len;
222         int total;
223         int mib[2];
224
225         mib[0] = CTL_HW;
226         mib[1] = HW_PHYSMEM;
227         len = sizeof (total);
228
229         sysctl(mib, 2, &total, &len, NULL, 0);
230         return  total / 1024;
231     }
232 #elif HAVE_GETSYSINFO && defined GSI_PHYSMEM
233     {
234         /* This works on Tru64 UNIX V4/5.  */
235         int physmem;
236
237         if (getsysinfo (GSI_PHYSMEM, (caddr_t) &physmem, sizeof (physmem),
238         NULL, NULL, NULL) == 1)
239         {
240             double kbytes = physmem;
241
242             if (0 <= kbytes)
243             {
244                 return kbytes * 1024.0;
245             }
246             else
247             {
248                 return 0;
249             }
250         }
251     }
252 #else
253     /* Linux ,Solaris and others */
254     return (sysconf(_SC_PHYS_PAGES) / kooctet) * sysconf(_SC_PAGESIZE);
255 #endif
256 }
257 /*--------------------------------------------------------------------------*/