blob: 3dc700c81469102bf4a3cd9683ff1a6c70744eba [file] [log] [blame]
#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"