summaryrefslogtreecommitdiffstats
path: root/lib/libkse/test
diff options
context:
space:
mode:
authorjasone <jasone@FreeBSD.org>2001-07-20 04:23:11 +0000
committerjasone <jasone@FreeBSD.org>2001-07-20 04:23:11 +0000
commita9a7a5e9d63f8a71f1d3dfe0e1ed1a28ab589215 (patch)
tree656e85a738aa3a12d8926a342cea87c2eae35e1d /lib/libkse/test
parentf7019990adf13ef4a3ccbd680c5c5ba8292d5f7f (diff)
downloadFreeBSD-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/Makefile4
-rw-r--r--lib/libkse/test/guard_b.c150
-rw-r--r--lib/libkse/test/guard_b.exp3
-rw-r--r--lib/libkse/test/guard_s.pl69
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*)&top;
+ }
+
+ /*
+ * 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";
+ }
+ }
+ }
+}
OpenPOWER on IntegriCloud