diff options
author | David Leonard <d@cvs.openbsd.org> | 1998-09-03 11:04:48 +0000 |
---|---|---|
committer | David Leonard <d@cvs.openbsd.org> | 1998-09-03 11:04:48 +0000 |
commit | 19238dc05c5b501a685537b1fcb0b54f9d8bdf5a (patch) | |
tree | eae5c85762af12da5994ab4524ee73f6d6ba678e /lib/libc_r | |
parent | 542ab5713f06e4f89b3d17d7a1458a4214fa1bb9 (diff) |
libpthread tests modified for uthreads
Diffstat (limited to 'lib/libc_r')
34 files changed, 2658 insertions, 0 deletions
diff --git a/lib/libc_r/TEST/Makefile b/lib/libc_r/TEST/Makefile new file mode 100644 index 00000000000..d03d1c4ec61 --- /dev/null +++ b/lib/libc_r/TEST/Makefile @@ -0,0 +1,47 @@ +# Generated automatically from Makefile.in by configure. +# === GNUmakefile ============================================================ +# Copyright (c) 1993 Chris Provenzano, proven@athena.mit.edu +# +# Description: This file is for creating the test programs for libpthread.a +# +# 1.00 93/08/03 proven +# -Initial cut for pthreads. +# + +LIBC_R?= /usr/lib/libc_r.a + +CFLAGS += -pthread +CFLAGS += -ggdb -Wall # -Werror +CFLAGS += -DSRCDIR='"${.CURDIR}"' +LDLIBS += -lm +DPADD += ${LIBC_R} + +# This list used to include test_select, but that test doesn't terminate. +TESTS = test_create test_pthread_join test_switch test_sleep test_readdir \ + test_fork test_execve test_preemption test_preemption_float \ + test_sock_1 test_sock_2 test_stdio_1 test_pthread_mutex \ + test_pthread_cond_timedwait test_netdb test_pw test_cwd + +# This list used to include p_bench_semaphore, but the semaphore support isn't +# defined for all targets (or used for any). +BENCHMARKS = p_bench_read p_bench_mutex p_bench_yield \ + p_bench_getpid p_bench_pthread_create + +CLEANFILES += ${TESTS} ${BENCHMARKS} + +all : tests # benchmarks + +tests : ${TESTS} + @for i in ${.ALLSRC} ; do \ + echo ; echo "*** $$i ***"; \ + if ${.OBJDIR}/$$i; then \ + echo "-- $$i passed"; \ + else \ + echo "-- $$i FAILED (exit code $$?)"; \ + exit 1; \ + fi; \ + done; exit 0 + +benchmarks: ${BENCHMARKS} + +.include <bsd.prog.mk> diff --git a/lib/libc_r/TEST/README b/lib/libc_r/TEST/README new file mode 100644 index 00000000000..bb4a3e7ce01 --- /dev/null +++ b/lib/libc_r/TEST/README @@ -0,0 +1,26 @@ +This directory contains a few test and benchmark programs that I've +developed to help me test the consistancy of the libpthread.a. + +TEST +---------------------- +test_create Tests the pthread_create() routine. The stack addresses + should be very different (ie the upper values of the + address should be different) and the arg should be + 0xdeadbeaf. + +test_switch A nondeterministic test. It should show context switching, + by displaying different letters. + +test_sleep Timing this test should result in a time of about 20 seconds. + It should sleep for 10 seconds and then print ba 10 times + at the rate of about once a second. + +p_bench_* Benchmarks for various routines. + +------------------------------------------------------------------------------ +Copyright (c) 1994 Chris Provenzano. All rights reserved. +This product includes software developed by the Univeristy of California, +Berkeley and its contributors. + +For further licencing and distribution restrictions see the file COPYRIGHT +included in the parent directory. diff --git a/lib/libc_r/TEST/bench_fcntl.c b/lib/libc_r/TEST/bench_fcntl.c new file mode 100644 index 00000000000..b9efdb25031 --- /dev/null +++ b/lib/libc_r/TEST/bench_fcntl.c @@ -0,0 +1,81 @@ +/* ==== bench_read.c ============================================================ + * Copyright (c) 1993 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Benchmark reads of /dev/null. Gives a good aprox. of + * syscall times. + * + * 1.00 93/08/01 proven + * -Started coding this file. + */ + +#include <sys/types.h> +#include <sys/time.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include "test.h" + +/* ========================================================================== + * usage(); + */ +void usage(void) +{ + printf("getopt [-d?] [-c count]\n"); + errno = 0; +} + +main(int argc, char **argv) +{ + struct timeval starttime, endtime; + int count = 1000000; + int debug = 0; + int flags; + int fd; + int i; + + char word[8192]; + + /* Getopt variables. */ + extern int optind, opterr; + extern char *optarg; + + while ((word[0] = getopt(argc, argv, "c:d?")) != (char)EOF) { + switch (word[0]) { + case 'd': + debug++; + break; + case 'c': + count = atoi(optarg); + break; + case '?': + usage(); + return(OK); + default: + usage(); + return(NOTOK); + } + } + + if ((fd = open("/dev/zero", O_RDONLY)) < OK) { + printf("Error: open\n"); + exit(0); + } + + if (gettimeofday(&starttime, NULL)) { + printf("Error: gettimeofday\n"); + exit(0); + } + for (i = 0; i < count; i++) { + if ((flags = fcntl(0, F_GETFL)) < 0) { + perror("fcntl 1st GETFL"); + } + } + if (gettimeofday(&endtime, NULL)) { + printf("Error: gettimeofday\n"); + exit(0); + } + + printf("%d fcntls of /dev/null took %d usecs.\n", count, + (endtime.tv_sec - starttime.tv_sec) * 1000000 + + (endtime.tv_usec - starttime.tv_usec)); +} diff --git a/lib/libc_r/TEST/bench_pipe.c b/lib/libc_r/TEST/bench_pipe.c new file mode 100644 index 00000000000..298152f4c53 --- /dev/null +++ b/lib/libc_r/TEST/bench_pipe.c @@ -0,0 +1,113 @@ +/* ==== bench_pipe.c ============================================================ + * Copyright (c) 1993 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Benchmark reads of /dev/null. Gives a good aprox. of + * syscall times. + * + * 1.00 93/08/01 proven + * -Started coding this file. + */ + +#include <sys/types.h> +#include <sys/time.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include "test.h" + +/* ========================================================================== + * usage(); + */ +void usage(void) +{ + printf("bench_pipe [-d?] [-c count]\n"); + errno = 0; +} + +main(int argc, char **argv) +{ + struct timeval starttime, endtime; + char buf[1]; + int count = 1000; + int debug = 0; + int fd0[2]; + int fd1[2]; + int i; + + char word[256]; + + /* Getopt variables. */ + extern int optind, opterr; + extern char *optarg; + + while ((word[0] = getopt(argc, argv, "c:d?")) != (char)EOF) { + switch (word[0]) { + case 'd': + debug++; + break; + case 'c': + count = atoi(optarg); + break; + case '?': + usage(); + return(OK); + default: + usage(); + return(NOTOK); + } + } + + if ((pipe(fd0) < OK) || (pipe(fd1) < OK)) { + printf("Error: pipe\n"); + exit(0); + } + + switch (fork()) { + case NOTOK: + printf("Error: fork\n"); + exit(0); + case OK: /* Child */ + for (i = 0; i < count; i++) { + if (read(fd1[0], buf, 1) < OK) { + printf("Error: child read\n"); + exit(0); + } + if (write(fd0[1], buf, 1) < OK) { + printf("Error: child write\n"); + exit(0); + } + } + exit(0); + break; + default: + break; + } + + if (gettimeofday(&starttime, NULL)) { + printf("Error: gettimeofday\n"); + exit(0); + } + count --; + if (write(fd1[1], buf, 1) < OK) { + perror("first parent write"); + exit(0); + } + for (i = 0; i < count; i++) { + if (read(fd0[0], buf, 1) < OK) { + printf("Error: parent read\n"); + exit(0); + } + if (write(fd1[1], buf, 1) < OK) { + printf("Error: parent write\n"); + exit(0); + } + } + if (gettimeofday(&endtime, NULL)) { + printf("Error: gettimeofday\n"); + exit(0); + } + + printf("%d ping pong tests took %d usecs.\n", count, + (endtime.tv_sec - starttime.tv_sec) * 1000000 + + (endtime.tv_usec - starttime.tv_usec)); +} diff --git a/lib/libc_r/TEST/bench_read.c b/lib/libc_r/TEST/bench_read.c new file mode 100644 index 00000000000..0fd2938d05f --- /dev/null +++ b/lib/libc_r/TEST/bench_read.c @@ -0,0 +1,86 @@ +/* ==== bench_read.c ============================================================ + * Copyright (c) 1993 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Benchmark reads of /dev/null. Gives a good aprox. of + * syscall times. + * + * 1.00 93/08/01 proven + * -Started coding this file. + */ + +#include <sys/types.h> +#include <sys/time.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include "test.h" +/* ========================================================================== + * usage(); + */ +void usage(void) +{ + printf("getopt [-d?] [-c count] [-s size]\n"); + errno = 0; +} + +main(int argc, char **argv) +{ + struct timeval starttime, endtime; + int count = 1000000; + int debug = 0; + int size = 1; + int fd; + int i; + + char word[8192]; + + /* Getopt variables. */ + extern int optind, opterr; + extern char *optarg; + + while ((word[0] = getopt(argc, argv, "s:c:d?")) != (char)EOF) { + switch (word[0]) { + case 'd': + debug++; + break; + case 'c': + count = atoi(optarg); + break; + case 's': + if ((size = atoi(optarg)) > 8192) { + size = 8192; + } + break; + case '?': + usage(); + return(OK); + default: + usage(); + return(NOTOK); + } + } + + if ((fd = open("/netbsd", O_RDONLY)) < OK) { + printf("Error: open\n"); + exit(0); + } + + if (gettimeofday(&starttime, NULL)) { + printf("Error: gettimeofday\n"); + exit(0); + } + for (i = 0; i < count; i++) { + if (read(fd, word, size) < OK) { + printf("Error: read\n"); + exit(0); + } + } + if (gettimeofday(&endtime, NULL)) { + printf("Error: gettimeofday\n"); + exit(0); + } + + printf("%d reads of /netbsd took %d usecs.\n", count, + (endtime.tv_sec - starttime.tv_sec) * 1000000 + + (endtime.tv_usec - starttime.tv_usec)); +} diff --git a/lib/libc_r/TEST/p_bench_getpid.c b/lib/libc_r/TEST/p_bench_getpid.c new file mode 100644 index 00000000000..45fbc2d4500 --- /dev/null +++ b/lib/libc_r/TEST/p_bench_getpid.c @@ -0,0 +1,75 @@ +/* ==== p_bench_getpid.c ================================================= + * Copyright (c) 1993 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Benchmark getpid() times + * + * 1.00 93/11/08 proven + * -Started coding this file. + */ + +#include <errno.h> +#include <pthread.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include "test.h" + +/* ========================================================================== + * usage(); + */ +void usage(void) +{ + printf("p_bench_getpid [-d?] [-c count]\n"); + errno = 0; +} + +int +main(int argc, char **argv) +{ + struct timeval starttime, endtime; + pid_t process_id; + int count = 1000000; + int debug = 0; + int i; + + char word[256]; + + /* Getopt variables. */ + extern int optind, opterr; + extern char *optarg; + + while ((word[0] = getopt(argc, argv, "c:d?")) != (char)EOF) { + switch (word[0]) { + case 'd': + debug++; + break; + case 'c': + count = atoi(optarg); + break; + case '?': + usage(); + return(OK); + default: + usage(); + return(NOTOK); + } + } + + if (gettimeofday(&starttime, NULL)) { + perror ("gettimeofday"); + return 1; + } + for (i = 0; i < count; i++) { + process_id = getpid(); + } + if (gettimeofday(&endtime, NULL)) { + perror ("gettimeofday"); + return 1; + } + + printf("%d getpid calls took %ld usecs.\n", count, + (endtime.tv_sec - starttime.tv_sec) * 1000000 + + (endtime.tv_usec - starttime.tv_usec)); + + return 0; +} diff --git a/lib/libc_r/TEST/p_bench_mutex.c b/lib/libc_r/TEST/p_bench_mutex.c new file mode 100644 index 00000000000..1639a8d144e --- /dev/null +++ b/lib/libc_r/TEST/p_bench_mutex.c @@ -0,0 +1,78 @@ +/* ==== p_bench_mutex.c ================================================= + * Copyright (c) 1993 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Benchmark mutex lock and unlock times + * + * 1.00 93/11/08 proven + * -Started coding this file. + */ + +#include <errno.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "test.h" + +/* ========================================================================== + * usage(); + */ +void usage(void) +{ + printf("getopt [-d?] [-c count]\n"); + errno = 0; +} + +int +main(int argc, char **argv) +{ + struct timeval starttime, endtime; + pthread_mutex_t lock; + int count = 1000000; + int debug = 0; + int i; + + char word[256]; + + /* Getopt variables. */ + extern int optind, opterr; + extern char *optarg; + + while ((word[0] = getopt(argc, argv, "c:d?")) != (char)EOF) { + switch (word[0]) { + case 'd': + debug++; + break; + case 'c': + count = atoi(optarg); + break; + case '?': + usage(); + return(OK); + default: + usage(); + return(NOTOK); + } + } + + pthread_mutex_init(&lock, NULL); + if (gettimeofday(&starttime, NULL)) { + perror ("gettimeofday"); + return 1; + } + for (i = 0; i < count; i++) { + pthread_mutex_lock(&lock); + pthread_mutex_unlock(&lock); + } + if (gettimeofday(&endtime, NULL)) { + perror ("gettimeofday"); + return 1; + } + + printf("%d mutex locks/unlocks no contention took %ld usecs.\n", count, + (endtime.tv_sec - starttime.tv_sec) * 1000000 + + (endtime.tv_usec - starttime.tv_usec)); + + return 0; +} diff --git a/lib/libc_r/TEST/p_bench_pthread_create.c b/lib/libc_r/TEST/p_bench_pthread_create.c new file mode 100644 index 00000000000..8bf55a71e72 --- /dev/null +++ b/lib/libc_r/TEST/p_bench_pthread_create.c @@ -0,0 +1,94 @@ +/* ==== p_bench_pthread_create.c ============================================= + * Copyright (c) 1993 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Benchmark thread creation time + * + * 1.00 93/11/08 proven + * -Started coding this file. + */ + + +#include <errno.h> +#include <pthread.h> +#include <stdio.h> +#include <getopt.h> +#include <stdlib.h> +#include <unistd.h> +#include "test.h" + +/* ========================================================================== + * new_thread(); + */ +void * new_thread(void * arg) +{ + pthread_yield(); +} + +/* ========================================================================== + * usage(); + */ +void usage(void) +{ + printf("p_bench_getpid [-d?] [-c count]\n"); + errno = 0; +} + +int +main(int argc, char **argv) +{ + struct timeval starttime, endtime; + pthread_t thread_id; + int count = 10000; + int debug = 0; + int i; + pthread_attr_t attr;; + + + char word[256]; + + /* Getopt variables. */ + extern int optind, opterr; + extern char *optarg; + + pthread_attr_init(&attr); + pthread_attr_setstackaddr(&attr, &word); + pthread_attr_setstacksize(&attr, sizeof word); + + while ((word[0] = getopt(argc, argv, "c:d?")) != (char)EOF) { + switch (word[0]) { + case 'd': + debug++; + break; + case 'c': + count = atoi(optarg); + break; + case '?': + usage(); + return(OK); + default: + usage(); + return(NOTOK); + } + } + + if (gettimeofday(&starttime, NULL)) { + perror ("gettimeofday"); + return 1; + } + for (i = 0; i < count; i++) { + if (pthread_create(&thread_id, &attr, new_thread, NULL)) { + printf("Bad pthread create routine\n"); + exit(1); + } + } + if (gettimeofday(&endtime, NULL)) { + perror ("gettimeofday"); + return 1; + } + + printf("%d getpid calls took %ld usecs.\n", count, + (endtime.tv_sec - starttime.tv_sec) * 1000000 + + (endtime.tv_usec - starttime.tv_usec)); + + return 0; +} diff --git a/lib/libc_r/TEST/p_bench_read.c b/lib/libc_r/TEST/p_bench_read.c new file mode 100644 index 00000000000..ab504a88fc5 --- /dev/null +++ b/lib/libc_r/TEST/p_bench_read.c @@ -0,0 +1,104 @@ +/* ==== p_bench_read.c ============================================================ + * Copyright (c) 1993 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Benchmark reads of /dev/null. Gives a good aprox. of + * syscall times. + * + * 1.00 93/08/01 proven + * -Started coding this file. + */ + +#include <pthread.h> +#include <sys/types.h> +#include <sys/time.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <stdlib.h> + +#include "test.h" + +/* ========================================================================== + * usage(); + */ +void usage(void) +{ + printf("p_bench_read [-d?] [-c count] [-s size] [-f file]\n"); + errno = 0; +} + +int +main(int argc, char **argv) +{ + struct timeval starttime, endtime; + char *infile = "/dev/null"; + int count = 1000000; + int debug = 0; + int size = 1; + int fd; + int i; + + char word[16384], *word_ptr; + + /* Getopt variables. */ + extern int optind, opterr; + extern char *optarg; + + + while ((word[0] = getopt(argc, argv, "c:df:s:?")) != (char)EOF) { + switch (word[0]) { + case 'c': + count = atoi(optarg); + break; + case 'd': + debug++; + break; + case 'f': + infile = optarg; + break; + case 's': + if ((size = atoi(optarg)) > 8192) { + size = 8192; + } + break; + case '?': + usage(); + return(OK); + default: + usage(); + return(NOTOK); + } + } + + /* Align buffer boundary to a page boundary */ + word_ptr = (char *)(((size_t) word + 4095) & ~4095); + + if ((fd = open(infile, O_RDONLY)) < OK) { + perror ("open"); + return 1; + } + + if (gettimeofday(&starttime, NULL)) { + perror ("gettimeofday"); + return 1; + } + + for (i = 0; i < count; i++) { + if (read(fd, word_ptr, size) < OK) { + printf("Error: read\n"); + exit(0); + } + } + + if (gettimeofday(&endtime, NULL)) { + perror ("gettimeofday"); + return 1; + } + + printf("%d reads of %s took %ld usecs.\n", count, infile, + (endtime.tv_sec - starttime.tv_sec) * 1000000 + + (endtime.tv_usec - starttime.tv_usec)); + + return 0; +} diff --git a/lib/libc_r/TEST/p_bench_semaphore.c b/lib/libc_r/TEST/p_bench_semaphore.c new file mode 100644 index 00000000000..b3bce340b95 --- /dev/null +++ b/lib/libc_r/TEST/p_bench_semaphore.c @@ -0,0 +1,82 @@ +/* ==== p_bench_semaphore.c ================================================= + * Copyright (c) 1993 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Benchmark semaphore Test and Set/ CLear times + * + * 1.00 93/11/08 proven + * -Started coding this file. + */ + +#include <errno.h> +#include <pthread.h> +#include <stdio.h> + +#define OK 0 +#define NOTOK -1 + +/* ========================================================================== + * usage(); + */ +void usage(void) +{ + printf("getopt [-d?] [-c count]\n"); + errno = 0; +} + +main(int argc, char **argv) +{ + struct timeval starttime, endtime; + semaphore lock = SEMAPHORE_CLEAR; + semaphore *lock_addr; + int count = 1000000; + int debug = 0; + int i; + + char word[256]; + + /* Getopt variables. */ + extern int optind, opterr; + extern char *optarg; + + pthread_init(); + + while ((word[0] = getopt(argc, argv, "c:d?")) != (char)EOF) { + switch (word[0]) { + case 'd': + debug++; + break; + case 'c': + count = atoi(optarg); + break; + case '?': + usage(); + return(OK); + default: + usage(); + return(NOTOK); + } + } + + lock_addr = &lock; + if (gettimeofday(&starttime, NULL)) { + perror ("gettimeofday"); + return 1; + } + for (i = 0; i < count; i++) { + if (SEMAPHORE_TEST_AND_SET(lock_addr)) { + printf("Semaphore already locked error\n"); + return 1; + } + SEMAPHORE_RESET(lock_addr); + } + if (gettimeofday(&endtime, NULL)) { + perror ("gettimeofday"); + return 1; + } + + printf("%d locks/unlocks of a semaphore took %d usecs.\n", count, + (endtime.tv_sec - starttime.tv_sec) * 1000000 + + (endtime.tv_usec - starttime.tv_usec)); + + return 0; +} diff --git a/lib/libc_r/TEST/p_bench_yield.c b/lib/libc_r/TEST/p_bench_yield.c new file mode 100644 index 00000000000..92e6509b9af --- /dev/null +++ b/lib/libc_r/TEST/p_bench_yield.c @@ -0,0 +1,126 @@ +/* ==== p_bench_mutex.c ================================================= + * Copyright (c) 1993-1995 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Benchmark mutex lock and unlock times + * + * 1.00 93/11/08 proven + * -Started coding this file. + */ + +#include <errno.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "test.h" + +/* ========================================================================== + * usage(); + */ +void usage(void) +{ + printf("p_bench_yield [-d?] \\\n"); + printf("\t[-c count] \\\n"); + printf("\t[-C thread count] \\\n"); + printf("\t[-O optimization level]\n"); + errno = 0; +} + +void *yield(void * arg) +{ + int i, * count; + + count = (int *)arg; + for (i = 0; i < *count; i++) { + pthread_yield(); + } + return(NULL); +} + +int +main(int argc, char **argv) +{ + struct timeval starttime, endtime; + pthread_mutex_t lock; + pthread_attr_t attr; + pthread_t thread_id; + int thread_count = 1; + int optimization = 0; + int count = 1000000; + int i, debug = 0; + + char word[256]; + + /* Getopt variables. */ + extern int optind, opterr; + extern char *optarg; + + while ((word[0] = getopt(argc, argv, "C:O:c:d?")) != (char)EOF) { + switch (word[0]) { + case 'C': + thread_count = atoi(optarg); + break; + case 'O': + optimization = atoi(optarg); + break; + case 'c': + count = atoi(optarg); + break; + case 'd': + debug++; + break; + case '?': + usage(); + return(OK); + default: + usage(); + return(NOTOK); + } + } + + pthread_attr_init(&attr); +#ifdef SCHED_FIFO /* XXX */ + if (optimization > 0) { + pthread_attr_setschedpolicy(&attr, SCHED_FIFO); + } +#endif +#if 0 /* XXX */ + if (optimization > 1) { + pthread_attr_setfloatstate(&attr, PTHREAD_NOFLOAT); + } +#endif + pthread_mutex_init(&lock, NULL); + if (gettimeofday(&starttime, NULL)) { + perror ("gettimeofday"); + return 1; + } + for (i = 1; i < thread_count; i++) { + if (pthread_create(&thread_id, &attr, yield, &count)) { + perror ("pthread_create"); + return 1; + } + if (pthread_detach(thread_id)) { + perror ("pthread_detach"); + return 1; + } + } + if (pthread_create(&thread_id, &attr, yield, &count)) { + perror ("pthread_create"); + return 1; + } + if (pthread_join(thread_id, NULL)) { + perror ("pthread_join"); + return 1; + } + if (gettimeofday(&endtime, NULL)) { + perror ("gettimeofday"); + return 1; + } + + printf("%d pthread_yields took %ld usecs.\n", count, + (endtime.tv_sec - starttime.tv_sec) * 1000000 + + (endtime.tv_usec - starttime.tv_usec)); + + return 0; +} diff --git a/lib/libc_r/TEST/test.h b/lib/libc_r/TEST/test.h new file mode 100644 index 00000000000..1dd97986caf --- /dev/null +++ b/lib/libc_r/TEST/test.h @@ -0,0 +1,29 @@ + +#ifndef _h_test_ +#define _h_test_ + +static __dead void __panic __P((char *filenm, int lineno)) + __attribute__((noreturn)); + +static void __panic(char *filenm, int lineno) { + extern int _thread_sys_write __P((int, char*, size_t)); + extern __dead void _thread_sys__exit __P((int)) + __attribute__((noreturn)); + extern size_t strlen __P((const char*)); + extern int sprintf __P((char *, const char *, ...)); + char buf[1024]; + char *panicstr = "\npanic at "; + + _thread_sys_write(2, panicstr, sizeof panicstr - 1); + sprintf(buf, "%s:%d\n", filenm, lineno); + _thread_sys_write(2, buf, strlen(buf)); + _thread_sys__exit(1); + __panic(NULL, 0); +} + +#define PANIC() __panic(__FILE__, __LINE__) + +#define OK (0) +#define NOTOK (-1) + +#endif _h_test_ diff --git a/lib/libc_r/TEST/test_create.c b/lib/libc_r/TEST/test_create.c new file mode 100644 index 00000000000..e984fe110fe --- /dev/null +++ b/lib/libc_r/TEST/test_create.c @@ -0,0 +1,38 @@ +/* ==== test_create.c ============================================================ + * Copyright (c) 1993 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Test pthread_create() and pthread_exit() calls. + * + * 1.00 93/08/03 proven + * -Started coding this file. + */ + +#include <pthread.h> +#include <stdio.h> +#include "test.h" + +void* new_thread(void* arg) +{ + int i; + + printf("New thread was passed arg address %p\n", arg); + printf("New thread stack at %p\n", &i); + return(NULL); + PANIC(); +} + +int +main() +{ + pthread_t thread; + int i; + + printf("Original thread stack at %p\n", &i); + if (pthread_create(&thread, NULL, new_thread, (void *)0xdeadbeef)) { + printf("Error: creating new thread\n"); + } + pthread_exit(NULL); + PANIC(); + return(1); + PANIC(); +} diff --git a/lib/libc_r/TEST/test_cwd.c b/lib/libc_r/TEST/test_cwd.c new file mode 100644 index 00000000000..5bb6401d699 --- /dev/null +++ b/lib/libc_r/TEST/test_cwd.c @@ -0,0 +1,13 @@ +#include <stdio.h> +#include <sys/param.h> +#include <unistd.h> + +int +main(int argc, char **argv) +{ + char wd[MAXPATHLEN], *getcwd(), *getwd(); + + printf("getcwd => %s\n", getcwd(wd, MAXPATHLEN)); + printf("getwd => %s\n", getwd(wd)); + exit(0); +} diff --git a/lib/libc_r/TEST/test_execve.c b/lib/libc_r/TEST/test_execve.c new file mode 100644 index 00000000000..409b37bfc1b --- /dev/null +++ b/lib/libc_r/TEST/test_execve.c @@ -0,0 +1,55 @@ +/* ==== test_execve.c ============================================================ + * Copyright (c) 1994 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Test execve() and dup2() calls. + * + * 1.00 94/04/29 proven + * -Started coding this file. + */ + +#include <pthread.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <stdio.h> +#include <err.h> +#include "test.h" + +extern char **environ; +char *argv[] = { + "/bin/echo", + "This message should be displayed after the execve system call", + NULL +}; + +char * should_succeed = "This line should be displayed\n"; +char * should_fail = "Error: This line should NOT be displayed\n"; + +int +main() +{ + int fd; + + printf("This is the first message\n"); + if (isatty(1)) { + char *ttynm; + + ttynm = ttyname(1); + printf("tty is %s\n", ttynm); + if ((fd = open(ttynm, O_RDWR)) < OK) + err(1, "%s", ttynm); + } else + errx(1, "stdout not a tty"); + + printf("This output is necessary to set the stdout fd to NONBLOCKING\n"); + + /* do a dup2 */ + dup2(fd, 1); + write(1, should_succeed, (size_t)strlen(should_succeed)); + _thread_sys_write(1, should_fail, strlen(should_fail)); + + if (execve(argv[0], argv, environ) < OK) + err(1, "execve"); + + PANIC(); +} diff --git a/lib/libc_r/TEST/test_fcntl.c b/lib/libc_r/TEST/test_fcntl.c new file mode 100644 index 00000000000..60bc77ce464 --- /dev/null +++ b/lib/libc_r/TEST/test_fcntl.c @@ -0,0 +1,32 @@ +#include <stdio.h> +#include <fcntl.h> + +main() +{ + int flags, child; + + if ((flags = fcntl(0, F_GETFL)) < 0) { + perror("fcntl 1st GETFL"); + } + printf ("flags = %x\n", flags); + + switch(child = fork()) { + case -1: + printf("error during fork\n"); + break; + case 0: /* child */ + execlp("test_create", "test_create", NULL); + break; + default: /* parent */ + wait(NULL); + break; + } + + while(1){ + if ((flags = fcntl(0, F_GETFL)) < 0) { + perror("fcntl parent GETFL"); + } + printf ("parent %d flags = %x\n", child, flags); + sleep(1); + } +} diff --git a/lib/libc_r/TEST/test_fork.c b/lib/libc_r/TEST/test_fork.c new file mode 100644 index 00000000000..29309ba7c37 --- /dev/null +++ b/lib/libc_r/TEST/test_fork.c @@ -0,0 +1,43 @@ +/* ==== test_fork.c ============================================================ + * Copyright (c) 1994 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Test fork() and dup2() calls. + * + * 1.00 94/04/29 proven + * -Started coding this file. + */ + +#include <pthread.h> +#include <stdio.h> +#include <fcntl.h> +#include <sys/types.h> +#include <unistd.h> +#include "test.h" + +int +main() +{ + int flags; + pid_t pid; + extern int _thread_sys_fcntl __P((int, int, ...)); + + if (((flags = _thread_sys_fcntl(1, F_GETFL, NULL)) >= OK) && + (flags & (O_NONBLOCK | O_NDELAY))) { + _thread_sys_fcntl(1, F_SETFL, flags & ~(O_NONBLOCK | O_NDELAY)); + } + printf("parent process %d\n", getpid()); + + switch(pid = fork()) { + case OK: + exit(OK); + case NOTOK: + printf("fork() FAILED\n"); + exit(2); + default: + printf("child process %d\n", pid); + break; + } + + printf("test_fork PASSED\n"); + pthread_exit(NULL); +} diff --git a/lib/libc_r/TEST/test_netdb.c b/lib/libc_r/TEST/test_netdb.c new file mode 100644 index 00000000000..3c075231461 --- /dev/null +++ b/lib/libc_r/TEST/test_netdb.c @@ -0,0 +1,118 @@ +/* ==== test_netdb.c ========================================================= + * Copyright (c) 1995 by Greg Hudson, ghudson@.mit.edu + * + * Description : Test netdb calls. + * + * 1.00 95/01/05 ghudson + * -Started coding this file. + */ + +#include <pthread.h> +#include <string.h> +#include <stdio.h> +#include <netdb.h> +#include <errno.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <unistd.h> +#include "test.h" + +struct servent * getservbyname_r __P((const char *, const char *, struct servent *, char *, int)); +struct hostent * gethostbyname_r __P((const char *, struct hostent *, char *, int, int *)); + +int debug = 0; + +static int test_serv() +{ + struct servent *serv; + char answer[1024]; + + if ((serv = getservbyname("telnet", "tcp")) != NULL) + printf("getservbyname -> port %d\n", ntohs(serv->s_port)); + else + printf("getservbyname -> NULL (bad)\n"); + + if ((serv = getservbyname_r("telnet", "tcp", serv, answer, 1024))!=NULL) + printf("getservbyname_r -> port %d\n", ntohs(serv->s_port)); + else + printf("getservbyname_r -> NULL (bad)\n"); + return(OK); +} + +static int test_host() +{ + struct hostent *host; + struct in_addr addr; + char answer[1024]; + int error; + + if ((host = gethostbyname("maze.mit.edu")) != NULL) { + memcpy(&addr, host->h_addr, sizeof(addr)); + printf("gethostbyname -> %s\n", inet_ntoa(addr)); + } else { + printf("gethostbyname -> NULL (bad)\n"); + host = (struct hostent *)answer; + } + + if ((host = gethostbyname_r("maze.mit.edu", host, answer, 1024, &error)) + != NULL) { + memcpy(&addr, host->h_addr, sizeof(addr)); + printf("gethostbyname_r -> %s\n", inet_ntoa(addr)); + } else { + printf("gethostbyname_r -> NULL (bad)\n"); + } + return(OK); +} + +static int test_localhost() +{ + struct hostent *host; + + if ((host = gethostbyname("127.0.0.1")) != NULL) { + return(OK); + } + return(NOTOK); +} + +/* ========================================================================== + * usage(); + */ +void usage(void) +{ + printf("test_netdb [-d?]\n"); + errno = 0; +} + +int +main(int argc, char **argv) +{ + + /* Getopt variables. */ + extern int optind, opterr; + extern char *optarg; + char ch; + + while ((ch = getopt(argc, argv, "d?")) != (char)EOF) { + switch (ch) { + case 'd': + debug++; + break; + case '?': + usage(); + return(OK); + default: + usage(); + return(NOTOK); + } + } + + printf("test_netdb START\n"); + + if (test_serv() || test_localhost() || test_host()) { + printf("test_netdb FAILED\n"); + exit(1); + } + + printf("test_netdb PASSED\n"); + exit(0); +} diff --git a/lib/libc_r/TEST/test_pause.c b/lib/libc_r/TEST/test_pause.c new file mode 100644 index 00000000000..46c5080e43e --- /dev/null +++ b/lib/libc_r/TEST/test_pause.c @@ -0,0 +1,19 @@ +#include <stdio.h> +#include <signal.h> + +foo(int sig) +{ + return; +} + +main() +{ + sigset_t all; + + signal (1, foo); + sigfillset(&all); + sigprocmask(SIG_BLOCK, &all, NULL); + printf("Begin pause\n"); + pause(); + printf("Done pause\n"); +} diff --git a/lib/libc_r/TEST/test_preemption.c b/lib/libc_r/TEST/test_preemption.c new file mode 100644 index 00000000000..1793f022292 --- /dev/null +++ b/lib/libc_r/TEST/test_preemption.c @@ -0,0 +1,38 @@ +/* ==== test_pthread_cond.c ========================================= + * Copyright (c) 1993 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Test pthread_cond(). Run this after test_create() + * + * 1.23 94/05/04 proven + * -Started coding this file. + */ + +#include <pthread.h> +#include <stdio.h> + +void* new_thread(void * new_buf) +{ + int i; + + for (i = 0; i < 10; i++) { + pthread_yield(); + } + printf("test_preemption PASSED\n"); + exit(0); +} + +int +main() +{ + pthread_t thread; + + printf("test_preemption START\n"); + + if (pthread_create(&thread, NULL, new_thread, NULL)) { + printf("pthread_create failed\n"); + exit(2); + } + + while(1); + exit(1); +} diff --git a/lib/libc_r/TEST/test_preemption_float.c b/lib/libc_r/TEST/test_preemption_float.c new file mode 100644 index 00000000000..621297001a5 --- /dev/null +++ b/lib/libc_r/TEST/test_preemption_float.c @@ -0,0 +1,96 @@ +/* Test to see if floating point state is being properly maintained + for each thread. Different threads doing floating point operations + simultaneously should not interfere with one another. This + includes operations that might change some FPU flags, such as + rounding modes, at least implicitly. */ + +#include <pthread.h> +#include <math.h> +#include <stdio.h> + +int limit = 2; +int float_passed = 0; +int float_failed = 1; + +void *log_loop (void *x) { + int i; + double d, d1, d2; + /* sleep (1); */ + for (i = 0; i < limit; i++) { + d = 42.0; + d = log (exp (d)); + d = (d + 39.0) / d; + if (i == 0) + d1 = d; + else { + d2 = d; + d = sin(d); + /* if (d2 != d1) { */ + if (memcmp (&d2, &d1, 8)) { + pthread_exit(&float_failed); + } + } + } + pthread_exit(&float_passed); +} + +void *trig_loop (void *x) { + int i; + double d, d1, d2; + /* sleep (1); */ + for (i = 0; i < limit; i++) { + d = 35.0; + d *= M_PI; + d /= M_LN2; + d = sin (d); + d = cos (1 / d); + if (i == 0) + d1 = d; + else { + d2 = d; + d = sin(d); + /* if (d2 != d1) { */ + if (memcmp (&d2, &d1, 8)) { + pthread_exit(&float_failed); + } + } + } + pthread_exit(&float_passed); +} + +#define N 10 +int main () { + pthread_t thread[2]; + pthread_attr_t attr; + int *x, *y; + + pthread_attr_init(&attr); + /* pthread_attr_setfloatstate(&attr, PTHREAD_NOFLOAT); */ + + while(limit < 100000) { + pthread_create (&thread[0], &attr, trig_loop, 0); + pthread_create (&thread[1], &attr, log_loop, 0); + pthread_join(thread[0], (void **) &x); + pthread_join(thread[1], (void **) &y); + if ((*x == float_failed) || (*y == float_failed)) { + limit *= 4; + break; + } + limit *= 4; + } + if ((*x == float_passed) && (*y == float_passed)) { + printf("test_preemption_float INDETERMINATE\n"); + return(0); + } + pthread_create (&thread[0], NULL, trig_loop, 0); + pthread_create (&thread[1], NULL, log_loop, 0); + pthread_join(thread[0], (void **) &x); + pthread_join(thread[1], (void **) &y); + + if ((*x == float_failed) || (*y == float_failed)) { + printf("test_preemption_float FAILED\n"); + return(1); + } + printf("test_preemption_float PASSED\n"); + return(0); +} diff --git a/lib/libc_r/TEST/test_pthread_cond_timedwait.c b/lib/libc_r/TEST/test_pthread_cond_timedwait.c new file mode 100644 index 00000000000..9942f3aa26e --- /dev/null +++ b/lib/libc_r/TEST/test_pthread_cond_timedwait.c @@ -0,0 +1,93 @@ +/* ==== test_pthread_cond.c ========================================= + * Copyright (c) 1993 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Test pthread_cond(). Run this after test_create() + * + * 1.23 94/05/04 proven + * -Started coding this file. + */ + +#include <pthread.h> +#include <stdio.h> +#include <errno.h> +#include <unistd.h> + +#ifndef ETIME +#define ETIME ETIMEDOUT +#endif + +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cond = PTHREAD_COND_INITIALIZER; + +void* thread_1(void * new_buf) +{ + pthread_mutex_lock(&mutex); + pthread_cond_signal(&cond); + pthread_mutex_unlock(&mutex); + pthread_exit(NULL); +} + +void* thread_2(void * new_buf) +{ + sleep(1); + pthread_mutex_lock(&mutex); + pthread_cond_signal(&cond); + pthread_mutex_unlock(&mutex); + pthread_exit(NULL); +} + +int +main() +{ + struct timespec abstime = { 0, 0 }; + struct timeval curtime; + pthread_t thread; + + printf("pthread_cond_timedwait START\n"); + + pthread_mutex_lock(&mutex); + gettimeofday(&curtime, NULL); + abstime.tv_sec = curtime.tv_sec + 5; + + /* Test a condition timeout */ + if (pthread_cond_timedwait(&cond, &mutex, &abstime) != ETIME) { + printf("pthread_cond_timedwait failed to timeout\n"); + printf("pthread_cond_timedwait FAILED\n"); + pthread_mutex_unlock(&mutex); + exit(1); + } + printf("Got first timeout ok\n"); /* Added by monty */ + /* Test a normal condition signal */ + if (pthread_create(&thread, NULL, thread_1, NULL)) { + printf("pthread_create failed\n"); + exit(2); + } + + abstime.tv_sec = curtime.tv_sec + 10; + if (pthread_cond_timedwait(&cond, &mutex, &abstime)) { + printf("pthread_cond_timedwait #1 timedout\n"); + printf("pthread_cond_timedwait FAILED\n"); + pthread_mutex_unlock(&mutex); + exit(1); + } + + /* Test a normal condition signal after a sleep */ + if (pthread_create(&thread, NULL, thread_2, NULL)) { + printf("pthread_create failed\n"); + exit(2); + } + + pthread_yield(); + + abstime.tv_sec = curtime.tv_sec + 10; + if (pthread_cond_timedwait(&cond, &mutex, &abstime)) { + printf("pthread_cond_timedwait #2 timedout\n"); + printf("pthread_cond_timedwait FAILED\n"); + pthread_mutex_unlock(&mutex); + exit(1); + } + + printf("pthread_cond_timedwait PASSED\n"); + pthread_mutex_unlock(&mutex); + exit(0); +} diff --git a/lib/libc_r/TEST/test_pthread_join.c b/lib/libc_r/TEST/test_pthread_join.c new file mode 100644 index 00000000000..c5f612c58eb --- /dev/null +++ b/lib/libc_r/TEST/test_pthread_join.c @@ -0,0 +1,77 @@ +/* ==== test_pthread_join.c ================================================= + * Copyright (c) 1993 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Test pthread_join(). Run this after test_create() + * + * 1.23 94/05/04 proven + * -Started coding this file. + */ + +#include <pthread.h> +#include <stdio.h> +#include "test.h" + +/* This thread yields so the creator has a live thread to wait on */ +void* new_thread_1(void * new_buf) +{ + int i; + + sprintf((char *)new_buf, "New thread %%d stack at %p\n", &i); + pthread_yield(); + return(new_buf); + PANIC(); +} + +/* This thread doesn't yield so the creator has a dead thread to wait on */ +void* new_thread_2(void * new_buf) +{ + int i; + + sprintf((char *)new_buf, "New thread %%d stack at %p\n", &i); + return(new_buf); + PANIC(); +} + +int +main() +{ + char buf[256], *status; + pthread_t thread; + int debug = 1; + int i = 0; + + printf("Original thread stack at %p\n", &i); + if (pthread_create(&thread, NULL, new_thread_1, (void *)buf) == 0) { + if (pthread_join(thread, (void **)(&status)) == 0) { + if (debug) { printf(status, ++i); } + } else { + printf("ERROR: Joining with new thread #1.\n"); + printf("FAILED: test_pthread_join\n"); + exit(1); + } + } else { + printf("ERROR: Creating new thread #1\n"); + printf("FAILED: test_pthread_join\n"); + exit(2); + } + + + /* Now have the created thread finishing before the join. */ + if (pthread_create(&thread, NULL, new_thread_2, (void *)buf) == 0){ + pthread_yield(); + if (pthread_join(thread, (void **)(&status)) == 0) { + if (debug) { printf(status, ++i); } + } else { + printf("ERROR: Joining with new thread #2.\n"); + printf("FAILED: test_pthread_join\n"); + exit(1); + } + } else { + printf("ERROR: Creating new thread #2\n"); + printf("FAILED: test_pthread_join\n"); + exit(2); + } + printf("test_pthread_join PASSED\n"); + pthread_exit(NULL); +} + diff --git a/lib/libc_r/TEST/test_pthread_mutex.c b/lib/libc_r/TEST/test_pthread_mutex.c new file mode 100644 index 00000000000..96027de5c03 --- /dev/null +++ b/lib/libc_r/TEST/test_pthread_mutex.c @@ -0,0 +1,221 @@ +/* ==== test_pthread_cond.c ========================================= + * Copyright (c) 1993 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Test pthread_cond(). Run this after test_create() + * + * 1.23 94/05/04 proven + * -Started coding this file. + */ + +#include <errno.h> +#include <pthread.h> +#include <stdio.h> +#include "test.h" + + +int contention_variable; + +void * thread_contention(void * arg) +{ + pthread_mutex_t * mutex = arg; + + if (pthread_mutex_lock(mutex)) { + printf("pthread_mutex_lock() ERROR\n"); + pthread_exit(NULL); + } + + if (contention_variable != 1) { + printf("contention_variable != 1 ERROR\n"); + pthread_exit(NULL); + } + contention_variable = 2; + + if (pthread_mutex_unlock(mutex)) { + printf("pthread_mutex_unlock() ERROR\n"); + pthread_exit(NULL); + } + pthread_exit(NULL); +} + +int test_contention_lock(pthread_mutex_t * mutex) +{ + pthread_t thread; + + printf("test_contention_lock()\n"); + + if (pthread_mutex_lock(mutex)) { + printf("pthread_mutex_lock() ERROR\n"); + return(NOTOK); + } + contention_variable = 0; + + if (pthread_create(&thread, NULL, thread_contention, mutex)) { + printf("pthread_create() FAILED\n"); + exit(2); + } + + pthread_yield(); + + contention_variable = 1; + + if (pthread_mutex_unlock(mutex)) { + printf("pthread_mutex_unlock() ERROR\n"); + return(NOTOK); + } + + if (pthread_mutex_lock(mutex)) { + printf("pthread_mutex_lock() ERROR\n"); + return(NOTOK); + } + + if (contention_variable != 2) { + printf("contention_variable != 2 ERROR\n"); + return(NOTOK); + } + + if (pthread_mutex_unlock(mutex)) { + printf("pthread_mutex_unlock() ERROR\n"); + return(NOTOK); + } + + return(OK); +} + +int test_nocontention_lock(pthread_mutex_t * mutex) +{ + printf("test_nocontention_lock()\n"); + if (pthread_mutex_lock(mutex)) { + printf("pthread_mutex_lock() ERROR\n"); + return(NOTOK); + } + if (pthread_mutex_unlock(mutex)) { + printf("pthread_mutex_unlock() ERROR\n"); + return(NOTOK); + } + return(OK); +} + +int test_debug_double_lock(pthread_mutex_t * mutex) +{ + printf("test_debug_double_lock()\n"); + if (pthread_mutex_lock(mutex)) { + printf("pthread_mutex_lock() ERROR\n"); + return(NOTOK); + } + if (pthread_mutex_lock(mutex) != EDEADLK) { + printf("double lock error not detected ERROR\n"); + return(NOTOK); + } + if (pthread_mutex_unlock(mutex)) { + printf("pthread_mutex_unlock() ERROR\n"); + return(NOTOK); + } + return(OK); +} + +int test_debug_double_unlock(pthread_mutex_t * mutex) +{ + printf("test_debug_double_unlock()\n"); + if (pthread_mutex_lock(mutex)) { + printf("pthread_mutex_lock() ERROR\n"); + return(NOTOK); + } + if (pthread_mutex_unlock(mutex)) { + printf("pthread_mutex_unlock() ERROR\n"); + return(NOTOK); + } + if (pthread_mutex_unlock(mutex) != EPERM) { + printf("double unlock error not detected ERROR\n"); + return(NOTOK); + } + return(OK); +} + +int test_nocontention_trylock(pthread_mutex_t * mutex) +{ + printf("test_nocontention_trylock()\n"); + if (pthread_mutex_trylock(mutex)) { + printf("pthread_mutex_trylock() ERROR\n"); + return(NOTOK); + } + if (pthread_mutex_unlock(mutex)) { + printf("pthread_mutex_unlock() ERROR\n"); + return(NOTOK); + } + return(OK); +} + +int test_mutex_static(void) +{ + pthread_mutex_t mutex_static = PTHREAD_MUTEX_INITIALIZER; + + printf("test_mutex_static()\n"); + if (test_nocontention_lock(&mutex_static) || + test_contention_lock(&mutex_static)) { + return(NOTOK); + } + return(OK); +} + +int test_mutex_fast(void) +{ + pthread_mutex_t mutex_fast; + + printf("test_mutex_fast()\n"); + if (pthread_mutex_init(&mutex_fast, NULL)) { + printf("pthread_mutex_init() ERROR\n"); + return(NOTOK); + } + if (test_nocontention_lock(&mutex_fast) || + test_contention_lock(&mutex_fast)) { + return(NOTOK); + } + if (pthread_mutex_destroy(&mutex_fast)) { + printf("pthread_mutex_destroy() ERROR\n"); + return(NOTOK); + } + return(OK); +} + +int test_mutex_debug() +{ + pthread_mutexattr_t mutex_debug_attr; + pthread_mutex_t mutex_debug; + + printf("test_mutex_debug()\n"); + pthread_mutexattr_init(&mutex_debug_attr); +#if 0 + pthread_mutexattr_settype(&mutex_debug_attr, PTHREAD_MUTEXTYPE_DEBUG); +#endif + if (pthread_mutex_init(&mutex_debug, &mutex_debug_attr)) { + printf("pthread_mutex_init() ERROR\n"); + return(NOTOK); + } + if (test_nocontention_lock(&mutex_debug) || + test_contention_lock(&mutex_debug) || + test_debug_double_lock(&mutex_debug) || + test_debug_double_unlock(&mutex_debug)) { + return(NOTOK); + } + if (pthread_mutex_destroy(&mutex_debug)) { + printf("pthread_mutex_destroy() ERROR\n"); + return(NOTOK); + } + return(OK); +} + +int +main() +{ + + printf("test_pthread_mutex START\n"); + + if (test_mutex_static() || test_mutex_fast() || test_mutex_debug()) { + printf("test_pthread_mutex FAILED\n"); + exit(1); + } + + printf("test_pthread_mutex PASSED\n"); + exit(0); +} + diff --git a/lib/libc_r/TEST/test_pw.c b/lib/libc_r/TEST/test_pw.c new file mode 100644 index 00000000000..d7740a109eb --- /dev/null +++ b/lib/libc_r/TEST/test_pw.c @@ -0,0 +1,21 @@ +#include <stdio.h> +#include <sys/types.h> +#include <unistd.h> +#include <pwd.h> + +int +main() +{ + struct passwd *pw; + + pw = getpwuid(getuid()); + if (!pw) { + printf("getpwuid(%d) died!\n", getuid()); + exit(1); + } + printf("getpwuid(%d) => %p\n", getuid(), pw); + printf(" you are: %s\n uid: %d\n gid: %d\n class: %s\n gecos: %s\n dir: %s\n shell: %s\n", + pw->pw_name, pw->pw_uid, pw->pw_gid, pw->pw_class, pw->pw_gecos, pw->pw_dir, + pw->pw_shell); + exit(0); +} diff --git a/lib/libc_r/TEST/test_readdir.c b/lib/libc_r/TEST/test_readdir.c new file mode 100644 index 00000000000..62167fa3100 --- /dev/null +++ b/lib/libc_r/TEST/test_readdir.c @@ -0,0 +1,41 @@ +/* ==== test_readdir.c ======================================================== + * Copyright (c) 1993, 1994 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Test pthread_create() and pthread_exit() calls. + * + * 1.00 94/05/19 proven + * -Started coding this file. + */ + +#include <pthread.h> +#include <sys/types.h> +#include <dirent.h> +#include <stdio.h> + +int +main() +{ + struct dirent * file; + DIR * dot_dir; + int found = 0; + + if ((dot_dir = opendir(".")) != NULL) { + while ((file = readdir(dot_dir)) != NULL) { + if (strcmp("test_readdir", file->d_name) == 0) { + found = 1; + } + } + closedir(dot_dir); + if (found) { + printf("test_readdir PASSED\n"); + exit(0); + } else { + printf("Couldn't find file test_readdir ERROR\n"); + } + } else { + printf("opendir() ERROR\n"); + } + printf("test_readdir FAILED\n"); + exit(1); +} + diff --git a/lib/libc_r/TEST/test_select.c b/lib/libc_r/TEST/test_select.c new file mode 100644 index 00000000000..0401d77a666 --- /dev/null +++ b/lib/libc_r/TEST/test_select.c @@ -0,0 +1,115 @@ +#include <pthread.h> +#include <stdio.h> +#ifndef ultrix +#include <sys/fcntl.h> +#else /* ultrix */ +#include <fcntl.h> +#endif /* !ultrix */ +#include <sys/types.h> +#include <sys/time.h> +#ifdef hpux +#include <sys/file.h> +#endif /* hpux */ +#include <errno.h> +#define NLOOPS 1000 + +int ntouts = 0; + +void * +bg_routine(void *arg) +{ + write(1,"bg routine running\n",19); + /*pthread_dump_state();*/ + while (1) { + int n; + char dot; + + dot = '.'; + pthread_yield(); + write(1,&dot,1); + pthread_yield(); + n = NLOOPS; + while (n-- > 0) + pthread_yield(); + } +} + +void * +fg_routine(void *arg) +{ + int flags, stat, nonblock_flag; + static struct timeval tout = { 0, 500000 }; + +#if 0 +#if defined(hpux) || defined(__alpha) + nonblock_flag = O_NONBLOCK; +#else + nonblock_flag = FNDELAY; +#endif + printf("fg_routine running\n"); + flags = fcntl(0, F_GETFL, 0); + printf("stdin flags b4 anything = %x\n", flags); + stat = fcntl(0, F_SETFL, flags | nonblock_flag); + if (stat < 0) { + printf("fcntl(%x) => %d\n", nonblock_flag, errno); + printf("could not set nonblocking i/o on stdin [oldf %x, stat %d]\n", + flags, stat); + exit(1); + } + printf("stdin flags = 0x%x after turning on %x\n", flags, nonblock_flag); +#endif + while (1) { + int n; + fd_set r; + + FD_ZERO(&r); + FD_SET(0,&r); + printf("select>"); + n = select(1, &r, (fd_set*)0, (fd_set*)0, (struct timeval *)0); + if (n < 0) { + perror ("select"); + exit(1); + } else if (n > 0) { + int nb; + char buf[128]; + + printf("=> select returned: %d\n", n); + while ((nb = read(0, buf, sizeof(buf)-1)) >= 0) { + buf[nb] = '\0'; + printf("read %d: |%s|\n", nb, buf); + } + printf("=> out of read loop: %d / %d\n", nb, errno); + if (nb < 0) { + if (errno != EWOULDBLOCK && errno != EAGAIN) { + perror ("read"); + exit(1); + } + } + } else + ntouts++; + } +} + +main(int argc, char **argv) +{ + pthread_t bg_thread, fg_thread; + int junk; + + pthread_init(); + setbuf(stdout,NULL); + setbuf(stderr,NULL); + if (argc > 1) { + if (pthread_create(&bg_thread, NULL, bg_routine, 0) < 0) { + printf("error: could not create bg thread\n"); + exit(1); + } + } + if (pthread_create(&fg_thread, NULL, fg_routine, 0) < 0) { + printf("error: could not create fg thread\n"); + exit(1); + } + printf("threads forked: bg=%lx fg=%lx\n", bg_thread, fg_thread); + /*pthread_dump_state();*/ + printf("initial thread %lx joining fg...\n", pthread_self()); + pthread_join(fg_thread, (void **)&junk); +} diff --git a/lib/libc_r/TEST/test_setjmp.c b/lib/libc_r/TEST/test_setjmp.c new file mode 100644 index 00000000000..ea24ecd63bc --- /dev/null +++ b/lib/libc_r/TEST/test_setjmp.c @@ -0,0 +1,13 @@ +#include <setjmp.h> + +main() +{ +jmp_buf foo; + +if (setjmp(foo)) { + exit(0); +} +printf("Hi mom\n"); +longjmp(foo, 1); +printf("Should never reach here\n"); +} diff --git a/lib/libc_r/TEST/test_sleep.c b/lib/libc_r/TEST/test_sleep.c new file mode 100644 index 00000000000..d13e44123bc --- /dev/null +++ b/lib/libc_r/TEST/test_sleep.c @@ -0,0 +1,47 @@ +/* ==== test_switch.c ============================================================ + * Copyright (c) 1993 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Test context switch functionality. + * + * 1.00 93/08/04 proven + * -Started coding this file. + */ + +#include <pthread.h> +#include <stdio.h> +#include <unistd.h> + +const char buf[] = "abcdefghijklimnopqrstuvwxyz"; +int fd = 1; + +void* new_thread(void* arg) +{ + int i; + + for (i = 0; i < 10; i++) { + write(fd, buf + (long) arg, 1); + sleep(1); + } + return NULL; +} + +int +main() +{ + pthread_t thread; + int count = 2; + long i; + + printf("Going to sleep\n"); + sleep(3); + printf("Done sleeping\n"); + + for(i = 0; i < count; i++) { + if (pthread_create(&thread, NULL, new_thread, (void *) i)) { + printf("error creating new thread %ld\n", i); + } + } + pthread_exit(NULL); + fprintf(stderr, "pthread_exit returned\n"); + exit(1); +} diff --git a/lib/libc_r/TEST/test_sock_1.c b/lib/libc_r/TEST/test_sock_1.c new file mode 100644 index 00000000000..8b4e594e912 --- /dev/null +++ b/lib/libc_r/TEST/test_sock_1.c @@ -0,0 +1,210 @@ +/* ==== test_sock_1.c ========================================================= + * Copyright (c) 1993 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Test pthread_create() and pthread_exit() calls. + * + * 1.00 93/08/03 proven + * -Started coding this file. + */ + +#include <pthread.h> +#include <errno.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <unistd.h> +#include "test.h" +#include <sched.h> + +struct sockaddr_in a_sout; +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_attr_t attr; + +#define MESSAGE5 "This should be message #5" +#define MESSAGE6 "This should be message #6" + +void * sock_connect(void* arg) +{ + char buf[1024]; + int fd, tmp; + + /* Ensure sock_read runs first */ + if (pthread_mutex_lock(&mutex)) { + printf("Error: sock_connect:pthread_mutex_lock()\n"); + exit(1); + } + + a_sout.sin_addr.s_addr = htonl(0x7f000001); /* loopback */ + + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + printf("Error: sock_connect:socket()\n"); + exit(1); + } + + printf("This should be message #2\n"); + if (connect(fd, (struct sockaddr *) &a_sout, sizeof(a_sout)) < 0) { + printf("Error: sock_connect:connect()\n"); + exit(1); + } + close(fd); + + if (pthread_mutex_unlock(&mutex)) { + printf("Error: sock_connect:pthread_mutex_lock()\n"); + exit(1); + } + + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + printf("Error: sock_connect:socket()\n"); + exit(1); + } + + printf("This should be message #3\n"); + + if (connect(fd, (struct sockaddr *) &a_sout, sizeof(a_sout)) < 0) { + printf("Error: sock_connect:connect()\n"); + exit(1); + } + + /* Ensure sock_read runs again */ + pthread_yield(); + pthread_yield(); + pthread_yield(); + pthread_yield(); + if (pthread_mutex_lock(&mutex)) { + printf("Error: sock_connect:pthread_mutex_lock()\n"); + exit(1); + } + + if ((tmp = read(fd, buf, 1024)) <= 0) { + printf("Error: sock_connect:read() == %d\n", tmp); + exit(1); + } + write(fd, MESSAGE6, sizeof(MESSAGE6)); + printf("%s\n", buf); + close(fd); + return(NULL); +} + +extern struct fd_table_entry ** fd_table; +void * sock_write(void* arg) +{ + int fd = *(int *)arg; + + write(fd, MESSAGE5, sizeof(MESSAGE5)); + return(NULL); +} + +void * sock_accept(void* arg) +{ + pthread_t thread; + struct sockaddr a_sin; + int a_sin_size, a_fd, fd, tmp; + short port; + char buf[1024]; + + if (pthread_mutex_unlock(&mutex)) { + printf("Error: sock_accept:pthread_mutex_lock()\n"); + exit(1); + } + + port = 3276; + a_sout.sin_family = AF_INET; + a_sout.sin_port = htons(port); + a_sout.sin_addr.s_addr = INADDR_ANY; + + if ((a_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + printf("Error: sock_accept:socket()\n"); + exit(1); + } + + while (bind(a_fd, (struct sockaddr *) &a_sout, sizeof(a_sout)) < 0) { + if (errno == EADDRINUSE) { + a_sout.sin_port = htons((++port)); + continue; + } + printf("Error: sock_accept:bind()\n"); + exit(1); + } + + if (listen(a_fd, 2)) { + printf("Error: sock_accept:listen()\n"); + exit(1); + } + + a_sin_size = sizeof(a_sin); + printf("This should be message #1\n"); + if ((fd = accept(a_fd, &a_sin, &a_sin_size)) < 0) { + perror("Error: sock_accept:accept()"); + exit(1); + } + + if (pthread_mutex_lock(&mutex)) { + printf("Error: sock_accept:pthread_mutex_lock()\n"); + exit(1); + } + close(fd); + + a_sin_size = sizeof(a_sin); + printf("This should be message #4\n"); + if ((fd = accept(a_fd, &a_sin, &a_sin_size)) < 0) { + printf("Error: sock_accept:accept()\n"); + exit(1); + } + + if (pthread_mutex_unlock(&mutex)) { + printf("Error: sock_accept:pthread_mutex_lock()\n"); + exit(1); + } + + /* Setup a write thread */ + if (pthread_create(&thread, &attr, sock_write, &fd)) { + printf("Error: sock_accept:pthread_create(sock_write)\n"); + exit(1); + } + if ((tmp = read(fd, buf, 1024)) <= 0) { + printf("Error: sock_accept:read() == %d\n", tmp); + exit(1); + } + printf("%s\n", buf); + close(fd); + return(NULL); +} + +int +main() +{ + pthread_t thread; + + setbuf(stdout, NULL); + setbuf(stderr, NULL); + + /* Ensure sock_read runs first */ + if (pthread_mutex_lock(&mutex)) { + printf("Error: main:pthread_mutex_lock()\n"); + exit(1); + } + + if (pthread_attr_init(&attr)) { + printf("Error: main:pthread_attr_init()\n"); + exit(1); + } +#if 0 + if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) { + printf("Error: main:pthread_attr_setschedpolicy()\n"); + exit(1); + } +#endif + if (pthread_create(&thread, &attr, sock_accept, (void *)0xdeadbeaf)) { + printf("Error: main:pthread_create(sock_accept)\n"); + exit(1); + } + if (pthread_create(&thread, &attr, sock_connect, (void *)0xdeadbeaf)) { + printf("Error: main:pthread_create(sock_connect)\n"); + exit(1); + } + printf("initial thread %p going to sleep\n", pthread_self()); + sleep(3); + printf("done sleeping\n"); + return 0; +} diff --git a/lib/libc_r/TEST/test_sock_2.c b/lib/libc_r/TEST/test_sock_2.c new file mode 100644 index 00000000000..1788d0bbb17 --- /dev/null +++ b/lib/libc_r/TEST/test_sock_2.c @@ -0,0 +1,119 @@ +/* ==== test_sock_1.c ========================================================= + * Copyright (c) 1993 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Test pthread_create() and pthread_exit() calls. + * + * 1.00 93/08/03 proven + * -Started coding this file. + */ + +#include <pthread.h> +#include <errno.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <unistd.h> +#include <string.h> + +struct sockaddr_in a_sout; + +#define MESSAGE5 "This should be message #5" +#define MESSAGE6 "This should be message #6" + +void * sock_write(void* arg) +{ + int fd = *(int *)arg; + + write(fd, MESSAGE5, sizeof(MESSAGE5)); + return(NULL); +} + +void * sock_accept(void* arg) +{ + pthread_t thread; + struct sockaddr a_sin; + int a_sin_size, a_fd, fd, tmp; + short port; + char buf[1024]; + + port = 3276; + a_sout.sin_family = AF_INET; + a_sout.sin_port = htons(port); + a_sout.sin_addr.s_addr = INADDR_ANY; + + if ((a_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("Error: sock_accept:socket()"); + exit(1); + } + + while (bind(a_fd, (struct sockaddr *) &a_sout, sizeof(a_sout)) < 0) { + if (errno == EADDRINUSE) { + a_sout.sin_port = htons((++port)); + continue; + } + perror("Error: sock_accept:bind()"); + exit(1); + } + + if (listen(a_fd, 2)) { + perror("Error: sock_accept:listen()"); + exit(1); + } + + a_sin_size = sizeof(a_sin); + printf("This should be message #1\n"); + if ((fd = accept(a_fd, &a_sin, &a_sin_size)) < 0) { + perror("Error: sock_accept:accept()"); + exit(1); + } + close(fd); + sleep(1); + + a_sin_size = sizeof(a_sin); + memset(&a_sin, 0, sizeof(a_sin)); + printf("This should be message #4\n"); + if ((fd = accept(a_fd, &a_sin, &a_sin_size)) < 0) { + perror("Error: sock_accept:accept()"); + exit(1); + } + + /* Setup a write thread */ + if (pthread_create(&thread, NULL, sock_write, &fd)) { + perror("Error: sock_accept:pthread_create(sock_write)"); + exit(1); + } + if ((tmp = read(fd, buf, 1024)) <= 0) { + tmp = read(fd, buf, 1024); + printf("Error: sock_accept:read() == %d %s\n", tmp, strerror(errno)); + exit(1); + } + printf("%s\n", buf); + close(fd); + return(NULL); +} + +int +main() +{ + pthread_t thread; + + switch(fork()) { + case -1: + perror("Error: main:fork()"); + break; + case 0: + execl("test_sock_2a", "test_sock_2a", "fork okay", NULL); + default: + break; + } + + setbuf(stdout, NULL); + setbuf(stderr, NULL); + + if (pthread_create(&thread, NULL, sock_accept, (void *)0xdeadbeaf)) { + perror("Error: main:pthread_create(sock_accept)"); + exit(1); + } + pthread_exit(NULL); +} diff --git a/lib/libc_r/TEST/test_sock_2a.c b/lib/libc_r/TEST/test_sock_2a.c new file mode 100644 index 00000000000..7ff73bcfc76 --- /dev/null +++ b/lib/libc_r/TEST/test_sock_2a.c @@ -0,0 +1,87 @@ +/* ==== test_sock_1.c ========================================================= + * Copyright (c) 1993 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Test pthread_create() and pthread_exit() calls. + * + * 1.00 93/08/03 proven + * -Started coding this file. + */ + +#include <pthread.h> +#include <errno.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> + +struct sockaddr_in a_sout; + +#define MESSAGE5 "This should be message #5" +#define MESSAGE6 "This should be message #6" + +void * sock_connect(void* arg) +{ + char buf[1024]; + int fd, tmp; + short port; + + port = 3276; + a_sout.sin_family = AF_INET; + a_sout.sin_port = htons(port); + a_sout.sin_addr.s_addr = htonl(0x7f000001); /* loopback */ + + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("Error: sock_connect:socket()"); + exit(1); + } + + printf("This should be message #2\n"); + if (connect(fd, (struct sockaddr *) &a_sout, sizeof(a_sout)) < 0) { + perror("Error: sock_connect:connect()"); + exit(1); + } + close(fd); + + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("Error: sock_connect:socket()"); + exit(1); + } + + printf("This should be message #3\n"); + + if (connect(fd, (struct sockaddr *) &a_sout, sizeof(a_sout)) < 0) { + perror("Error: sock_connect:connect()"); + exit(1); + } + + /* Ensure sock_read runs again */ + + if ((tmp = read(fd, buf, 1024)) <= 0) { + printf("Error: sock_connect:read() == %d %s\n", tmp, strerror(errno)); + exit(1); + } + write(fd, MESSAGE6, sizeof(MESSAGE6)); + printf("%s\n", buf); + close(fd); +} + +main(int argc, char **argv) +{ + pthread_t thread; + int i; + + if (argv[1] && (!strcmp(argv[1], "fork okay"))) { + sleep(1); + setbuf(stdout, NULL); + setbuf(stderr, NULL); + + if (pthread_create(&thread, NULL, sock_connect, (void *)0xdeadbeaf)) { + perror("Error: main:pthread_create(sock_connect)"); + exit(1); + } + pthread_exit(NULL); + } + printf("test_sock_2a needs to be execed from test_sock_2.\n"); + printf("It is not a stand alone test.\n"); + exit(1); +} diff --git a/lib/libc_r/TEST/test_stdio_1.c b/lib/libc_r/TEST/test_stdio_1.c new file mode 100644 index 00000000000..72a79630641 --- /dev/null +++ b/lib/libc_r/TEST/test_stdio_1.c @@ -0,0 +1,123 @@ +#include <pthread.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include "test.h" + +char * base_name = "test_stdio_1.c"; +char * dir_name = SRCDIR; +char * fullname; + +/* Test fopen()/ftell()/getc() */ +int test_1(void) +{ + struct stat statbuf; + FILE * fp; + int i; + + if (stat(fullname, &statbuf) < OK) { + printf("ERROR: Couldn't stat %s\n", fullname); + return(NOTOK); + } + + if ((fp = fopen(fullname, "r")) == NULL) { + printf("ERROR: Couldn't open %s\n", fullname); + return(NOTOK); + } + + /* Get the entire file */ + while ((i = getc(fp)) != EOF); + + if (ftell(fp) != statbuf.st_size) { + printf("ERROR: ftell() and stat() don't agree."); + return(NOTOK); + } + + if (fclose(fp) < OK) { + printf("ERROR: fclose() failed."); + return(NOTOK); + } + return(OK); +} + +/* Test fopen()/fclose() */ +int test_2(void) +{ + FILE *fp1, *fp2; + + if ((fp1 = fopen(fullname, "r")) == NULL) { + printf("ERROR: Couldn't fopen %s\n", fullname); + return(NOTOK); + } + + if (fclose(fp1) < OK) { + printf("ERROR: fclose() failed."); + return(NOTOK); + } + + if ((fp2 = fopen(fullname, "r")) == NULL) { + printf("ERROR: Couldn't fopen %s\n", fullname); + return(NOTOK); + } + + if (fclose(fp2) < OK) { + printf("ERROR: fclose() failed."); + return(NOTOK); + } + + if (fp1 != fp2) { + printf("ERROR: FILE table leak.\n"); + return(NOTOK); + } + + return(OK); +} + +/* Test sscanf()/sprintf() */ +int test_3(void) +{ + char * str = "10 4.53"; + char buf[64]; + double d; + int i; + + if (sscanf(str, "%d %lf", &i, &d) != 2) { + printf("ERROR: sscanf didn't parse input string correctly\n"); + return(NOTOK); + } + + /* Should have a check */ + sprintf(buf, "%d %2.2f", i, d); + + if (strcmp(buf, str)) { + printf("ERROR: sscanf()/sprintf() didn't parse unparse correctly\n"); + return(NOTOK); + } + return(OK); +} + +int +main() +{ + + printf("test_stdio_1 START\n"); + + if ((fullname = malloc (strlen (dir_name) + strlen (base_name) + 2)) != NULL) { + sprintf (fullname, "%s/%s", dir_name, base_name); + } else { + perror ("malloc"); + exit(1); + } + + if (test_1() || test_2() || test_3()) { + printf("test_stdio_1 FAILED\n"); + exit(1); + } + + printf("test_stdio_1 PASSED\n"); + exit(0); +} + + diff --git a/lib/libc_r/TEST/test_switch.c b/lib/libc_r/TEST/test_switch.c new file mode 100644 index 00000000000..eedc98c8123 --- /dev/null +++ b/lib/libc_r/TEST/test_switch.c @@ -0,0 +1,98 @@ +/* ==== test_switch.c ============================================================ + * Copyright (c) 1993 by Chris Provenzano, proven@athena.mit.edu + * + * Description : Test context switch functionality. + * + * 1.00 93/08/04 proven + * -Started coding this file. + */ + +#include <pthread.h> +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <stdlib.h> +#include "test.h" + +const char buf[] = "abcdefghijklmnopqrstuvwxyz"; +char x[sizeof(buf)]; +int fd = 1; + +/* ========================================================================== + * usage(); + */ +void usage(void) +{ + printf("test_switch [-d?] [-c count]\n"); + printf("count must be between 2 and 26\n"); + errno = 0; +} + +void* new_thread(void* arg) +{ + while(1) { + write (fd, (char *) arg, 1); + x[(char *)arg - buf] = 1; + } + fprintf(stderr, "Compiler error\n"); + exit(1); +} + +int +main(int argc, char **argv) +{ + pthread_t thread; + int count = 2; + int debug = 0; + int eof = 0; + long i; + + /* Getopt variables. */ + extern int optind, opterr; + extern char *optarg; + + while (!eof) + switch (getopt (argc, argv, "c:d?")) + { + case EOF: + eof = 1; + break; + case 'd': + debug++; + break; + case 'c': + count = atoi(optarg); + if ((count > 26) || (count < 2)) { + count = 2; + } + break; + case '?': + usage(); + return(OK); + default: + usage(); + return(NOTOK); + } + + for (i = 0; i < count; i++) { + if (pthread_create(&thread, NULL, new_thread, (void*)(buf+i))) { + fprintf (stderr, "error creating new thread %ld\n", i); + exit (1); + } + } +#if 0 /* This would cause the program to loop forever, and "make + check" would never complete. */ + pthread_exit (NULL); + fprintf(stderr, "pthread_exit returned\n"); + exit(1); +#else + sleep (3); + for (i = 0; i < count; i++) + if (x[i] == 0) { + fprintf (stderr, "thread %ld never ran\n", i); + return 1; + } + printf ("\n%s PASSED\n", argv[0]); + return 0; +#endif +} |