diff options
author | Vicent Segui Pascual <segui@google.com> | 2016-01-18 02:05:31 -0800 |
---|---|---|
committer | Vicent Segui Pascual <segui@google.com> | 2016-01-18 02:05:31 -0800 |
commit | bab244a0066749511f2c76efa2a499b39b6181ef (patch) | |
tree | 3afc484f1f03daf9f96be0528c6defa2602ca7ed | |
parent | fa9a6cbaeaf0ddd6ff6dcbbc09a4dda802cdb15e (diff) | |
download | glibc-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.google | 5 | ||||
-rw-r--r-- | nptl/Makefile | 2 | ||||
-rw-r--r-- | nptl/allocatestack.c | 6 | ||||
-rw-r--r-- | nptl/tst-basic8.c | 91 |
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" |