diff options
author | jasone <jasone@FreeBSD.org> | 2001-07-20 04:23:11 +0000 |
---|---|---|
committer | jasone <jasone@FreeBSD.org> | 2001-07-20 04:23:11 +0000 |
commit | a9a7a5e9d63f8a71f1d3dfe0e1ed1a28ab589215 (patch) | |
tree | 656e85a738aa3a12d8926a342cea87c2eae35e1d /lib/libkse/test | |
parent | f7019990adf13ef4a3ccbd680c5c5ba8292d5f7f (diff) | |
download | FreeBSD-src-a9a7a5e9d63f8a71f1d3dfe0e1ed1a28ab589215.zip FreeBSD-src-a9a7a5e9d63f8a71f1d3dfe0e1ed1a28ab589215.tar.gz |
Implement pthread_attr_[gs]etguardsize(). Non-default-size stacks used to
be malloc()ed, but they are now allocated using mmap(), just as the
default-size stacks are. A separate cache of stacks is kept for
non-default-size stacks.
Collaboration with: deischen
Diffstat (limited to 'lib/libkse/test')
-rw-r--r-- | lib/libkse/test/Makefile | 4 | ||||
-rw-r--r-- | lib/libkse/test/guard_b.c | 150 | ||||
-rw-r--r-- | lib/libkse/test/guard_b.exp | 3 | ||||
-rw-r--r-- | lib/libkse/test/guard_s.pl | 69 |
4 files changed, 224 insertions, 2 deletions
diff --git a/lib/libkse/test/Makefile b/lib/libkse/test/Makefile index ef0090e..0eb530c 100644 --- a/lib/libkse/test/Makefile +++ b/lib/libkse/test/Makefile @@ -12,10 +12,10 @@ CTESTS := hello_d.c hello_s.c join_leak_d.c mutex_d.c sem_d.c sigsuspend_d.c \ # C programs that are used internally by the tests. The build system merely # compiles these. -BTESTS := hello_b.c +BTESTS := guard_b.c hello_b.c # Tests written in perl. -PTESTS := propagate_s.pl +PTESTS := guard_s.pl propagate_s.pl # Munge the file lists to their final executable names (strip the .c). CTESTS := $(CTESTS:R) diff --git a/lib/libkse/test/guard_b.c b/lib/libkse/test/guard_b.c new file mode 100644 index 0000000..e2f1a3a --- /dev/null +++ b/lib/libkse/test/guard_b.c @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2001 Jason Evans <jasone@freebsd.org>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice(s), this list of conditions and the following disclaimer + * unmodified other than the allowable addition of one or more + * copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + * + * Test thread stack guard functionality. + */ + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <limits.h> +#include <pthread.h> + +#define FRAME_SIZE 1024 +#define FRAME_OVERHEAD 40 + +struct args +{ + void *top; /* Top of thread's initial stack frame. */ + int cur; /* Recursion depth. */ + int max; /* Maximum recursion depth. */ +}; + +void * +recurse(void *args) +{ + int top; + struct args *parms = (struct args *)args; + char filler[FRAME_SIZE - FRAME_OVERHEAD]; + + /* Touch the memory in this stack frame. */ + top = 0xa5; + memset(filler, 0xa5, sizeof(filler)); + + if (parms->top == NULL) { + /* Initial stack frame. */ + parms->top = (void*)⊤ + } + + /* + * Make sure frame size is what we expect. Getting this right involves + * hand tweaking, so just print a warning rather than aborting. + */ + if (parms->top - (void *)&top != FRAME_SIZE * parms->cur) { + fprintf(stderr, "Stack size (%d) != expected (%d), frame %d\n", + parms->top - (void *)&top, FRAME_SIZE * parms->cur, + parms->cur); + } + + parms->cur++; + if (parms->cur < parms->max) + recurse(args); + + return NULL; +} + + +int +main(int argc, char **argv) +{ + size_t def_stacksize, def_guardsize; + size_t stacksize, guardsize; + pthread_t thread; + pthread_attr_t attr; + struct args args; + + if (argc != 3) { + fprintf(stderr, "Usage: guard_b <stacksize> <guardsize>\n"); + exit(1); + } + fprintf(stderr, "Test begin\n"); + + stacksize = strtoul(argv[1], NULL, 10); + guardsize = strtoul(argv[2], NULL, 10); + + assert(pthread_attr_init(&attr) == 0); + /* + * Exercise the attribute APIs more thoroughly than is strictly + * necessary for the meat of this test program. + */ + assert(pthread_attr_getstacksize(&attr, &def_stacksize) == 0); + assert(pthread_attr_getguardsize(&attr, &def_guardsize) == 0); + if (def_stacksize != stacksize) { + assert(pthread_attr_setstacksize(&attr, stacksize) == 0); + assert(pthread_attr_getstacksize(&attr, &def_stacksize) == 0); + assert(def_stacksize == stacksize); + } + if (def_guardsize != guardsize) { + assert(pthread_attr_setguardsize(&attr, guardsize) == 0); + assert(pthread_attr_getguardsize(&attr, &def_guardsize) == 0); + assert(def_guardsize >= guardsize); + } + + /* + * Create a thread that will come just short of overflowing the thread + * stack. We need to leave a bit of breathing room in case the thread + * is context switched, and we also have to take care not to call any + * functions in the deepest stack frame. + */ + args.top = NULL; + args.cur = 0; + args.max = (stacksize / FRAME_SIZE) - 1; + fprintf(stderr, "No overflow:\n"); + assert(pthread_create(&thread, &attr, recurse, &args) == 0); + assert(pthread_join(thread, NULL) == 0); + + /* + * Create a thread that will barely of overflow the thread stack. This + * should cause a segfault. + */ + args.top = NULL; + args.cur = 0; + args.max = (stacksize / FRAME_SIZE) + 1; + fprintf(stderr, "Overflow:\n"); + assert(pthread_create(&thread, &attr, recurse, &args) == 0); + assert(pthread_join(thread, NULL) == 0); + + /* Not reached. */ + fprintf(stderr, "Unexpected success\n"); + abort(); + + return 0; +} diff --git a/lib/libkse/test/guard_b.exp b/lib/libkse/test/guard_b.exp new file mode 100644 index 0000000..8e5b9e4 --- /dev/null +++ b/lib/libkse/test/guard_b.exp @@ -0,0 +1,3 @@ +Test begin +No overflow: +Overflow: diff --git a/lib/libkse/test/guard_s.pl b/lib/libkse/test/guard_s.pl new file mode 100644 index 0000000..7802ff3 --- /dev/null +++ b/lib/libkse/test/guard_s.pl @@ -0,0 +1,69 @@ +#!/usr/bin/perl -w +# +# Copyright (C) 2001 Jason Evans <jasone@freebsd.org>. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice(s), this list of conditions and the following disclaimer +# unmodified other than the allowable addition of one or more +# copyright notices. +# 2. Redistributions in binary form must reproduce the above copyright +# notice(s), this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# $FreeBSD$ +# +# Test thread stack guard functionality. The C test program needs to be driven +# by this script because it segfaults when the stack guard is hit. +# + +print "1..30\n"; + +$i = 0; +# Iterates 10 times. +for ($stacksize = 65536; $stacksize < 131072; $stacksize += 7168) +{ + # Iterates 3 times (1024, 4096, 7168). + for ($guardsize = 1024; $guardsize < 8192; $guardsize += 3072) + { + $i++; + + print "stacksize: $stacksize, guardsize: $guardsize\n"; + + `./guard_b $stacksize $guardsize >guard_b.out 2>&1`; + + if (! -f "./guard_b.out") + { + print "not ok $i\n"; + } + else + { + `diff guard_b.exp guard_b.out >guard_b.diff 2>&1`; + if ($?) + { + # diff returns non-zero if there is a difference. + print "not ok $i\n"; + } + else + { + print "ok $i\n"; + } + } + } +} |