Core: fix Linux compilation
[scilab.git] / scilab / modules / core / src / c / getmemory.c
index 7147d9f..0eab2ce 100644 (file)
+/*
+ * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+ * Copyright (C) 2005 - INRIA - Allan CORNET
+ * Copyright (C) 2009 - Dan McMahill (Fix of bug 4299 and 4312)
+ *
+ * This file must be used under the terms of the CeCILL.
+ * This source file is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution.  The terms
+ * are also available at
+ * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+ *
+ */
 
-/*--------------------------------------------------------------------------*/
-/* INRIA 2005 */
-/* Allan CORNET */
 /* References
 @sa http://nixdoc.net/man-pages/Tru64/man2/getsysinfo.2.html
 @sa http://www.opensource.apple.com/darwinsource/projects/other/gccfast-1621.1/libiberty/physmem.c
 @sa http://lists.gnu.org/archive/html/bug-gnulib/2003-08/msg00102.html
+@sa http://netbsd.gw.com/cgi-bin/man-cgi?sysctl+3+NetBSD-4.0
+@sa http://cvsweb.netbsd.org/bsdweb.cgi/pkgsrc/math/scilab/patches/patch-aj?annotate=1.9
 */
+
+#if defined(__linux__)
+#define _GNU_SOURCE /* Bug 5673 fix: avoid dependency on GLIBC_2.7 */
+#endif
+
 #include "getmemory.h"
 
-int getfreememory()
-{
+#ifdef _MSC_VER
+#include <windows.h>
+#endif
+
+#if defined(__NetBSD__) || defined(__DragonFly__)
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
+#define PAGESHIFT_UNDEF -100
+#elif defined(__FreeBSD__)
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#endif
+
+
+#include <string.h>
+#include <stdio.h>
 #define kooctet 1024
-#undef MEMOK
+int getfreememory(void)
+{
 
 #if defined(_MSC_VER)
-  {
-    #define MEMOK 1
-    MEMORYSTATUS stat;
-    GlobalMemoryStatus (&stat);
-    return (int)(stat.dwAvailPhys/kooctet);
-  }
-#endif
+    {
+        MEMORYSTATUS stat;
+        GlobalMemoryStatus (&stat);
+        return (int)(stat.dwAvailPhys / kooctet);
+    }
+#elif defined(hpux)
+    {
+        struct pst_static pst;
+        /*        pstat_getstatic(&pst, sizeof(pst), (size_t) 1, 0);
+              memorysizeKO=(pst.psd_free)/kooctet;*/
+        return 0;
+    }
+#elif defined(__APPLE__)
+    {
+        vm_statistics_data_t page_info;
+        vm_size_t pagesize;
+        mach_msg_type_number_t count;
+        kern_return_t kret;
 
-#if defined(hpux)
-#define MEMOK 1
+        pagesize = 0;
+        kret = host_page_size (mach_host_self(), &pagesize);
+        count = HOST_VM_INFO_COUNT;
 
- {
-   struct pst_static pst;
-  /*   pstat_getstatic(&pst, sizeof(pst), (size_t) 1, 0);
-       memorysizeKO=(pst.psd_free)/kooctet;*/
-  return 0;
- }
+        kret = host_statistics (mach_host_self(), HOST_VM_INFO, (host_info_t)&page_info, &count);
+        return page_info.free_count * pagesize / 1024;
+    }
+#elif HAVE_TABLE && defined TBL_VMSTATS
+    {
+        /* This works on Tru64 UNIX V4/5.  */
+        struct tbl_vmstats vmstats;
 
-#endif
-#if defined(__APPLE__) 
-#define MEMOK 1
-      {
-       vm_statistics_data_t page_info;
-       vm_size_t pagesize;
-       mach_msg_type_number_t count;
-       kern_return_t kret;
-    
-       pagesize = 0;
-       kret = host_page_size (mach_host_self(), &pagesize);
-       count = HOST_VM_INFO_COUNT;
-    
-       kret = host_statistics (mach_host_self(), HOST_VM_INFO,(host_info_t)&page_info, &count);
-       return page_info.free_count*pagesize / 1024;
-      }
-#endif
+        if (table (TBL_VMSTATS, 0, &vmstats, 1, sizeof (vmstats)) == 1)
+        {
+            double pages = vmstats.free_count;
+            double pagesize = vmstats.pagesize;
 
-#if HAVE_TABLE && defined TBL_VMSTATS
-#define MEMOK 1
-   { /* This works on Tru64 UNIX V4/5.  */
-     struct tbl_vmstats vmstats;
-
-     if (table (TBL_VMSTATS, 0, &vmstats, 1, sizeof (vmstats)) == 1)
-       {
-         double pages = vmstats.free_count;
-         double pagesize = vmstats.pagesize;
-
-         if (0 <= pages && 0 <= pagesize)
-           return pages * pagesize;
-        else
-          return 0;
-       }
-   }
-#endif
+            if (0 <= pages && 0 <= pagesize)
+            {
+                return pages * pagesize;
+            }
+            else
+            {
+                return 0;
+            }
+        }
+    }
+#elif defined(__linux__)
+    {
+        char field[9]  = {0};
+        long long data =  0;
+        char unit[4]   = {0};
 
-#ifndef  MEMOK
-/* Linux ,Solaris and others assumed*/
-      return (sysconf(_SC_AVPHYS_PAGES)*sysconf(_SC_PAGESIZE))/kooctet;
-#endif
+        long long free    = -1,
+                  buffers = -1,
+                  cached  = -1;
 
+        FILE *fp = fopen("/proc/meminfo", "r");
+        if (fp != NULL)
+        {
+            /* Read Cached, Buffers and MemFree from /proc/meminfo */
+            while (fscanf(fp, "%8s %lld %3s\n", field, &data, unit) != EOF)
+            {
+                if (!strncmp("MemFree:", field, 8))
+                {
+                    free = data;
+                }
+                else if (!strncmp("Buffers:", field, 8))
+                {
+                    buffers = data;
+                }
+                else if (!strncmp("Cached:", field, 8))
+                {
+                    cached = data;
+                }
+            }
+            fclose(fp);
+
+            /* Read successful, convert unit and return the result */
+            if (buffers >= 0 && cached >= 0 && free >= 0)
+            {
+                free += cached + buffers;
+                switch (unit[0])
+                {
+                    case 'g':
+                    case 'G':
+                        free *= kooctet;
+                    case 'm':
+                    case 'M':
+                        free *= kooctet;
+                        break;
+                    case 'o':
+                    case 'O':
+                        free /= kooctet;
+                }
+                return (int)free;
+            }
+        }
+
+        /* Strange, /proc not mounted ? new and unknown format ?
+           fall back to inaccurate sysconf() */
+        return (sysconf(_SC_AVPHYS_PAGES) * sysconf(_SC_PAGESIZE)) / kooctet;
+    }
+#elif defined(__NetBSD__) || defined(__DragonFly__)
+    {
+        /* This works on *bsd.  */
+        int mib[2];
+        struct uvmexp_sysctl uvmexp;
+        long freemem;
+        size_t lenu = sizeof uvmexp;
+        unsigned int pagesize;
+        static int pageshift = PAGESHIFT_UNDEF;
+        size_t lenp = sizeof pagesize;
+
+        mib[0] = CTL_HW;
+        if (pageshift == PAGESHIFT_UNDEF)
+        {
+            /* Figure out the page size */
+            mib[1] = HW_PAGESIZE;
+            if (sysctl (mib, ARRAY_SIZE (mib), &pagesize, &lenp, NULL, 0) != 0 || lenp != sizeof (pagesize) )
+            {
+                /* sysctl failed -- what to do?? */
+                return 0;
+            }
+            pageshift = 0;
+            while (pagesize > 1)
+            {
+                pageshift++;
+                pagesize >>= 1;
+            }
+
+            /* convert to kB */
+            pageshift -= 10;
+        }
+
+        mib[0] = CTL_VM;
+        mib[1] = VM_UVMEXP2;
+        if ( (sysctl (mib, ARRAY_SIZE (mib), &uvmexp, &lenu, NULL, 0) == 0) && (lenu == sizeof (uvmexp)) )
+        {
+            return  (uvmexp.free << pageshift);
+        }
+
+        return 0;
+    }
+#elif defined(__FreeBSD__)
+    int avphys_pages;
+    size_t oldlenp = sizeof (avphys_pages);
+    sysctlbyname("vm.stats.vm.v_free_count", &avphys_pages, &oldlenp, NULL, NULL);
+    return (avphys_pages / kooctet) * sysconf(_SC_PAGESIZE);
+
+#else
+    /* Solaris and others assumed*/
+    return (sysconf(_SC_AVPHYS_PAGES) / kooctet) * sysconf(_SC_PAGESIZE);
+#endif
 }
-/*--------------------------------------------------------------------------*/ 
+/*--------------------------------------------------------------------------*/
 int getmemorysize()
 {
-#define kooctet 1024
-#undef MEMOK
-
-
 #if defined(_MSC_VER)
-#define MEMOK 1
-  {
-    MEMORYSTATUS stat;
-    GlobalMemoryStatus (&stat);
-    return (int)(stat.dwTotalPhys/kooctet);
-  }
-#endif
+    {
+        MEMORYSTATUS stat;
+        GlobalMemoryStatus (&stat);
+        return (int)(stat.dwTotalPhys / kooctet);
+    }
+#elif defined(hpux)
+    {
+        struct pst_static pst;
+        pstat_getstatic(&pst, sizeof(pst), (size_t) 1, 0);
+        return (int)((pst.physical_memory) / kooctet);
+    }
+#elif defined(__APPLE__) || defined(__NetBSD__) || defined(__DragonFly__)
+    {
+        /* this works on *bsd and darwin */
+        size_t len;
+        int total;
+        int mib[2];
 
-#if defined(hpux)
-#define MEMOK 1
-  {
-    struct pst_static pst;
-    pstat_getstatic(&pst, sizeof(pst), (size_t) 1, 0);
-    return (int)((pst.physical_memory)/kooctet);
-  }
-#endif
+        mib[0] = CTL_HW;
+        mib[1] = HW_PHYSMEM;
+        len = sizeof (total);
 
-#if defined(__APPLE__) 
-#define MEMOK 1
-  {
-    size_t len;
-    int total;
-    int mib[2];
-
-    mib[0] = CTL_HW;
-    mib[1] = HW_PHYSMEM;
-    len = sizeof (total);
-    sysctl(mib, 2, &total, &len, NULL, 0);
-    return  total/1024;
-  }
-#endif
+        sysctl(mib, 2, &total, &len, NULL, 0);
+        return  total / 1024;
+    }
+#elif HAVE_GETSYSINFO && defined GSI_PHYSMEM
+    {
+        /* This works on Tru64 UNIX V4/5.  */
+        int physmem;
 
-#if HAVE_GETSYSINFO && defined GSI_PHYSMEM
-#define MEMOK 1
-   { /* This works on Tru64 UNIX V4/5.  */
-     int physmem;
-
-     if (getsysinfo (GSI_PHYSMEM, (caddr_t) &physmem, sizeof (physmem),
-                    NULL, NULL, NULL) == 1)
-       {
-        double kbytes = physmem;
-
-        if (0 <= kbytes)
-          return kbytes * 1024.0;
-       else
-         return 0;
-       }
-   }
-#endif
+        if (getsysinfo (GSI_PHYSMEM, (caddr_t) &physmem, sizeof (physmem),
+        NULL, NULL, NULL) == 1)
+        {
+            double kbytes = physmem;
 
-#ifndef  MEMOK
-  /* Linux ,Solaris and others */
-  return (sysconf(_SC_PHYS_PAGES)*sysconf(_SC_PAGESIZE))/kooctet;
+            if (0 <= kbytes)
+            {
+                return kbytes * 1024.0;
+            }
+            else
+            {
+                return 0;
+            }
+        }
+    }
+#else
+    /* Linux ,Solaris and others */
+    return (sysconf(_SC_PHYS_PAGES) / kooctet) * sysconf(_SC_PAGESIZE);
 #endif
 }
 /*--------------------------------------------------------------------------*/