get-rusage-as: Improve on NetBSD.
[pspp] / lib / get-rusage-as.c
index 3ca13660084b883f707d851d619f5f14313368d6..80eab6a81e5835de8a7e489991f0a2697ed2b172 100644 (file)
@@ -61,7 +61,8 @@
 
    NetBSD:
      a) setrlimit with RLIMIT_AS works.
-     b) No VMA iteration API exists.
+     b) The /proc/self/maps file contains a list of the virtual memory areas.
+     Both methods agree,
 
    OpenBSD:
      a) setrlimit exists, but RLIMIT_AS is not defined.
@@ -182,7 +183,7 @@ get_rusage_as_via_setrlimit (void)
   if (getrlimit (RLIMIT_AS, &orig_limit) < 0)
     {
       result = 0;
-      goto done;
+      goto done2;
     }
 
   if (orig_limit.rlim_max != RLIM_INFINITY
@@ -192,7 +193,7 @@ get_rusage_as_via_setrlimit (void)
        So bail out.  */
     {
       result = 0;
-      goto done;
+      goto done2;
     }
 
   {
@@ -223,7 +224,7 @@ get_rusage_as_via_setrlimit (void)
           {
             /* try_next could not be increased.  */
             result = low_bound;
-            goto done;
+            goto done1;
           }
 
         try_limit.rlim_max = orig_limit.rlim_max;
@@ -311,11 +312,12 @@ get_rusage_as_via_setrlimit (void)
     result = low_bound;
   }
 
+ done1:
   /* Restore the original rlim_cur value.  */
   if (setrlimit (RLIMIT_AS, &orig_limit) < 0)
     abort ();
 
- done:
+ done2:
 # if !HAVE_MAP_ANONYMOUS
   close (fd);
 # endif
@@ -327,7 +329,7 @@ get_rusage_as_via_setrlimit (void)
 
 /* Support for reading text files in the /proc file system.  */
 
-#if defined __linux__ || defined __FreeBSD__ /* || defined __CYGWIN__ */
+#if defined __linux__ || defined __FreeBSD__ || defined __NetBSD__ /* || defined __CYGWIN__ */
 
 /* Buffered read-only streams.
    We cannot use <stdio.h> here, because fopen() calls malloc(), and a malloc()
@@ -461,7 +463,7 @@ get_rusage_as_via_iterator (void)
   rof_close (&rof);
   return total;
 
-#elif defined __FreeBSD__
+#elif defined __FreeBSD__ || defined __NetBSD__
 
   struct rofile rof;
   int c;
@@ -653,7 +655,11 @@ get_rusage_as_via_iterator (void)
   while (VirtualQuery ((void*)address, &info, sizeof(info)) == sizeof(info))
     {
       if (info.State != MEM_FREE)
-        total += info.RegionSize;
+        /* Ignore areas where info.Protect has the undocumented value 0.
+           This is needed, so that on Cygwin, areas used by malloc() are
+           distinguished from areas reserved for future malloc().  */
+        if (info.Protect != 0)
+          total += info.RegionSize;
       address = (unsigned long)info.BaseAddress + info.RegionSize;
     }
   return total;