]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Use munlock before madvise to make sure that we effectively "uncommit" the page
authorVicent Segui Pascual <segui@google.com>
Mon, 18 Jan 2016 10:05:31 +0000 (02:05 -0800)
committerVicent Segui Pascual <segui@google.com>
Mon, 18 Jan 2016 10:05:31 +0000 (02:05 -0800)
README.google
nptl/Makefile
nptl/allocatestack.c
nptl/tst-basic8.c [new file with mode: 0644]

index 3b478f5da7ae1cc060a85befc9edfa36fa96bcfe..0b0792ec93c992c4d3cd4f9bd9d53ba07d03bf58 100644 (file)
@@ -544,3 +544,8 @@ iconv/gconv_trans.c
 resolv/res_send.c
   For b/25900273, adjust allocations to avoid segfault.
   (bmoses, google-local)
+
+nptl/allocatestack.c
+nptl/Makefile
+nptl/tst-basic8.c
+  For b/24399992 unlock guard pages to avoid wasting memory.
index f669d1a3cce9ff3c6d616048a5240dd3da15d4bb..3176e54dbae66c54aed643263c8db4de3fae0013 100644 (file)
@@ -234,7 +234,7 @@ tests = tst-typesizes \
        tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \
        tst-align tst-align2 tst-align3 \
        tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \
-       tst-basic7 \
+       tst-basic7 tst-basic8 \
        tst-kill1 tst-kill2 tst-kill3 tst-kill4 tst-kill5 tst-kill6 \
        tst-raise1 \
        tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 tst-join6 \
index e8dfbbb8deb15c864b994aa2e4e6c531048ba5a8..c6264aa4dd601da9748975d6df74c3857d3274a2 100644 (file)
@@ -656,6 +656,12 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
 
              return errno;
            }
+         /* The call to madvise(...MADV_DONTNEED) below will fail if pages
+            are locked. Unlock the guard memory to make sure the
+            madvise function succeeds (memory can be locked if
+            process called mlockall(MCL_FUTURE) at some point in the
+            past).*/
+         munlock (guard, guardsize);
          /* We've marked this guard region unwritable, but it's
             possible it already became resident, the most common case
             being transparent hugepages; if stack + guard (+ adjacent
diff --git a/nptl/tst-basic8.c b/nptl/tst-basic8.c
new file mode 100644 (file)
index 0000000..3dc700c
--- /dev/null
@@ -0,0 +1,91 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <pthread.h>
+/* Test that stack guards do not become resident, even with
+mlockall(MCL_FUTURE) by verifying that spawning NTHREADS with these
+stack/guard sizes use a reasonable (<100kb/thread) amount of RSS. */
+#define NTHREADS 100
+#define STACKSIZE (64 * 1024)
+#define GUARDSIZE (1024 * 1024)
+
+pthread_barrier_t barrier;
+
+
+static void fail (const char *msg)
+{
+  puts (msg);
+  exit (1);
+}
+
+static size_t get_rss_bytes (void)
+{
+  struct rusage usage;
+  if (getrusage(RUSAGE_SELF, &usage) != 0)
+    fail ("getrusage failed");
+
+  return usage.ru_maxrss * 1024;
+}
+
+static void *
+child (void *arg)
+{
+  int ret = pthread_barrier_wait(&barrier);
+  if (ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD)
+    fail("pthread_barrier_wait failed");
+  while (1)
+    {
+      sleep (10);
+    }
+  return NULL;
+}
+
+static int
+do_test (void)
+{
+  int err;
+  int i;
+  size_t bytes;
+  char buffer[2048];
+  size_t overhead, count;
+  int fd;
+  mlockall(MCL_CURRENT);
+  overhead = get_rss_bytes();
+  mlockall(MCL_CURRENT|MCL_FUTURE);
+  if (pthread_barrier_init(&barrier, NULL, NTHREADS + 1) != 0)
+    fail("pthread_barrier_init failed");
+  for (i = 0; i < NTHREADS; ++i)
+    {
+      pthread_attr_t attr;
+      pthread_t tid;
+      pthread_attr_init (&attr);
+      pthread_attr_setstacksize (&attr, STACKSIZE + GUARDSIZE);
+      pthread_attr_setguardsize (&attr, GUARDSIZE);
+      err = pthread_create (&tid, &attr, child, NULL);
+      if (err != 0)
+        fail("pthread_create failed");
+    }
+  err = pthread_barrier_wait(&barrier);
+  if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+    fail("pthread_barrier_wait failed");
+  bytes = get_rss_bytes ();
+  fd = open("/proc/self/smaps", O_RDONLY);
+  while(0 < (count = read(fd, buffer, 2048)))
+    write(1, buffer, count);
+  close(fd);
+  printf ("%d threads with %d stacks and %d guards using %zu per thread\n",
+          NTHREADS, STACKSIZE, GUARDSIZE, (bytes-overhead)/NTHREADS);
+  if ((bytes-overhead) > (NTHREADS * GUARDSIZE))
+    fail ("memory usage too high");
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"