aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Segui Pascual <segui@google.com>2016-01-18 02:05:31 -0800
committerVicent Segui Pascual <segui@google.com>2016-01-18 02:05:31 -0800
commitbab244a0066749511f2c76efa2a499b39b6181ef (patch)
tree3afc484f1f03daf9f96be0528c6defa2602ca7ed
parentfa9a6cbaeaf0ddd6ff6dcbbc09a4dda802cdb15e (diff)
downloadglibc-bab244a0066749511f2c76efa2a499b39b6181ef.zip
glibc-bab244a0066749511f2c76efa2a499b39b6181ef.tar.gz
glibc-bab244a0066749511f2c76efa2a499b39b6181ef.tar.bz2
Use munlock before madvise to make sure that we effectively "uncommit" the page
-rw-r--r--README.google5
-rw-r--r--nptl/Makefile2
-rw-r--r--nptl/allocatestack.c6
-rw-r--r--nptl/tst-basic8.c91
4 files changed, 103 insertions, 1 deletions
diff --git a/README.google b/README.google
index 3b478f5..0b0792e 100644
--- a/README.google
+++ b/README.google
@@ -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.
diff --git a/nptl/Makefile b/nptl/Makefile
index f669d1a..3176e54 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -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 \
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
index e8dfbbb..c6264aa 100644
--- a/nptl/allocatestack.c
+++ b/nptl/allocatestack.c
@@ -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
index 0000000..3dc700c
--- /dev/null
+++ b/nptl/tst-basic8.c
@@ -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"