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