summaryrefslogtreecommitdiff
path: root/lib/libpthread
diff options
context:
space:
mode:
authorPeter Galbavy <peter@cvs.openbsd.org>1998-07-21 13:22:23 +0000
committerPeter Galbavy <peter@cvs.openbsd.org>1998-07-21 13:22:23 +0000
commit0294ed9251849ce79ab3d4cc45841a9f6de82844 (patch)
tree30d684d4c18138e4ccaf59b61acadc667e515c74 /lib/libpthread
parent43b686d61558c0957f1779c747214ddef20a2252 (diff)
Complete initial import from mySQL 3.22.4 (mit-pthreads/).
Lots of dross to move and remove yet. At minimum: o remove GNU config and GNU Makefiles o build arch directory and migrate away machdep/ o rebuild BSD Makefiles o move notes etc. into doc/
Diffstat (limited to 'lib/libpthread')
-rw-r--r--lib/libpthread/bin/Makefile49
-rw-r--r--lib/libpthread/bin/Makefile.in48
-rw-r--r--lib/libpthread/bin/finger/Makefile61
-rwxr-xr-xlib/libpthread/bin/finger/Makefile.in60
-rwxr-xr-xlib/libpthread/bin/finger/finger.c231
-rwxr-xr-xlib/libpthread/bin/finger/net.c189
-rw-r--r--lib/libpthread/lib/Makefile49
-rw-r--r--lib/libpthread/lib/Makefile.in48
-rw-r--r--lib/libpthread/lib/libpthreadutil/Makefile66
-rwxr-xr-xlib/libpthread/lib/libpthreadutil/Makefile.in65
-rwxr-xr-xlib/libpthread/lib/libpthreadutil/pthread_atexit.c135
-rwxr-xr-xlib/libpthread/lib/libpthreadutil/pthread_tad.c170
-rw-r--r--lib/libpthread/lib/libpthreadutil/pthreadutil.h75
-rwxr-xr-xlib/libpthread/patches/Streepy.html2873
-rwxr-xr-xlib/libpthread/patches/Streepy2.html93
-rwxr-xr-xlib/libpthread/patches/bill_lear70
-rwxr-xr-xlib/libpthread/patches/chris_demetriou149
-rwxr-xr-xlib/libpthread/patches/mevans642
-rwxr-xr-xlib/libpthread/patches/p15390
-rwxr-xr-xlib/libpthread/patches/p15596
-rw-r--r--lib/libpthread/stdio/xprintf.c883
-rwxr-xr-xlib/libpthread/stdlib/GNUmakefile.inc7
-rw-r--r--lib/libpthread/stdlib/Makefile.inc10
-rw-r--r--lib/libpthread/stdlib/abort.c67
-rw-r--r--lib/libpthread/stdlib/atexit.h46
-rw-r--r--lib/libpthread/stdlib/exit.c89
-rw-r--r--lib/libpthread/stdlib/getopt.c135
-rw-r--r--lib/libpthread/stdlib/rand.c64
-rw-r--r--lib/libpthread/stdlib/random.c389
-rw-r--r--lib/libpthread/stdlib/strtod.c178
-rw-r--r--lib/libpthread/stdlib/strtol.c131
-rw-r--r--lib/libpthread/stdlib/strtoul.c109
-rw-r--r--lib/libpthread/stdlib/system.c83
-rwxr-xr-xlib/libpthread/string/GNUmakefile.inc7
-rw-r--r--lib/libpthread/string/Makefile.inc8
-rw-r--r--lib/libpthread/string/strtok.c119
-rw-r--r--lib/libpthread/tests/Makefile165
-rw-r--r--lib/libpthread/tests/Makefile.in164
-rwxr-xr-xlib/libpthread/tests/README26
-rw-r--r--lib/libpthread/tests/bench_fcntl.c82
-rw-r--r--lib/libpthread/tests/bench_pipe.c115
-rw-r--r--lib/libpthread/tests/bench_read.c88
-rw-r--r--lib/libpthread/tests/p_bench_getpid.c78
-rw-r--r--lib/libpthread/tests/p_bench_mutex.c78
-rw-r--r--lib/libpthread/tests/p_bench_pthread_create.c92
-rw-r--r--lib/libpthread/tests/p_bench_read.c103
-rw-r--r--lib/libpthread/tests/p_bench_semaphore.c82
-rw-r--r--lib/libpthread/tests/p_bench_yield.c123
-rw-r--r--lib/libpthread/tests/test_create.c35
-rw-r--r--lib/libpthread/tests/test_cwd.c11
-rw-r--r--lib/libpthread/tests/test_execve.c57
-rw-r--r--lib/libpthread/tests/test_fcntl.c32
-rw-r--r--lib/libpthread/tests/test_fork.c60
-rw-r--r--lib/libpthread/tests/test_netdb.c110
-rw-r--r--lib/libpthread/tests/test_pause.c19
-rw-r--r--lib/libpthread/tests/test_preemption.c38
-rw-r--r--lib/libpthread/tests/test_preemption_float.c98
-rw-r--r--lib/libpthread/tests/test_pthread_cond_timedwait.c93
-rw-r--r--lib/libpthread/tests/test_pthread_join.c78
-rw-r--r--lib/libpthread/tests/test_pthread_mutex.c221
-rw-r--r--lib/libpthread/tests/test_pw.c20
-rw-r--r--lib/libpthread/tests/test_readdir.c42
-rw-r--r--lib/libpthread/tests/test_select.c115
-rw-r--r--lib/libpthread/tests/test_setjmp.c13
-rw-r--r--lib/libpthread/tests/test_sleep.c46
-rw-r--r--lib/libpthread/tests/test_sock_1.c204
-rw-r--r--lib/libpthread/tests/test_sock_2.c116
-rw-r--r--lib/libpthread/tests/test_sock_2a.c87
-rw-r--r--lib/libpthread/tests/test_stdio_1.c124
-rw-r--r--lib/libpthread/tests/test_switch.c97
70 files changed, 10496 insertions, 0 deletions
diff --git a/lib/libpthread/bin/Makefile b/lib/libpthread/bin/Makefile
new file mode 100644
index 00000000000..ce18f70b66a
--- /dev/null
+++ b/lib/libpthread/bin/Makefile
@@ -0,0 +1,49 @@
+# 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.
+#
+
+CC = ../pgcc -notinstalled
+srctop = /dr1/my/masters/mysql/mit-pthreads
+srcdir = /dr1/my/masters/mysql/mit-pthreads/lib
+VPATH = /dr1/my/masters/mysql/mit-pthreads/lib
+CDEBUGFLAGS = -g -O2 -Werror
+
+CFLAGS = $(CDEBUGFLAGS) $(INCLUDES) $(ADDL_CFLAGS) -DSRCDIR=\"$(srcdir)\"
+
+#
+DIRS = finger
+
+################################################################################
+#
+all:
+ (for i in $(DIRS); do cd $$i; $(MAKE) all; cd ..; done)
+
+clean:
+ (for i in $(DIRS); do cd $$i; $(MAKE) clean; cd ..; done)
+ rm -f *.o $(TESTS) $(BENCHMARKS) a.out core maketmp makeout
+
+depend:
+ (for i in $(DIRS); do cd $$i; $(MAKE) depend; cd ..; done)
+ sed '/\#\#\# Dependencies/q' < Makefile > maketmp
+ (for i in $(CSRC);do $(CPP) -M $$i;done) >> maketmp
+ cp maketmp Makefile
+
+install:
+ (for i in $(DIRS); do cd $$i; $(MAKE) install; cd ..; done)
+
+realclean: clean
+ (for i in $(DIRS); do cd $$i; $(MAKE) realclean; cd ..; done)
+ rm -f Makefile
+
+Makefile: Makefile.in
+ (cd .. ; sh config.status)
+
+################################################################################
+### Do not remove the following line. It is for depend #########################
+### Dependencies:
diff --git a/lib/libpthread/bin/Makefile.in b/lib/libpthread/bin/Makefile.in
new file mode 100644
index 00000000000..979ad2db2ea
--- /dev/null
+++ b/lib/libpthread/bin/Makefile.in
@@ -0,0 +1,48 @@
+# === 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.
+#
+
+CC = ../pgcc -notinstalled
+srctop = @srctop@
+srcdir = @srctop@/lib
+VPATH = @srctop@/lib
+CDEBUGFLAGS = @CFLAGS@
+
+CFLAGS = $(CDEBUGFLAGS) $(INCLUDES) $(ADDL_CFLAGS) -DSRCDIR=\"$(srcdir)\"
+
+#
+DIRS = finger
+
+################################################################################
+#
+all:
+ (for i in $(DIRS); do cd $$i; $(MAKE) all; cd ..; done)
+
+clean:
+ (for i in $(DIRS); do cd $$i; $(MAKE) clean; cd ..; done)
+ rm -f *.o $(TESTS) $(BENCHMARKS) a.out core maketmp makeout
+
+depend:
+ (for i in $(DIRS); do cd $$i; $(MAKE) depend; cd ..; done)
+ sed '/\#\#\# Dependencies/q' < Makefile > maketmp
+ (for i in $(CSRC);do $(CPP) -M $$i;done) >> maketmp
+ cp maketmp Makefile
+
+install:
+ (for i in $(DIRS); do cd $$i; $(MAKE) install; cd ..; done)
+
+realclean: clean
+ (for i in $(DIRS); do cd $$i; $(MAKE) realclean; cd ..; done)
+ rm -f Makefile
+
+Makefile: Makefile.in
+ (cd .. ; sh config.status)
+
+################################################################################
+### Do not remove the following line. It is for depend #########################
+### Dependencies:
diff --git a/lib/libpthread/bin/finger/Makefile b/lib/libpthread/bin/finger/Makefile
new file mode 100644
index 00000000000..8ee4396b758
--- /dev/null
+++ b/lib/libpthread/bin/finger/Makefile
@@ -0,0 +1,61 @@
+# Generated automatically from Makefile.in by configure.
+# === makefile ============================================================
+# 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.
+#
+
+srctop = /dr1/my/masters/mysql/mit-pthreads
+srcdir = /dr1/my/masters/mysql/mit-pthreads/bin/finger
+VPATH = /dr1/my/masters/mysql/mit-pthreads/bin/finger
+prefix= /usr/local/pthreads
+exec_prefix= ${prefix}
+
+INSTALL_PATH = ${prefix}
+ BINDIR = $(INSTALL_PATH)/bin
+ LIBDIR = $(INSTALL_PATH)/lib
+ MANDIR = $(INSTALL_PATH)/man
+ INCDIR = $(INSTALL_PATH)/include
+
+ CC = ../../pgcc -notinstalled
+ CDEBUGFLAGS = -g -O2 -Werror
+ INCLUDES = -I/dr1/my/masters/mysql/mit-pthreads/lib/libpthreadutil/ -L../../lib/libpthreadutil/
+ CFLAGS = $(CDEBUGFLAGS) $(INCLUDES) $(ADDL_CFLAGS) -DSRCDIR=\"$(srcdir)\"
+ RANLIB = ranlib
+
+ OBJS = finger.o net.o
+ BINARY = finger
+
+################################################################################
+#
+all : $(BINARY)
+
+clean:
+ rm -f *.o $(TESTS) $(BENCHMARKS) a.out core maketmp makeout
+
+depend:
+ sed '/\#\#\# Dependencies/q' < Makefile > maketmp
+ (for i in $(CSRC);do $(CPP) -M $$i;done) >> maketmp
+ cp maketmp Makefile
+
+install: $(BINARY)
+ install $(BINARY) $(BINDIR)
+
+realclean: clean
+ rm -f Makefile
+
+Makefile: Makefile.in
+ (cd ../.. ; sh config.status)
+
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+
+$(BINARY) : ${OBJS}
+ $(CC) $(CFLAGS) -o $(BINARY) ${OBJS} -lpthreadutil
+
+################################################################################
+### Do not remove the following line. It is for depend #########################
+### Dependencies:
diff --git a/lib/libpthread/bin/finger/Makefile.in b/lib/libpthread/bin/finger/Makefile.in
new file mode 100755
index 00000000000..ee20f47443d
--- /dev/null
+++ b/lib/libpthread/bin/finger/Makefile.in
@@ -0,0 +1,60 @@
+# === makefile ============================================================
+# 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.
+#
+
+srctop = @srctop@
+srcdir = @srctop@/bin/finger
+VPATH = @srctop@/bin/finger
+prefix= @prefix@
+exec_prefix= @exec_prefix@
+
+INSTALL_PATH = @exec_prefix@
+ BINDIR = $(INSTALL_PATH)/bin
+ LIBDIR = $(INSTALL_PATH)/lib
+ MANDIR = $(INSTALL_PATH)/man
+ INCDIR = $(INSTALL_PATH)/include
+
+ CC = ../../pgcc -notinstalled
+ CDEBUGFLAGS = @CFLAGS@
+ INCLUDES = -I@srctop@/lib/libpthreadutil/ -L../../lib/libpthreadutil/
+ CFLAGS = $(CDEBUGFLAGS) $(INCLUDES) $(ADDL_CFLAGS) -DSRCDIR=\"$(srcdir)\"
+ RANLIB = @RANLIB@
+
+ OBJS = finger.o net.o
+ BINARY = finger
+
+################################################################################
+#
+all : $(BINARY)
+
+clean:
+ rm -f *.o $(TESTS) $(BENCHMARKS) a.out core maketmp makeout
+
+depend:
+ sed '/\#\#\# Dependencies/q' < Makefile > maketmp
+ (for i in $(CSRC);do $(CPP) -M $$i;done) >> maketmp
+ cp maketmp Makefile
+
+install: $(BINARY)
+ install $(BINARY) $(BINDIR)
+
+realclean: clean
+ rm -f Makefile
+
+Makefile: Makefile.in
+ (cd ../.. ; sh config.status)
+
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+
+$(BINARY) : ${OBJS}
+ $(CC) $(CFLAGS) -o $(BINARY) ${OBJS} -lpthreadutil
+
+################################################################################
+### Do not remove the following line. It is for depend #########################
+### Dependencies:
diff --git a/lib/libpthread/bin/finger/finger.c b/lib/libpthread/bin/finger/finger.c
new file mode 100755
index 00000000000..33b3011e8bb
--- /dev/null
+++ b/lib/libpthread/bin/finger/finger.c
@@ -0,0 +1,231 @@
+/* ==== finger.c ============================================================
+ * Copyright (c) 1993 by Chris Provenzano, proven@athena.mit.edu
+ *
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
+ *
+ * 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, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Chris Provenzano,
+ * the University of California, Berkeley and its contributors.
+ * 4. Neither the name of Chris Provenzano, the University nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO, THE REGENTS AND CONTRIBUTORS
+ * ``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 REGENTS OR CONTRIBUTORS 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.
+ *
+ * 1.00 93/08/26 proven
+ * -Pthread redesign of this file.
+ *
+ * 1.10 95/02/11 proven
+ * -Now that gethostbyname works ....
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1989 The Regents of the University of California.\n\
+ @(#) Copyright (c) 1993, 1995 Chris Provenzano.\n\
+ @(#) Copyright (c) 1995 Greg Stark.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#include <pthreadutil.h>
+#include <sys/param.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+void *netfinger();
+
+void usage(int eval)
+{
+ fprintf(stderr,
+ "usage: finger [-lps] [-c <net_count>] [-t|T <timeout>] [-f <filename>] [login ...]\n");
+ exit(eval);
+}
+
+/*
+ * These globals are set initialy and then are only read.
+ * They do not need mutexes.
+ */
+int thread_time = 0, program_timeout = 0, lflag = 0;
+pthread_tad_t parse_file_tad;
+pthread_tad_t netfinger_tad;
+
+void * timeout_thread(void * arg)
+{
+ sleep(program_timeout);
+ exit(0);
+}
+
+void * signal_thread(void * arg)
+{
+ int sig;
+ sigset_t program_signals;
+ sigemptyset(&program_signals);
+ sigaddset(&program_signals, SIGINT);
+ sigwait(&program_signals, &sig);
+ exit(0);
+}
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+void * parse_file(void * arg)
+{
+ char hostname[MAXHOSTNAMELEN];
+ char * filename = arg;
+ pthread_atexit_t atexit_id;
+ pthread_attr_t attr;
+ pthread_t thread_id;
+ char * thread_arg;
+ FILE * fp;
+ int len;
+
+ netsetupwait();
+
+ /* Parse the file and create a thread per connection */
+ if ((fp = fopen(filename, "r")) == NULL) {
+ fprintf(stderr, "Can't open file %s\n", filename);
+ pthread_exit(NULL);
+ }
+ pthread_atexit_add(&atexit_id, fclose_nrv, fp);
+
+ if (pthread_attr_init(&attr)) {
+ fprintf(stderr, "Error: Can't initialize thread attributes\n");
+ exit(2);
+ }
+ pthread_atexit_add(&atexit_id, pthread_attr_destroy_nrv, &attr);
+
+ while (fgets(hostname, MAXHOSTNAMELEN, fp)) {
+ if ((thread_arg = (char *)malloc(len = strlen(hostname))) == NULL) {
+ fprintf(stderr, "Error: out of memory\n");
+ exit(2);
+ }
+
+ hostname[len - 1] = '\0';
+ strcpy(thread_arg, hostname);
+ pthread_attr_setcleanup(&attr, free, thread_arg);
+ if (pthread_tad_create(&netfinger_tad, &thread_id, NULL,
+ netfinger, thread_arg)) {
+ fprintf(stderr, "Error: pthread_tad_create() netfinger_tad.\n");
+ exit(2);
+ }
+ }
+ pthread_exit(NULL);
+}
+
+main(int argc, char **argv)
+{
+ pthread_atexit_t atexit_id;
+ pthread_t thread_id;
+ int max_count = 0;
+ char ch;
+
+ /* getopt variables */
+ extern char *optarg;
+ extern int optind;
+
+ /* Setup tad for parse_file() threads */
+ if (pthread_tad_init(&parse_file_tad, max_count)) {
+ fprintf(stderr,"Error: couldn't create parse_file() TAD.\n");
+ exit(1);
+ }
+
+ while ((ch = getopt(argc, argv, "c:f:t:T:ls")) != (char)EOF)
+ switch(ch) {
+ case 't': /* Time to let each thread run */
+ if ((thread_time = atoi(optarg)) <= 0) {
+ usage(1);
+ }
+ break;
+ case 'T': /* Time to let entire program run */
+ if ((program_timeout = atoi(optarg)) <= 0) {
+ usage(1);
+ }
+ break;
+ case 'f': /* Parse file for list of places to finger */
+ if (pthread_tad_create(&parse_file_tad, &thread_id, NULL,
+ parse_file, optarg)) {
+ fprintf(stderr,"Error: pthread_tad_create() parse_file_tad.\n");
+ exit(1);
+ }
+ break;
+ case 'c':
+ max_count = atoi(optarg);
+ break;
+ case 'l': /* long format */
+ lflag = 1;
+ break;
+ case 's': /* short format */
+ lflag = 0;
+ break;
+ case '?':
+ usage(0);
+ default:
+ usage(1);
+ }
+
+ /* The rest of the argumants are hosts */
+ argc -= optind;
+ argv += optind;
+
+ /* Setup timeout thread, if there is one */
+ if (program_timeout) {
+ if (pthread_create(&thread_id, NULL, timeout_thread, NULL)) {
+ fprintf(stderr,"Error: couldn't create program_timeout() thread\n");
+ exit(1);
+ }
+ }
+
+ /* Setup cleanup thread for signals */
+ if (pthread_create(&thread_id, NULL, signal_thread, NULL)) {
+ fprintf(stderr,"Error: couldn't create signal_timeout() thread\n");
+ exit(1);
+ }
+
+ /* Setup tad for netfinger() threads */
+ if (pthread_tad_init(&netfinger_tad, max_count)) {
+ fprintf(stderr,"Error: couldn't create netfinger() TAD.\n");
+ exit(1);
+ }
+
+ /* Setup the net and let everyone run */
+ netsetup();
+
+ while (*argv) {
+ if (pthread_tad_create(&netfinger_tad, &thread_id, NULL,
+ netfinger, *argv)) {
+ fprintf(stderr, "Error: pthread_tad_create() netfinger_tad.\n");
+ exit(2);
+ }
+ argv++;
+ }
+ pthread_tad_wait(&parse_file_tad, 0);
+ pthread_tad_wait(&netfinger_tad, 0);
+ exit(0);
+}
+
diff --git a/lib/libpthread/bin/finger/net.c b/lib/libpthread/bin/finger/net.c
new file mode 100755
index 00000000000..77ccd92ee8c
--- /dev/null
+++ b/lib/libpthread/bin/finger/net.c
@@ -0,0 +1,189 @@
+/* ==== net.c ============================================================
+ * Copyright (c) 1993, 1995 by Chris Provenzano, proven@athena.mit.edu
+ *
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
+ *
+ * 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, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ *
+ * 1.00 93/08/26 proven
+ * -Pthread redesign of this file.
+ */
+
+#include <pthreadutil.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+/*
+ * These globals are set initialy and then are only read.
+ * They do not need mutexes.
+ */
+extern int lflag;
+char myhostname[MAXHOSTNAMELEN];
+
+/*
+ * These globals change and therefor do need mutexes
+ */
+pthread_mutex_t spmutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t spcond = PTHREAD_COND_INITIALIZER;
+struct servent *sp = NULL;
+
+void netsetup(void)
+{
+ pthread_mutex_lock(&spmutex);
+ if (sp) {
+ fprintf(stderr, "finger: service pointer already initialized.\n");
+ exit(2);
+ }
+ if ((sp = (struct servent *)malloc(sizeof(struct servent) + 4096)) == NULL){
+ fprintf(stderr, "finger: Couldn't allocate service pointer.\n");
+ exit(2);
+ }
+ if (getservbyname_r("finger", "tcp", sp, (char *)sp + sizeof(struct servent), 4096) == NULL) {
+ fprintf(stderr, "finger: tcp/finger: unknown service\n");
+ exit(2);
+ }
+ if (gethostname(myhostname, MAXHOSTNAMELEN)) {
+ fprintf(stderr, "finger: couldn't get my hostname.\n");
+ exit(2);
+ }
+ pthread_cond_broadcast(&spcond);
+ pthread_mutex_unlock(&spmutex);
+}
+
+void netsetupwait(void)
+{
+ pthread_mutex_lock(&spmutex);
+ while(sp == NULL) {
+ pthread_cond_wait(&spcond, &spmutex);
+ }
+ pthread_mutex_unlock(&spmutex);
+}
+
+void *netfinger(char *name)
+{
+ pthread_atexit_t atexit_id;
+ register int c, lastc;
+ struct in_addr defaddr;
+ struct hostent *hp;
+ struct sockaddr_in sin;
+ int s, i, readbuflen;
+ char readbuf[1024];
+ char *host;
+
+ netsetupwait();
+ pthread_atexit_add(&atexit_id, fflush_nrv, NULL);
+
+ if (!(host = strrchr(name, '@'))) {
+ host = myhostname;
+ } else {
+ *host++ = '\0';
+ }
+ if (!(hp = gethostbyname(host))) {
+ if ((defaddr.s_addr = inet_addr(host)) < 0) {
+ fprintf(stderr, "[%s] gethostbyname: Unknown host\n", host);
+ return;
+ }
+ }
+ sin.sin_family = hp->h_addrtype;
+ memcpy((char *)&sin.sin_addr, hp->h_addr, hp->h_length);
+ sin.sin_port = sp->s_port;
+
+ if ((s = socket(sin.sin_family, SOCK_STREAM, 0)) < 0) {
+ sprintf(readbuf, "[%s]: socket", hp->h_name);
+ perror(readbuf);
+ return;
+ }
+
+ /* have network connection; identify the host connected with */
+ if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ sprintf(readbuf, "[%s]: connect", hp->h_name);
+ perror(readbuf);
+ close(s);
+ return;
+ }
+
+ /* -l flag for remote fingerd */
+ if (lflag)
+ write(s, "/W ", 3);
+ /* send the name followed by <CR><LF> */
+ write(s, name, strlen(name));
+ write(s, "\r\n", 2);
+
+ /*
+ * Read from the remote system; once we're connected, we assume some
+ * data. If none arrives, we hang until the user interrupts, or
+ * until the thread timeout expires.
+ *
+ * If we see a <CR> or a <CR> with the high bit set, treat it as
+ * a newline; if followed by a newline character, only output one
+ * newline.
+ *
+ * Otherwise, all high bits are stripped; if it isn't printable and
+ * it isn't a space, we can simply set the 7th bit. Every ASCII
+ * character with bit 7 set is printable.
+ */
+ for (readbuflen = read(s, readbuf, 1024), flockfile(stdout), lastc = '\n',
+ printf("[%s]\n", hp->h_name); readbuflen > 0;
+ readbuflen = read(s, readbuf, 1024)) {
+ for (i = 0; i < readbuflen; i++) {
+ c = readbuf[i] & 0x7f;
+ if (c == 0x0d) {
+ c = '\n';
+ lastc = '\r';
+ } else {
+ if (!isprint(c) && !isspace(c))
+ c |= 0x40;
+ if (lastc != '\r' || c != '\n')
+ lastc = c;
+ else {
+ lastc = '\n';
+ continue;
+ }
+ }
+ putchar_unlocked(c);
+ }
+ }
+ if (lastc != '\n')
+ putchar_unlocked('\n');
+ funlockfile(stdout);
+}
diff --git a/lib/libpthread/lib/Makefile b/lib/libpthread/lib/Makefile
new file mode 100644
index 00000000000..3775a11b38e
--- /dev/null
+++ b/lib/libpthread/lib/Makefile
@@ -0,0 +1,49 @@
+# 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.
+#
+
+CC = ../pgcc -notinstalled
+srctop = /dr1/my/masters/mysql/mit-pthreads
+srcdir = /dr1/my/masters/mysql/mit-pthreads/lib
+VPATH = /dr1/my/masters/mysql/mit-pthreads/lib
+CDEBUGFLAGS = -g -O2 -Werror
+
+CFLAGS = $(CDEBUGFLAGS) $(INCLUDES) $(ADDL_CFLAGS) -DSRCDIR=\"$(srcdir)\"
+
+#
+DIRS = libpthreadutil
+
+################################################################################
+#
+all:
+ (for i in $(DIRS); do cd $$i; $(MAKE) all; cd ..; done)
+
+clean:
+ (for i in $(DIRS); do cd $$i; $(MAKE) clean; cd ..; done)
+ rm -f *.o $(TESTS) $(BENCHMARKS) a.out core maketmp makeout
+
+depend:
+ (for i in $(DIRS); do cd $$i; $(MAKE) depend; cd ..; done)
+ sed '/\#\#\# Dependencies/q' < Makefile > maketmp
+ (for i in $(CSRC);do $(CPP) -M $$i;done) >> maketmp
+ cp maketmp Makefile
+
+install:
+ (for i in $(DIRS); do cd $$i; $(MAKE) install; cd ..; done)
+
+realclean: clean
+ (for i in $(DIRS); do cd $$i; $(MAKE) realclean; cd ..; done)
+ rm -f Makefile
+
+Makefile: Makefile.in
+ (cd .. ; sh config.status)
+
+################################################################################
+### Do not remove the following line. It is for depend #########################
+### Dependencies:
diff --git a/lib/libpthread/lib/Makefile.in b/lib/libpthread/lib/Makefile.in
new file mode 100644
index 00000000000..821d293d896
--- /dev/null
+++ b/lib/libpthread/lib/Makefile.in
@@ -0,0 +1,48 @@
+# === 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.
+#
+
+CC = ../pgcc -notinstalled
+srctop = @srctop@
+srcdir = @srctop@/lib
+VPATH = @srctop@/lib
+CDEBUGFLAGS = @CFLAGS@
+
+CFLAGS = $(CDEBUGFLAGS) $(INCLUDES) $(ADDL_CFLAGS) -DSRCDIR=\"$(srcdir)\"
+
+#
+DIRS = libpthreadutil
+
+################################################################################
+#
+all:
+ (for i in $(DIRS); do cd $$i; $(MAKE) all; cd ..; done)
+
+clean:
+ (for i in $(DIRS); do cd $$i; $(MAKE) clean; cd ..; done)
+ rm -f *.o $(TESTS) $(BENCHMARKS) a.out core maketmp makeout
+
+depend:
+ (for i in $(DIRS); do cd $$i; $(MAKE) depend; cd ..; done)
+ sed '/\#\#\# Dependencies/q' < Makefile > maketmp
+ (for i in $(CSRC);do $(CPP) -M $$i;done) >> maketmp
+ cp maketmp Makefile
+
+install:
+ (for i in $(DIRS); do cd $$i; $(MAKE) install; cd ..; done)
+
+realclean: clean
+ (for i in $(DIRS); do cd $$i; $(MAKE) realclean; cd ..; done)
+ rm -f Makefile
+
+Makefile: Makefile.in
+ (cd .. ; sh config.status)
+
+################################################################################
+### Do not remove the following line. It is for depend #########################
+### Dependencies:
diff --git a/lib/libpthread/lib/libpthreadutil/Makefile b/lib/libpthread/lib/libpthreadutil/Makefile
new file mode 100644
index 00000000000..58bd76446ec
--- /dev/null
+++ b/lib/libpthread/lib/libpthreadutil/Makefile
@@ -0,0 +1,66 @@
+# Generated automatically from Makefile.in by configure.
+# === makefile ============================================================
+# 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.
+#
+
+srctop = /dr1/my/masters/mysql/mit-pthreads
+srcdir = /dr1/my/masters/mysql/mit-pthreads/lib/libpthreadutil
+VPATH = /dr1/my/masters/mysql/mit-pthreads/lib/libpthreadutil
+prefix= /usr/local/pthreads
+exec_prefix= ${prefix}
+
+INSTALL_PATH = ${prefix}
+ BINDIR = $(INSTALL_PATH)/bin
+ LIBDIR = $(INSTALL_PATH)/lib
+ MANDIR = $(INSTALL_PATH)/man
+ INCDIR = $(INSTALL_PATH)/include
+
+ CC = ../../pgcc -notinstalled
+ CDEBUGFLAGS = -g -O2 -Werror
+ CFLAGS = $(CDEBUGFLAGS) $(INCLUDES) $(ADDL_CFLAGS) -DSRCDIR=\"$(srcdir)\"
+ RANLIB = ranlib
+
+ OBJS = pthread_tad.o pthread_atexit.o
+ LIBRARY = libpthreadutil.a
+ HEADERS = pthreadutil.h
+
+################################################################################
+#
+all : $(LIBRARY)
+
+clean:
+ rm -f *.o $(TESTS) $(BENCHMARKS) a.out core maketmp makeout
+
+depend:
+ sed '/\#\#\# Dependencies/q' < Makefile > maketmp
+ (for i in $(CSRC);do $(CPP) -M $$i;done) >> maketmp
+ cp maketmp Makefile
+
+install: $(LIBRARY)
+ install $(LIBRARY) $(LIBDIR)
+ for x in $(HEADERS); \
+ do cp $(srcdir)/$$x $(INCDIR); \
+ done
+
+realclean: clean
+ rm -f Makefile
+
+Makefile: Makefile.in
+ (cd ../.. ; sh config.status)
+
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+
+$(LIBRARY) : ${OBJS}
+ ar r new.a ${OBJS} && \
+ $(RANLIB) new.a && \
+ mv -f new.a $(LIBRARY)
+
+################################################################################
+### Do not remove the following line. It is for depend #########################
+### Dependencies:
diff --git a/lib/libpthread/lib/libpthreadutil/Makefile.in b/lib/libpthread/lib/libpthreadutil/Makefile.in
new file mode 100755
index 00000000000..94034f426b3
--- /dev/null
+++ b/lib/libpthread/lib/libpthreadutil/Makefile.in
@@ -0,0 +1,65 @@
+# === makefile ============================================================
+# 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.
+#
+
+srctop = @srctop@
+srcdir = @srctop@/lib/libpthreadutil
+VPATH = @srctop@/lib/libpthreadutil
+prefix= @prefix@
+exec_prefix= @exec_prefix@
+
+INSTALL_PATH = @exec_prefix@
+ BINDIR = $(INSTALL_PATH)/bin
+ LIBDIR = $(INSTALL_PATH)/lib
+ MANDIR = $(INSTALL_PATH)/man
+ INCDIR = $(INSTALL_PATH)/include
+
+ CC = ../../pgcc -notinstalled
+ CDEBUGFLAGS = @CFLAGS@
+ CFLAGS = $(CDEBUGFLAGS) $(INCLUDES) $(ADDL_CFLAGS) -DSRCDIR=\"$(srcdir)\"
+ RANLIB = @RANLIB@
+
+ OBJS = pthread_tad.o pthread_atexit.o
+ LIBRARY = libpthreadutil.a
+ HEADERS = pthreadutil.h
+
+################################################################################
+#
+all : $(LIBRARY)
+
+clean:
+ rm -f *.o $(TESTS) $(BENCHMARKS) a.out core maketmp makeout
+
+depend:
+ sed '/\#\#\# Dependencies/q' < Makefile > maketmp
+ (for i in $(CSRC);do $(CPP) -M $$i;done) >> maketmp
+ cp maketmp Makefile
+
+install: $(LIBRARY)
+ install $(LIBRARY) $(LIBDIR)
+ for x in $(HEADERS); \
+ do cp $(srcdir)/$$x $(INCDIR); \
+ done
+
+realclean: clean
+ rm -f Makefile
+
+Makefile: Makefile.in
+ (cd ../.. ; sh config.status)
+
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+
+$(LIBRARY) : ${OBJS}
+ ar r new.a ${OBJS} && \
+ $(RANLIB) new.a && \
+ mv -f new.a $(LIBRARY)
+
+################################################################################
+### Do not remove the following line. It is for depend #########################
+### Dependencies:
diff --git a/lib/libpthread/lib/libpthreadutil/pthread_atexit.c b/lib/libpthread/lib/libpthreadutil/pthread_atexit.c
new file mode 100755
index 00000000000..1d1e1ec3a6d
--- /dev/null
+++ b/lib/libpthread/lib/libpthreadutil/pthread_atexit.c
@@ -0,0 +1,135 @@
+/* ==== pthread_atexit.c =====================================================
+ * Copyright (c) 1994 by Chris Provenzano, proven@mit.edu
+ * 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, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Chris Provenzano.
+ * 4. The name of Chris Provenzano may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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.
+ *
+ * Description : Pthread attribute functions.
+ *
+ * 1.20 94/02/13 proven
+ * -Started coding this file.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id: pthread_atexit.c,v 1.1 1998/07/21 13:22:22 peter Exp $";
+#endif
+
+#define PTHREAD_KERNEL
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "pthreadutil.h"
+
+static int pthread_atexit_inited = 0;
+static pthread_key_t pthread_atexit_key;
+static pthread_mutex_t pthread_atexit_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/* ==========================================================================
+ * pthread_atexit_done()
+ */
+static void pthread_atexit_done(void * arg)
+{
+ pthread_atexit_t id, id_next;
+
+ for (id = arg; id; id = id_next) {
+ id_next = id->next;
+ id->rtn(id->arg);
+ free(id);
+ }
+}
+
+/* ==========================================================================
+ * pthread_atexit_add()
+ */
+int pthread_atexit_add(pthread_atexit_t *id, void (*rtn)(void *), void * arg)
+{
+ int ret;
+
+ if (ret = pthread_mutex_lock(&pthread_atexit_mutex)) {
+ return(ret);
+ }
+ if (!pthread_atexit_inited) {
+ if (ret = pthread_key_create(&pthread_atexit_key, pthread_atexit_done)){
+ pthread_mutex_unlock(&pthread_atexit_mutex);
+ return(ret);
+ }
+ pthread_atexit_inited++;
+ }
+ pthread_mutex_unlock(&pthread_atexit_mutex);
+
+ if ((*id) = (pthread_atexit_t)malloc(sizeof(struct pthread_atexit))) {
+ if ((*id)->next = pthread_getspecific(pthread_atexit_key)) {
+ (*id)->next->prev = (*id);
+ }
+ pthread_setspecific(pthread_atexit_key, (void *)*id);
+ (*id)->prev = NULL;
+ (*id)->rtn = rtn;
+ (*id)->arg = arg;
+ return(OK);
+ }
+ return(ENOMEM);
+}
+
+/* ==========================================================================
+ * pthread_atexit_remove()
+ */
+int pthread_atexit_remove(pthread_atexit_t * id, int execute)
+{
+ pthread_atexit_t old;
+
+ if (old = pthread_getspecific(pthread_atexit_key)) {
+ if (old == *id) {
+ old = old->next;
+ old->prev = NULL;
+ pthread_setspecific(pthread_atexit_key, old);
+ } else {
+ if ((*id)->next) {
+ (*id)->next->prev = (*id)->prev;
+ }
+ (*id)->prev->next = (*id)->next;
+ }
+ if (execute) {
+ (*id)->rtn((*id)->arg);
+ }
+ free((*id));
+ return(OK);
+ }
+ return(EINVAL);
+}
+
+/* ==========================================================================
+ * A few non void functions that are often used as void functions
+ */
+void fflush_nrv(void * fp) { fflush((FILE *)fp); }
+void fclose_nrv(void * fp) { fclose((FILE *)fp); }
+
+void pthread_attr_destroy_nrv(void * attr)
+{
+ pthread_attr_destroy((pthread_attr_t *)attr);
+}
diff --git a/lib/libpthread/lib/libpthreadutil/pthread_tad.c b/lib/libpthread/lib/libpthreadutil/pthread_tad.c
new file mode 100755
index 00000000000..a59fd9b87bf
--- /dev/null
+++ b/lib/libpthread/lib/libpthreadutil/pthread_tad.c
@@ -0,0 +1,170 @@
+/* ==== pthread_tad.c =========================================================
+ * Copyright (c) 1995 by Chris Provenzano, proven@athena.mit.edu
+ *
+ * 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, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Chris Provenzano,
+ * and its contributors.
+ * 4. Neither the name of Chris Provenzano, nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO, AND CONTRIBUTORS
+ * ``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 REGENTS OR CONTRIBUTORS 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.
+ *
+ */
+
+#ifndef lint
+static char copyright[] =
+ "@(#) Copyright (c) 1995 Chris Provenzano.\nAll rights reserved.\n";
+#endif /* not lint */
+
+/* tad = thread allocation domain */
+#define PTHREAD_KERNEL
+
+#include "pthreadutil.h"
+#include <stdio.h>
+#include <errno.h>
+
+int pthread_tad_count(pthread_tad_t * tad)
+{
+ int ret;
+
+ pthread_mutex_lock(&tad->mutex);
+ ret = tad->count_current;
+ pthread_mutex_unlock(&tad->mutex);
+ return(ret);
+}
+
+static void pthread_tad_done(void * arg)
+{
+ pthread_tad_t * tad = arg;
+ pthread_mutex_lock(&tad->mutex);
+ --tad->count_current;
+/* if (--tad->count_current < tad->count_max) */
+ pthread_cond_broadcast(&tad->cond);
+ pthread_mutex_unlock(&tad->mutex);
+}
+
+#ifndef PTHREAD_KERNEL
+struct tad_start {
+ pthread_tad_t * tad;
+ void * (*routine)();
+ void * arg;
+};
+
+static void * pthread_tad_start(struct tad_start * tad_start)
+{
+ void * (*routine)() = tad_start->routine;
+ void * arg = tad_start->arg;
+
+ pthread_mutex_lock(&tad_start->tad->mutex);
+ pthread_cleanup_push(pthread_tad_done, tad_start->tad);
+ pthread_mutex_unlock(&tad_start->tad->mutex);
+ free(tad_start);
+ return(routine(arg));
+}
+#else
+static void * pthread_tad_start(void * tad_start_arg)
+{
+ pthread_tad_t * tad = tad_start_arg;
+ void * (*routine)() = tad->routine;
+ void * arg = tad->arg;
+
+ tad->count_current++;
+ pthread_cleanup_push(pthread_tad_done, tad);
+ pthread_mutex_unlock(&tad->mutex);
+ return(routine(arg));
+}
+#endif
+
+int pthread_tad_create(pthread_tad_t * tad, pthread_t *thread_id,
+ pthread_attr_t *attr, void * (*routine)(), void * arg)
+{
+#ifndef PTHREAD_KERNEL
+ struct tad_start tad;
+#endif
+ int ret;
+
+ pthread_mutex_lock(&tad->mutex);
+ while (tad->count_max && (tad->count_current > tad->count_max))
+ pthread_cond_wait(&tad->cond, &tad->mutex);
+
+#ifndef PTHREAD_KERNEL
+ if ((tad_start = malloc(sizeof(struct tad_start))) == NULL) {
+ pthread_mutex_unlock(&tad->mutex);
+ return(ENOMEM);
+ }
+ tad_start->routine = routine;
+ tad_start->arg = arg;
+ tad_start->tad = tad;
+ if ((ret = pthread_create(thread_id, attr,
+ pthread_tad_start, tad_start)) == OK)
+ tad->count_current++;
+ pthread_mutex_unlock(&tad->mutex);
+#else
+ tad->routine = routine;
+ tad->arg = arg;
+ if (ret = pthread_create(thread_id, attr, pthread_tad_start, tad))
+ pthread_mutex_unlock(&tad->mutex);
+#endif
+ return(ret);
+}
+
+int pthread_tad_wait(pthread_tad_t * tad, unsigned int count)
+{
+ if ((tad->count_max) && (tad->count_max < count)) {
+ return(EINVAL);
+ }
+ pthread_mutex_lock(&tad->mutex);
+ while (tad->count_current > count)
+ pthread_cond_wait(&tad->cond, &tad->mutex);
+ pthread_mutex_unlock(&tad->mutex);
+ return(OK);
+}
+
+int pthread_tad_init(pthread_tad_t * tad, unsigned int max_count)
+{
+ int ret;
+
+ if ((ret = pthread_mutex_init(&tad->mutex, NULL)) == OK) {
+ if (ret = pthread_cond_init(&tad->cond, NULL)) {
+ pthread_mutex_destroy(&tad->mutex);
+ } else {
+ tad->count_max = max_count;
+ tad->count_current = 0;
+ }
+ }
+ return(ret);
+}
+
+/* User is responsible to make sure their are no threads running */
+int pthread_tad_destroy(pthread_tad_t * tad)
+{
+ int ret;
+
+ if ((ret = pthread_mutex_destroy(&tad->mutex)) == OK) {
+ ret = pthread_cond_destroy(&tad->cond);
+ } else {
+ pthread_cond_destroy(&tad->cond);
+ }
+ tad->count_max = NOTOK;
+ return(ret);
+}
diff --git a/lib/libpthread/lib/libpthreadutil/pthreadutil.h b/lib/libpthread/lib/libpthreadutil/pthreadutil.h
new file mode 100644
index 00000000000..0d8e6a6ef5f
--- /dev/null
+++ b/lib/libpthread/lib/libpthreadutil/pthreadutil.h
@@ -0,0 +1,75 @@
+/* ==== pthread_tad.h ========================================================
+ * Copyright (c) 1995 by Chris Provenzano, proven@athena.mit.edu
+ *
+ * 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, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Chris Provenzano,
+ * and its contributors.
+ * 4. Neither the name of Chris Provenzano, nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO, AND CONTRIBUTORS
+ * ``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 REGENTS OR CONTRIBUTORS 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.
+ *
+ */
+
+#include <pthread.h>
+#include <sys/cdefs.h>
+
+typedef struct pthread_tad_t {
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ unsigned int count_current;
+ unsigned int count_max;
+ void * arg;
+ void * (*routine)();
+} pthread_tad_t;
+
+typedef struct pthread_atexit {
+ struct pthread_atexit * next;
+ struct pthread_atexit * prev;
+ void (*rtn)(void *);
+ void * arg;
+} * pthread_atexit_t;
+
+/*
+ * New functions
+ */
+
+__BEGIN_DECLS
+
+int pthread_tad_count __P_((pthread_tad_t *));
+int pthread_tad_create __P_((pthread_tad_t *, pthread_t *, pthread_attr_t *,
+ void *(*routine)(), void *));
+int pthread_tad_wait __P_((pthread_tad_t *, unsigned int));
+int pthread_tad_init __P_((pthread_tad_t *, unsigned int));
+int pthread_tad_destroy __P_((pthread_tad_t *));
+
+int pthread_atexit_add __P_((pthread_atexit_t *, void (*)(void *), void *));
+int pthread_atexit_remove __P_((pthread_atexit_t *, int));
+
+
+void fclose_nrv __P_((void *));
+void fflush_nrv __P_((void *));
+void pthread_attr_destroy_nrv __P_((void *));
+
+__END_DECLS
+
diff --git a/lib/libpthread/patches/Streepy.html b/lib/libpthread/patches/Streepy.html
new file mode 100755
index 00000000000..a3b4faa815f
--- /dev/null
+++ b/lib/libpthread/patches/Streepy.html
@@ -0,0 +1,2873 @@
+diff -c -r1.1.1.1 pthread.h
+*** pthread.h 1996/03/13 04:30:57 1.1.1.1
+--- pthread.h 1996/10/02 17:52:47
+***************
+*** 35,40 ****
+--- 35,43 ----
+ *
+ * 1.00 93/07/20 proven
+ * -Started coding this file.
++ *
++ * 93/9/28 streepy - Added support for pthread cancel
++ *
+ */
+
+ #ifndef _PTHREAD_H_
+***************
+*** 65,70 ****
+--- 68,82 ----
+ /* More includes, that need size_t */
+ #include <pthread/pthread_attr.h>
+
++ /* Constants for use with pthread_setcancelstate and pthread_setcanceltype */
++ #define PTHREAD_CANCEL_DISABLE 0
++ #define PTHREAD_CANCEL_ENABLE 1
++ #define PTHREAD_CANCEL_DEFERRED 0
++ #define PTHREAD_CANCEL_ASYNCHRONOUS 1
++
++ #define PTHREAD_CANCELLED (void *)1 /* Exit status of a cancelled thread */
++
++
+ #ifdef PTHREAD_KERNEL
+
+ #include <signal.h> /* for sigset_t */
+***************
+*** 78,120 ****
+ PS_STATE_MAX
+ };
+
+- #define PF_WAIT_EVENT 0x01
+- #define PF_DONE_EVENT 0x02
+-
+ /* Put PANIC inside an expression that evaluates to non-void type, to
+ make it easier to combine it in expressions. */
+! #define DO_PANIC() (PANIC (), 0)
+! #define PANICIF(x) ((x) ? DO_PANIC () : 0)
+
+! #define SET_PF_DONE_EVENT(x) \
+! ( !(x->flags & PF_DONE_EVENT) \
+! ? ( (x->flags & PF_WAIT_EVENT) \
+! ? (x->flags = PF_DONE_EVENT, OK) \
+! : DO_PANIC ()) \
+ : NOTOK )
+
+! #define SET_PF_WAIT_EVENT(x) \
+! ( PANICIF (x->flags & (PF_WAIT_EVENT | PF_DONE_EVENT)), \
+! (x->flags = PF_WAIT_EVENT), 0)
+!
+! #define CLEAR_PF_DONE_EVENT(x) \
+! ( PANICIF (!(x->flags & PF_DONE_EVENT)), \
+! x->flags = 0 )
+
+ struct pthread_select_data {
+! int nfds;
+! fd_set readfds;
+! fd_set writefds;
+! fd_set exceptfds;
+ };
+
+ union pthread_wait_data {
+! pthread_mutex_t * mutex;
+! pthread_cond_t * cond;
+! const sigset_t * sigwait; /* Waiting on a signal in sigwait */
+ struct {
+! short fd; /* Used when thread waiting on fd */
+! short branch; /* line number, for debugging */
+ } fd;
+ struct pthread_select_data * select_data;
+ };
+--- 90,185 ----
+ PS_STATE_MAX
+ };
+
+ /* Put PANIC inside an expression that evaluates to non-void type, to
+ make it easier to combine it in expressions. */
+! #define DO_PANIC() (PANIC (), 0)
+! #define PANICIF(x) ((x) ? DO_PANIC () : 0)
+!
+! /* In the thread flag field, we use a series of bit flags. Flags can
+! * organized into "groups" of mutually exclusive flags. Other flags
+! * are unrelated and can be set and cleared with a single bit operation.
+! */
+
+! #define PF_WAIT_EVENT 0x01
+! #define PF_DONE_EVENT 0x02
+! #define PF_EVENT_GROUP 0x03 /* All event bits */
+!
+! #define PF_CANCEL_STATE 0x04 /* cancellability state */
+! #define PF_CANCEL_TYPE 0x08 /* cancellability type */
+! #define PF_THREAD_CANCELLED 0x10 /* thread has been cancelled */
+! #define PF_RUNNING_TO_CANCEL 0x20 /* Thread is running so it can cancel*/
+! #define PF_AT_CANCEL_POINT 0x40 /* Thread is at a cancel point */
+!
+! /* Flag operations */
+!
+! #define SET_PF_FLAG(x,f) ( (x)->flags |= (f) )
+! #define TEST_PF_FLAG(x,f) ( (x)->flags & (f) )
+! #define CLEAR_PF_FLAG(x,f) ( (x)->flags &= ~(f) )
+! #define CLEAR_PF_GROUP(x,g) ( (x)->flags &= ~(g) )
+! #define SET_PF_FLAG_IN_GROUP(x,g,f) ( CLEAR_PF_GROUP(x,g),SET_PF_FLAG(x,f))
+! #define TEST_PF_GROUP(x,g) ( (x)->flags & (g) )
+!
+! #define SET_PF_DONE_EVENT(x) \
+! ( !TEST_PF_FLAG(x,PF_DONE_EVENT) \
+! ? ( TEST_PF_FLAG(x,PF_WAIT_EVENT) \
+! ? (SET_PF_FLAG_IN_GROUP(x,PF_EVENT_GROUP,PF_DONE_EVENT), OK) \
+! : DO_PANIC ()) \
+ : NOTOK )
+
+! #define SET_PF_WAIT_EVENT(x) \
+! ( PANICIF (TEST_PF_GROUP(x,PF_EVENT_GROUP) ), \
+! SET_PF_FLAG_IN_GROUP(x,PF_EVENT_GROUP,PF_WAIT_EVENT), 0)
+!
+! #define CLEAR_PF_DONE_EVENT(x) \
+! ( PANICIF (!TEST_PF_FLAG(x,PF_DONE_EVENT)), \
+! CLEAR_PF_GROUP(x,PF_EVENT_GROUP) )
+!
+! #define SET_PF_CANCELLED(x) ( SET_PF_FLAG(x,PF_THREAD_CANCELLED) )
+! #define TEST_PF_CANCELLED(x) ( TEST_PF_FLAG(x,PF_THREAD_CANCELLED) )
+!
+! #define SET_PF_RUNNING_TO_CANCEL(x) ( SET_PF_FLAG(x,PF_RUNNING_TO_CANCEL) )
+! #define CLEAR_PF_RUNNING_TO_CANCEL(x)( CLEAR_PF_FLAG(x,PF_RUNNING_TO_CANCEL) )
+! #define TEST_PF_RUNNING_TO_CANCEL(x)( TEST_PF_FLAG(x,PF_RUNNING_TO_CANCEL) )
+!
+! #define SET_PF_AT_CANCEL_POINT(x) ( SET_PF_FLAG(x,PF_AT_CANCEL_POINT) )
+! #define CLEAR_PF_AT_CANCEL_POINT(x) ( CLEAR_PF_FLAG(x,PF_AT_CANCEL_POINT) )
+! #define TEST_PF_AT_CANCEL_POINT(x) ( TEST_PF_FLAG(x,PF_AT_CANCEL_POINT) )
+!
+! #define SET_PF_CANCEL_STATE(x,f) \
+! ( (f) ? SET_PF_FLAG(x,PF_CANCEL_STATE) : CLEAR_PF_FLAG(x,PF_CANCEL_STATE) )
+! #define TEST_PF_CANCEL_STATE(x) \
+! ( (TEST_PF_FLAG(x,PF_CANCEL_STATE)) ? PTHREAD_CANCEL_ENABLE \
+! : PTHREAD_CANCEL_DISABLE )
+!
+! #define SET_PF_CANCEL_TYPE(x,f) \
+! ( (f) ? SET_PF_FLAG(x,PF_CANCEL_TYPE) : CLEAR_PF_FLAG(x,PF_CANCEL_TYPE) )
+! #define TEST_PF_CANCEL_TYPE(x) \
+! ( (TEST_PF_FLAG(x,PF_CANCEL_TYPE)) ? PTHREAD_CANCEL_ASYNCHRONOUS \
+! : PTHREAD_CANCEL_DEFERRED )
+!
+! /* See if a thread is in a state that it can be cancelled */
+! #define TEST_PTHREAD_IS_CANCELLABLE(x) \
+! ( (TEST_PF_CANCEL_STATE(x) == PTHREAD_CANCEL_ENABLE && TEST_PF_CANCELLED(x)) \
+! ? ((TEST_PF_CANCEL_TYPE(x) == PTHREAD_CANCEL_ASYNCHRONOUS) \
+! ? 1 \
+! : TEST_PF_AT_CANCEL_POINT(x)) \
+! : 0 )
+!
+
+ struct pthread_select_data {
+! int nfds;
+! fd_set readfds;
+! fd_set writefds;
+! fd_set exceptfds;
+ };
+
+ union pthread_wait_data {
+! pthread_mutex_t * mutex;
+! pthread_cond_t * cond;
+! const sigset_t * sigwait; /* Waiting on a signal in sigwait */
+ struct {
+! short fd; /* Used when thread waiting on fd */
+! short branch; /* line number, for debugging */
+ } fd;
+ struct pthread_select_data * select_data;
+ };
+***************
+*** 122,143 ****
+ #define PTT_USER_THREAD 0x0001
+
+ struct pthread {
+! int thread_type;
+ struct machdep_pthread machdep_data;
+! pthread_attr_t attr;
+
+ /* Signal interface */
+! sigset_t sigmask;
+! sigset_t sigpending;
+! int sigcount; /* Number of signals pending */
+
+ /* Timeout time */
+! struct timespec wakeup_time;
+
+ /* Join queue for waiting threads */
+ struct pthread_queue join_queue;
+
+-
+ /*
+ * Thread implementations are just multiple queue type implemenations,
+ * Below are the various link lists currently necessary
+--- 187,207 ----
+ #define PTT_USER_THREAD 0x0001
+
+ struct pthread {
+! int thread_type;
+ struct machdep_pthread machdep_data;
+! pthread_attr_t attr;
+
+ /* Signal interface */
+! sigset_t sigmask;
+! sigset_t sigpending;
+! int sigcount; /* Number of signals pending */
+
+ /* Timeout time */
+! struct timespec wakeup_time;
+
+ /* Join queue for waiting threads */
+ struct pthread_queue join_queue;
+
+ /*
+ * Thread implementations are just multiple queue type implemenations,
+ * Below are the various link lists currently necessary
+***************
+*** 152,165 ****
+ * ALL threads, in any state.
+ * Must lock kernel lock before manipulating.
+ */
+! struct pthread * pll;
+
+ /*
+ * Standard link list for running threads, mutexes, etc ...
+ * It can't be on both a running link list and a wait queue.
+ * Must lock kernel lock before manipulating.
+ */
+! struct pthread * next;
+ union pthread_wait_data data;
+
+ /*
+--- 216,229 ----
+ * ALL threads, in any state.
+ * Must lock kernel lock before manipulating.
+ */
+! struct pthread * pll;
+
+ /*
+ * Standard link list for running threads, mutexes, etc ...
+ * It can't be on both a running link list and a wait queue.
+ * Must lock kernel lock before manipulating.
+ */
+! struct pthread * next;
+ union pthread_wait_data data;
+
+ /*
+***************
+*** 167,197 ****
+ * (Note: "priority" is a reserved word in Concurrent C, please
+ * don't use it. --KR)
+ */
+! struct pthread_queue * queue;
+! enum pthread_state state;
+! char flags;
+! char pthread_priority;
+
+ /*
+ * Sleep queue, this is different from the standard link list
+ * because it is possible to be on both (pthread_cond_timedwait();
+ * Must lock sleep mutex before manipulating
+ */
+! struct pthread *sll; /* For sleeping threads */
+
+ /*
+ * Data that doesn't need to be locked
+! * Mostly it's because only the thread owning the data can manipulate it
+ */
+! void * ret;
+! int error;
+! int * error_p;
+! const void ** specific_data;
+! int specific_data_count;
+
+ /* Cleanup handlers Link List */
+ struct pthread_cleanup *cleanup;
+-
+ };
+
+ #else /* not PTHREAD_KERNEL */
+--- 231,261 ----
+ * (Note: "priority" is a reserved word in Concurrent C, please
+ * don't use it. --KR)
+ */
+! struct pthread_queue * queue;
+! enum pthread_state state;
+! enum pthread_state old_state; /* Used when cancelled */
+! char flags;
+! char pthread_priority;
+
+ /*
+ * Sleep queue, this is different from the standard link list
+ * because it is possible to be on both (pthread_cond_timedwait();
+ * Must lock sleep mutex before manipulating
+ */
+! struct pthread *sll; /* For sleeping threads */
+
+ /*
+ * Data that doesn't need to be locked
+! * Mostly because only the thread owning the data can manipulate it
+ */
+! void * ret;
+! int error;
+! int * error_p;
+! const void ** specific_data;
+! int specific_data_count;
+
+ /* Cleanup handlers Link List */
+ struct pthread_cleanup *cleanup;
+ };
+
+ #else /* not PTHREAD_KERNEL */
+***************
+*** 200,223 ****
+
+ #endif
+
+! typedef struct pthread * pthread_t;
+
+ /*
+ * Globals
+ */
+ #ifdef PTHREAD_KERNEL
+
+! extern struct pthread * pthread_run;
+! extern struct pthread * pthread_initial;
+! extern struct pthread * pthread_link_list;
+ extern struct pthread_queue pthread_dead_queue;
+ extern struct pthread_queue pthread_alloc_queue;
+
+! extern pthread_attr_t pthread_attr_default;
+! extern volatile int fork_lock;
+! extern pthread_size_t pthread_pagesize;
+!
+! extern sigset_t * uthread_sigmask;
+
+ #endif
+
+--- 264,293 ----
+
+ #endif
+
+! typedef struct pthread *pthread_t;
+
+ /*
+ * Globals
+ */
+ #ifdef PTHREAD_KERNEL
+
+! extern struct pthread * pthread_run;
+! extern struct pthread * pthread_initial;
+! extern struct pthread * pthread_link_list;
+ extern struct pthread_queue pthread_dead_queue;
+ extern struct pthread_queue pthread_alloc_queue;
+
+! extern pthread_attr_t pthread_attr_default;
+! extern volatile int fork_lock;
+! extern pthread_size_t pthread_pagesize;
+!
+! extern sigset_t * uthread_sigmask;
+!
+! /* Kernel global functions */
+! extern void pthread_sched_prevent(void);
+! extern void pthread_sched_resume(void);
+! extern int __pthread_is_valid( pthread_t );
+! extern void pthread_cancel_internal( int freelocks );
+
+ #endif
+
+***************
+*** 229,271 ****
+
+ #if defined(DCE_COMPAT)
+
+! typedef void * (*pthread_startroutine_t)(void *)
+! typedef void * pthread_addr_t
+
+! int pthread_create __P((pthread_t *, pthread_attr_t,
+! pthread_startroutine_t,
+! pthread_addr_t));
+! void pthread_exit __P((pthread_addr_t));
+! int pthread_join __P((pthread_t, pthread_addr_t *));
+
+ #else
+
+! void pthread_init __P((void));
+! int pthread_create __P((pthread_t *,
+! const pthread_attr_t *,
+! void * (*start_routine)(void *),
+! void *));
+! void pthread_exit __P((void *));
+! pthread_t pthread_self __P((void));
+! int pthread_equal __P((pthread_t, pthread_t));
+! int pthread_join __P((pthread_t, void **));
+! int pthread_detach __P((pthread_t));
+! void pthread_yield __P((void));
+!
+! int pthread_setschedparam __P((pthread_t pthread, int policy,
+! struct sched_param * param));
+! int pthread_getschedparam __P((pthread_t pthread, int * policy,
+! struct sched_param * param));
+!
+! int pthread_kill __P((struct pthread *, int));
+! int pthread_signal __P((int, void (*)(int)));
+
+ #endif
+
+ #if defined(PTHREAD_KERNEL)
+
+ /* Not valid, but I can't spell so this will be caught at compile time */
+! #define pthread_yeild(notvalid)
+
+ #endif
+
+--- 299,343 ----
+
+ #if defined(DCE_COMPAT)
+
+! typedef void * (*pthread_startroutine_t)(void *);
+! typedef void * pthread_addr_t;
+
+! int pthread_create __P((pthread_t *, pthread_attr_t,
+! pthread_startroutine_t, pthread_addr_t));
+! void pthread_exit __P((pthread_addr_t));
+! int pthread_join __P((pthread_t, pthread_addr_t *));
+
+ #else
+
+! void pthread_init __P((void));
+! int pthread_create __P((pthread_t *, const pthread_attr_t *,
+! void * (*start_routine)(void *), void *));
+! void pthread_exit __P((void *));
+! pthread_t pthread_self __P((void));
+! int pthread_equal __P((pthread_t, pthread_t));
+! int pthread_join __P((pthread_t, void **));
+! int pthread_detach __P((pthread_t));
+! void pthread_yield __P((void));
+!
+! int pthread_setschedparam __P((pthread_t pthread, int policy,
+! struct sched_param * param));
+! int pthread_getschedparam __P((pthread_t pthread, int * policy,
+! struct sched_param * param));
+!
+! int pthread_kill __P((struct pthread *, int));
+! int pthread_signal __P((int, void (*)(int)));
+!
+! int pthread_cancel __P(( pthread_t pthread ));
+! int pthread_setcancelstate __P(( int state, int *oldstate ));
+! int pthread_setcanceltype __P(( int type, int *oldtype ));
+! void pthread_testcancel __P(( void ));
+
+ #endif
+
+ #if defined(PTHREAD_KERNEL)
+
+ /* Not valid, but I can't spell so this will be caught at compile time */
+! #define pthread_yeild(notvalid)
+
+ #endif
+
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/include/signal.h,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 signal.h
+*** signal.h 1995/12/25 03:03:09 1.1.1.1
+--- signal.h 1996/09/26 21:46:04
+***************
+*** 43,48 ****
+--- 43,49 ----
+ __BEGIN_DECLS
+
+ int raise __P((int));
++ __sighandler_t signal __P((int __sig, __sighandler_t));
+
+ #ifndef _ANSI_SOURCE
+
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/include/pthread/kernel.h,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 kernel.h
+*** kernel.h 1994/12/13 07:09:01 1.1.1.1
+--- kernel.h 1996/10/02 19:08:41
+***************
+*** 42,48 ****
+ */
+ #if defined(PTHREAD_KERNEL)
+
+! #define PANIC() abort()
+
+ /* Time each rr thread gets */
+ #define PTHREAD_RR_TIMEOUT 100000000
+--- 42,54 ----
+ */
+ #if defined(PTHREAD_KERNEL)
+
+! #ifdef __GNUC__
+! #include <assert.h>
+! #define PANIC() panic_kernel( __FILE__, __LINE__, __ASSERT_FUNCTION )
+! #else
+! #define PANIC() panic_kernel( __FILE__, __LINE__, (const char *)0 )
+! #endif
+!
+
+ /* Time each rr thread gets */
+ #define PTHREAD_RR_TIMEOUT 100000000
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/machdep/syscall-i386-linux-1.0.S,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 syscall-i386-linux-1.0.S
+*** syscall-i386-linux-1.0.S 1995/09/27 04:38:55 1.1.1.1
+--- syscall-i386-linux-1.0.S 1996/06/04 19:20:17
+***************
+*** 147,154 ****
+
+ /* =========================================================================
+ * exit 1 select 82
+! * fork 2 socketcall 102
+! * read 3
+ * write 4
+ * open 5
+ * creat 8
+--- 147,154 ----
+
+ /* =========================================================================
+ * exit 1 select 82
+! * fork 2 fstatfs 100
+! * read 3 socketcall 102
+ * write 4
+ * open 5
+ * creat 8
+***************
+*** 160,166 ****
+ * chown 16
+ * lseek 19
+ * rename 38
+! * dup 41
+ * pipe 42
+ * ioctl 54
+ * fcntl 55
+--- 160,166 ----
+ * chown 16
+ * lseek 19
+ * rename 38
+! * dup 41
+ * pipe 42
+ * ioctl 54
+ * fcntl 55
+***************
+*** 302,314 ****
+ #endif
+
+ /* ==========================================================================
+! * machdep_sys_fstat()
+ */
+ #ifdef __ELF__
+ STATCALL2(lstat)
+ #else
+ SYSCALL2(lstat)
+ #endif
+
+ /* ==========================================================================
+ * machdep_sys_ftruncate()
+--- 302,320 ----
+ #endif
+
+ /* ==========================================================================
+! * machdep_sys_lstat()
+ */
+ #ifdef __ELF__
+ STATCALL2(lstat)
+ #else
+ SYSCALL2(lstat)
+ #endif
++
++ /* ==========================================================================
++ * machdep_sys_fstatfs()
++ */
++ SYSCALL2(fstatfs)
++
+
+ /* ==========================================================================
+ * machdep_sys_ftruncate()
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/machdep/linux-1.0/socket.h,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 socket.h
+*** socket.h 1995/12/26 02:28:03 1.1.1.1
+--- socket.h 1996/09/27 18:12:45
+***************
+*** 26,32 ****
+
+ #endif
+
+! /* #include <asm/socket.h> /* arch-dependent defines */
+ #include <linux/sockios.h> /* the SIOCxxx I/O controls */
+ #include <pthread/posix.h>
+
+--- 26,32 ----
+
+ #endif
+
+! /* #include <asm/socket.h> arch-dependent defines */
+ #include <linux/sockios.h> /* the SIOCxxx I/O controls */
+ #include <pthread/posix.h>
+
+***************
+*** 161,166 ****
+--- 161,188 ----
+ int connect __P((int, const struct sockaddr *, int));
+ int listen __P((int, int));
+ int socket __P((int, int, int));
++
++ int getsockopt __P ((int __s, int __level, int __optname,
++ void *__optval, int *__optlen));
++ int setsockopt __P ((int __s, int __level, int __optname,
++ __const void *__optval, int optlen));
++ int getsockname __P ((int __sockfd, struct sockaddr *__addr,
++ int *__paddrlen));
++ int getpeername __P ((int __sockfd, struct sockaddr *__peer,
++ int *__paddrlen));
++ ssize_t send __P ((int __sockfd, __const void *__buff, size_t __len, int __flags));
++ ssize_t recv __P ((int __sockfd, void *__buff, size_t __len, int __flags));
++ ssize_t sendto __P ((int __sockfd, __const void *__buff, size_t __len,
++ int __flags, __const struct sockaddr *__to,
++ int __tolen));
++ ssize_t recvfrom __P ((int __sockfd, void *__buff, size_t __len,
++ int __flags, struct sockaddr *__from,
++ int *__fromlen));
++ extern ssize_t sendmsg __P ((int __fd, __const struct msghdr *__message,
++ int __flags));
++ extern ssize_t recvmsg __P ((int __fd, struct msghdr *__message,
++ int __flags));
++ int shutdown __P ((int __sockfd, int __how));
+
+ __END_DECLS
+
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/machdep/linux-1.0/timers.h,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 timers.h
+*** timers.h 1996/03/05 08:28:36 1.1.1.1
+--- timers.h 1996/05/25 21:30:08
+***************
+*** 43,52 ****
+--- 43,54 ----
+ #include <sys/types.h>
+ #include <time.h>
+
++ #ifndef _LINUX_TIME_H
+ struct timespec {
+ time_t tv_sec;
+ long tv_nsec;
+ };
++ #endif /* _LINUX_TIME_H */
+
+ #define TIMEVAL_TO_TIMESPEC(tv, ts) { \
+ (ts)->tv_sec = (tv)->tv_sec; \
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/net/getprotoent.c,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 getprotoent.c
+*** getprotoent.c 1996/02/09 05:39:41 1.1.1.1
+--- getprotoent.c 1996/05/27 01:11:27
+***************
+*** 128,135 ****
+ if (p != NULL)
+ *p++ = '\0';
+ }
+! if (p && *p);
+! break;
+ }
+ *alias = NULL;
+ pthread_mutex_unlock(&proto_file_lock);
+--- 128,135 ----
+ if (p != NULL)
+ *p++ = '\0';
+ }
+! if (p && *p)
+! break;
+ }
+ *alias = NULL;
+ pthread_mutex_unlock(&proto_file_lock);
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/net/proto_internal.c,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 proto_internal.c
+*** proto_internal.c 1996/02/09 05:39:49 1.1.1.1
+--- proto_internal.c 1996/06/04 16:25:57
+***************
+*** 49,55 ****
+ static int init_status;
+
+ /* Performs global initialization. */
+! char *_proto_init()
+ {
+ char *buf;
+
+--- 49,55 ----
+ static int init_status;
+
+ /* Performs global initialization. */
+! char *_proto_buf()
+ {
+ char *buf;
+
+***************
+*** 75,78 ****
+ {
+ init_status = pthread_key_create(&key, free);
+ }
+-
+--- 75,77 ----
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/net/res_internal.c,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 res_internal.c
+*** res_internal.c 1996/02/09 05:39:53 1.1.1.1
+--- res_internal.c 1996/09/25 23:31:11
+***************
+*** 144,149 ****
+--- 144,150 ----
+ break;
+ cp += n;
+ result->h_name = bp;
++ bp += strlen(bp) + 1;
+ iquery_done = 1;
+ break;
+ }
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/pthreads/GNUmakefile.inc,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 GNUmakefile.inc
+*** GNUmakefile.inc 1995/08/30 22:27:04 1.1.1.1
+--- GNUmakefile.inc 1996/10/02 19:04:29
+***************
+*** 8,14 ****
+ syscall.S pthread_join.c pthread_detach.c pthread_once.c sleep.c \
+ specific.c process.c wait.c errno.c schedparam.c _exit.c prio_queue.c \
+ pthread_init.c init.cc sig.c info.c mutexattr.c select.c wrapper.c \
+! dump_state.c pthread_kill.c stat.c readv.c writev.c condattr.c $(SRCS)
+
+ ifeq ($(HAVE_SYSCALL_TEMPLATE),yes)
+ SYSCALL_FILTER_RULE= for s in $(AVAILABLE_SYSCALLS) ; do \
+--- 8,15 ----
+ syscall.S pthread_join.c pthread_detach.c pthread_once.c sleep.c \
+ specific.c process.c wait.c errno.c schedparam.c _exit.c prio_queue.c \
+ pthread_init.c init.cc sig.c info.c mutexattr.c select.c wrapper.c \
+! dump_state.c pthread_kill.c stat.c readv.c writev.c condattr.c \
+! pthread_cancel.c panic.c $(SRCS)
+
+ ifeq ($(HAVE_SYSCALL_TEMPLATE),yes)
+ SYSCALL_FILTER_RULE= for s in $(AVAILABLE_SYSCALLS) ; do \
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/pthreads/Makefile.inc,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 Makefile.inc
+*** Makefile.inc 1995/08/22 22:09:07 1.1.1.1
+--- Makefile.inc 1996/10/02 19:04:38
+***************
+*** 8,14 ****
+ pthread_join.c pthread_detach.c pthread_once.c sleep.c specific.c \
+ process.c wait.c errno.c schedparam.c _exit.c prio_queue.c \
+ pthread_init.c init.cc sig.c info.c mutexattr.c select.c wrapper.c \
+! dump_state.c pthread_kill.c condattr.c
+
+ .if $(HAVE_SYSCALL_TEMPLATE) == yes
+ OBJS+= syscalls.o
+--- 8,14 ----
+ pthread_join.c pthread_detach.c pthread_once.c sleep.c specific.c \
+ process.c wait.c errno.c schedparam.c _exit.c prio_queue.c \
+ pthread_init.c init.cc sig.c info.c mutexattr.c select.c wrapper.c \
+! dump_state.c pthread_kill.c condattr.c pthread_cancel.c panic.c
+
+ .if $(HAVE_SYSCALL_TEMPLATE) == yes
+ OBJS+= syscalls.o
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/pthreads/cond.c,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 cond.c
+*** cond.c 1996/03/05 08:29:12 1.1.1.1
+--- cond.c 1996/10/03 18:19:04
+***************
+*** 188,197 ****
+--- 188,204 ----
+ pthread_queue_enq(&cond->c_queue, pthread_run);
+ pthread_mutex_unlock(mutex);
+
++ pthread_run->data.mutex = mutex;
++
+ SET_PF_WAIT_EVENT(pthread_run);
++ SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
+ /* Reschedule will unlock pthread_run */
+ pthread_resched_resume(PS_COND_WAIT);
++ CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
+ CLEAR_PF_DONE_EVENT(pthread_run);
++
++ pthread_run->data.mutex = NULL;
++
+ rval = pthread_mutex_lock(mutex);
+ return(rval);
+ break;
+***************
+*** 203,212 ****
+--- 210,226 ----
+ pthread_mutex_unlock(mutex);
+ mutex->m_data.m_count = 1;
+
++ pthread_run->data.mutex = mutex;
++
+ SET_PF_WAIT_EVENT(pthread_run);
++ SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
+ /* Reschedule will unlock pthread_run */
+ pthread_resched_resume(PS_COND_WAIT);
++ CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
+ CLEAR_PF_DONE_EVENT(pthread_run);
++
++ pthread_run->data.mutex = NULL;
++
+ rval = pthread_mutex_lock(mutex);
+ mutex->m_data.m_count = count;
+ return(rval);
+***************
+*** 258,265 ****
+--- 272,285 ----
+ SET_PF_WAIT_EVENT(pthread_run);
+ pthread_mutex_unlock(mutex);
+
++ pthread_run->data.mutex = mutex;
++
++ SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
+ /* Reschedule will unlock pthread_run */
+ pthread_resched_resume(PS_COND_WAIT);
++ CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
++
++ pthread_run->data.mutex = NULL;
+
+ /* Remove ourselves from sleep queue. If we fail then we timedout */
+ if (sleep_cancel(pthread_run) == NOTOK) {
+***************
+*** 285,292 ****
+--- 305,318 ----
+ SET_PF_WAIT_EVENT(pthread_run);
+ pthread_mutex_unlock(mutex);
+
++ pthread_run->data.mutex = mutex;
++
++ SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
+ /* Reschedule will unlock pthread_run */
+ pthread_resched_resume(PS_COND_WAIT);
++ CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
++
++ pthread_run->data.mutex = NULL;
+
+ /* Remove ourselves from sleep queue. If we fail then we timedout */
+ if (sleep_cancel(pthread_run) == NOTOK) {
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/pthreads/fd.c,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 fd.c
+*** fd.c 1996/02/09 02:54:19 1.1.1.1
+--- fd.c 1996/10/03 01:33:03
+***************
+*** 48,54 ****
+--- 48,59 ----
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <sys/uio.h>
++ #include <sys/ioctl.h>
++ #if __STDC__
+ #include <stdarg.h>
++ #else
++ #include <varargs.h>
++ #endif
+ #include <fcntl.h>
+ #include <errno.h>
+ #include <pthread/posix.h>
+***************
+*** 62,67 ****
+--- 67,74 ----
+ static const int dtablecount = 4096/sizeof(struct fd_table_entry);
+ int dtablesize;
+
++ static int fd_get_pthread_fd_from_kernel_fd( int );
++
+ /* ==========================================================================
+ * Allocate dtablecount entries at once and populate the fd_table.
+ *
+***************
+*** 199,204 ****
+--- 206,244 ----
+ return(NOTOK);
+ }
+
++ /*----------------------------------------------------------------------
++ * Function: fd_get_pthread_fd_from_kernel_fd
++ * Purpose: get the fd_table index of a kernel fd
++ * Args: fd = kernel fd to convert
++ * Returns: fd_table index, -1 if not found
++ * Notes:
++ *----------------------------------------------------------------------*/
++ static int
++ fd_get_pthread_fd_from_kernel_fd( int kfd )
++ {
++ int j;
++
++ /* This is *SICK*, but unless there is a faster way to
++ * turn a kernel fd into an fd_table index, this has to do.
++ */
++ for( j=0; j < dtablesize; j++ ) {
++ if( fd_table[j] &&
++ fd_table[j]->type != FD_NT &&
++ fd_table[j]->type != FD_NIU &&
++ fd_table[j]->fd.i == kfd ) {
++ return j;
++ }
++ }
++
++ /* Not listed byfd, Check for kernel fd == pthread fd */
++ if( fd_table[kfd] == NULL || fd_table[kfd]->type == FD_NT ) {
++ /* Assume that the kernel fd is the same */
++ return kfd;
++ }
++
++ return NOTOK; /* Not found */
++ }
++
+ /* ==========================================================================
+ * fd_basic_basic_unlock()
+ *
+***************
+*** 288,293 ****
+--- 328,334 ----
+ switch (fd_table[fd]->type) {
+ case FD_NIU:
+ /* If not in use return EBADF error */
++ SET_ERRNO(EBADF);
+ return(NOTOK);
+ break;
+ case FD_NT:
+***************
+*** 297,302 ****
+--- 338,344 ----
+ */
+ fd_kern_init(fd);
+ if (fd_table[fd]->type == FD_NIU) {
++ SET_ERRNO(EBADF);
+ return(NOTOK);
+ }
+ break;
+***************
+*** 409,414 ****
+--- 451,545 ----
+ return(OK);
+ }
+
++ /*----------------------------------------------------------------------
++ * Function: fd_unlock_for_cancel
++ * Purpose: Unlock all fd locks held prior to being cancelled
++ * Args: void
++ * Returns:
++ * OK or NOTOK
++ * Notes:
++ * Assumes the kernel is locked on entry
++ *----------------------------------------------------------------------*/
++ int
++ fd_unlock_for_cancel( void )
++ {
++ int i, fd;
++ struct pthread_select_data *data;
++ int rdlk, wrlk, lktype;
++ int found;
++
++ /* What we do depends on the previous state of the thread */
++ switch( pthread_run->old_state ) {
++ case PS_RUNNING:
++ case PS_JOIN:
++ case PS_SLEEP_WAIT:
++ case PS_WAIT_WAIT:
++ case PS_SIGWAIT:
++ case PS_FDLR_WAIT:
++ case PS_FDLW_WAIT:
++ case PS_DEAD:
++ case PS_UNALLOCED:
++ break; /* Nothing to do */
++
++ case PS_COND_WAIT:
++ CLEAR_PF_GROUP( pthread_run, PF_EVENT_GROUP );
++ /* Must reaquire the mutex according to the standard */
++ if( pthread_run->data.mutex == NULL ) {
++ PANIC();
++ }
++ pthread_mutex_lock( pthread_run->data.mutex );
++ break;
++
++ case PS_FDR_WAIT:
++ CLEAR_PF_GROUP( pthread_run, PF_EVENT_GROUP);
++ /* Free the lock on the fd being used */
++ fd = fd_get_pthread_fd_from_kernel_fd( pthread_run->data.fd.fd );
++ if( fd == NOTOK ) {
++ PANIC(); /* Can't find fd */
++ }
++ fd_unlock( fd, FD_READ );
++ break;
++
++ case PS_FDW_WAIT: /* Waiting on i/o */
++ CLEAR_PF_GROUP( pthread_run, PF_EVENT_GROUP);
++ /* Free the lock on the fd being used */
++ fd = fd_get_pthread_fd_from_kernel_fd( pthread_run->data.fd.fd );
++ if( fd == NOTOK ) {
++ PANIC(); /* Can't find fd */
++ }
++ fd_unlock( fd, FD_WRITE );
++ break;
++
++ case PS_SELECT_WAIT:
++ data = pthread_run->data.select_data;
++
++ CLEAR_PF_GROUP( pthread_run, PF_EVENT_GROUP);
++
++ for( i = 0; i < data->nfds; i++) {
++ rdlk =(FD_ISSET(i,&data->readfds)
++ || FD_ISSET(i,&data->exceptfds));
++ wrlk = FD_ISSET(i, &data->writefds);
++ lktype = rdlk ? (wrlk ? FD_RDWR : FD_READ) : FD_WRITE;
++
++ if( ! (rdlk || wrlk) )
++ continue; /* No locks, no unlock */
++
++ if( (fd = fd_get_pthread_fd_from_kernel_fd( i )) == NOTOK ) {
++ PANIC(); /* Can't find fd */
++ }
++
++ fd_unlock( fd, lktype );
++ }
++ break;
++
++ case PS_MUTEX_WAIT:
++ PANIC(); /* Should never cancel a mutex wait */
++
++ default:
++ PANIC(); /* Unknown thread status */
++ }
++ }
++
+ /* ==========================================================================
+ * fd_lock()
+ */
+***************
+*** 476,481 ****
+--- 607,616 ----
+ ret = fd_table[fd]->ops->read(fd_table[fd]->fd,
+ fd_table[fd]->flags, buf, nbytes, timeout);
+ fd_unlock(fd, FD_READ);
++ if( ret < 0 ) {
++ SET_ERRNO(-ret);
++ ret = NOTOK;
++ }
+ }
+ return(ret);
+ }
+***************
+*** 500,505 ****
+--- 635,644 ----
+ ret = fd_table[fd]->ops->readv(fd_table[fd]->fd,
+ fd_table[fd]->flags, iov, iovcnt, timeout);
+ fd_unlock(fd, FD_READ);
++ if( ret < 0 ) {
++ SET_ERRNO(-ret);
++ ret = NOTOK;
++ }
+ }
+ return(ret);
+ }
+***************
+*** 524,529 ****
+--- 663,672 ----
+ ret = fd_table[fd]->ops->write(fd_table[fd]->fd,
+ fd_table[fd]->flags, buf, nbytes, timeout);
+ fd_unlock(fd, FD_WRITE);
++ if( ret < 0 ) {
++ SET_ERRNO(-ret);
++ ret = NOTOK;
++ }
+ }
+ return(ret);
+ }
+***************
+*** 548,553 ****
+--- 691,700 ----
+ ret = fd_table[fd]->ops->writev(fd_table[fd]->fd,
+ fd_table[fd]->flags, iov, iovcnt, timeout);
+ fd_unlock(fd, FD_WRITE);
++ if( ret < 0 ) {
++ SET_ERRNO(-ret);
++ ret = NOTOK;
++ }
+ }
+ return(ret);
+ }
+***************
+*** 599,677 ****
+ union fd_data realfd;
+ int ret, flags;
+
+ /* Need to lock the newfd by hand */
+! if (fd < dtablesize) {
+! pthread_mutex_lock(&fd_table_mutex);
+! if (fd_table[fd]) {
+! pthread_mutex_unlock(&fd_table_mutex);
+! mutex = &(fd_table[fd]->mutex);
+! pthread_mutex_lock(mutex);
+
+! /*
+! * XXX Gross hack ... because of fork(), any fd closed by the
+! * parent should not change the fd of the child, unless it owns it.
+ */
+! switch(fd_table[fd]->type) {
+! case FD_NIU:
+! pthread_mutex_unlock(mutex);
+! ret = -EINVAL;
+! break;
+! case FD_NT:
+! /*
+! * If it's not tested then the only valid possibility is it's
+! * kernel fd.
+! */
+! ret = machdep_sys_close(fd);
+! fd_table[fd]->type = FD_NIU;
+! pthread_mutex_unlock(mutex);
+! break;
+! case FD_TEST_FULL_DUPLEX:
+! case FD_TEST_HALF_DUPLEX:
+ realfd = fd_table[fd]->fd;
+ flags = fd_table[fd]->flags;
+ if ((entry = fd_free(fd)) == NULL) {
+! ret = fd_table[fd]->ops->close(realfd, flags);
+ } else {
+! /* There can't be any others waiting for fd. */
+ pthread_mutex_unlock(&entry->mutex);
+ /* Note: entry->mutex = mutex */
+- mutex = &(fd_table[fd]->mutex);
+ }
+ pthread_mutex_unlock(mutex);
+- break;
+- default:
+- ret = fd_basic_lock(fd, FD_RDWR, mutex, NULL);
+- if (ret == OK) {
+- realfd = fd_table[fd]->fd;
+- flags = fd_table[fd]->flags;
+- pthread_mutex_unlock(mutex);
+- if ((entry = fd_free(fd)) == NULL) {
+- ret = fd_table[fd]->ops->close(realfd, flags);
+- } else {
+- fd_basic_basic_unlock(entry, FD_RDWR);
+- pthread_mutex_unlock(&entry->mutex);
+- /* Note: entry->mutex = mutex */
+- }
+- fd_unlock(fd, FD_RDWR);
+- } else {
+- pthread_mutex_unlock(mutex);
+- }
+- break;
+ }
+! } else {
+! /* Don't bother creating a table entry */
+! pthread_mutex_unlock(&fd_table_mutex);
+! ret = machdep_sys_close(fd);
+ }
+! return(ret);
+ }
+! return(-EINVAL);
+ }
+
+ /* ==========================================================================
+ * fd_basic_dup()
+ *
+ * Might need to do more than just what's below.
+ */
+ static inline void fd_basic_dup(int fd, int newfd)
+ {
+--- 746,836 ----
+ union fd_data realfd;
+ int ret, flags;
+
++ if( fd < 0 || fd >= dtablesize ) {
++ SET_ERRNO(EBADF);
++ return -1;
++ }
++
+ /* Need to lock the newfd by hand */
+! pthread_mutex_lock(&fd_table_mutex);
+! if (fd_table[fd]) {
+! pthread_mutex_unlock(&fd_table_mutex);
+! mutex = &(fd_table[fd]->mutex);
+! pthread_mutex_lock(mutex);
+
+! /*
+! * XXX Gross hack ... because of fork(), any fd closed by the
+! * parent should not change the fd of the child, unless it owns it.
+! */
+! switch(fd_table[fd]->type) {
+! case FD_NIU:
+! pthread_mutex_unlock(mutex);
+! ret = -EBADF;
+! break;
+! case FD_NT:
+! /*
+! * If it's not tested then the only valid possibility is it's
+! * kernel fd.
+ */
+! ret = machdep_sys_close(fd);
+! fd_table[fd]->type = FD_NIU;
+! pthread_mutex_unlock(mutex);
+! break;
+! case FD_TEST_FULL_DUPLEX:
+! case FD_TEST_HALF_DUPLEX:
+! realfd = fd_table[fd]->fd;
+! flags = fd_table[fd]->flags;
+! if ((entry = fd_free(fd)) == NULL) {
+! ret = fd_table[fd]->ops->close(realfd, flags);
+! } else {
+! /* There can't be any others waiting for fd. */
+! pthread_mutex_unlock(&entry->mutex);
+! /* Note: entry->mutex = mutex */
+! mutex = &(fd_table[fd]->mutex);
+! }
+! pthread_mutex_unlock(mutex);
+! break;
+! default:
+! ret = fd_basic_lock(fd, FD_RDWR, mutex, NULL);
+! if (ret == OK) {
+ realfd = fd_table[fd]->fd;
+ flags = fd_table[fd]->flags;
++ pthread_mutex_unlock(mutex);
+ if ((entry = fd_free(fd)) == NULL) {
+! ret = fd_table[fd]->ops->close(realfd, flags);
+ } else {
+! fd_basic_basic_unlock(entry, FD_RDWR);
+ pthread_mutex_unlock(&entry->mutex);
+ /* Note: entry->mutex = mutex */
+ }
++ fd_unlock(fd, FD_RDWR);
++ } else {
+ pthread_mutex_unlock(mutex);
+ }
+! break;
+ }
+! } else {
+! /* Don't bother creating a table entry */
+! pthread_mutex_unlock(&fd_table_mutex);
+! ret = machdep_sys_close(fd);
+! }
+!
+! if( ret < 0 ) {
+! SET_ERRNO(-ret);
+! ret = -1;
+ }
+!
+! return ret;
+ }
+
+ /* ==========================================================================
+ * fd_basic_dup()
+ *
+ * Might need to do more than just what's below.
++ *
++ * This is a MAJOR guess!! I don't know if the mutext unlock is valid
++ * in the BIG picture. But it seems to be needed to avoid deadlocking
++ * with ourselves when we try to close the duped file descriptor.
+ */
+ static inline void fd_basic_dup(int fd, int newfd)
+ {
+***************
+*** 679,684 ****
+--- 838,845 ----
+ fd_table[fd]->next = fd_table[newfd];
+ fd_table[newfd] = fd_table[fd];
+ fd_table[fd]->count++;
++ pthread_mutex_unlock(&fd_table[newfd]->next->mutex);
++
+ }
+
+ /* ==========================================================================
+***************
+*** 896,904 ****
+ * ala select()... --SNL
+ */
+ int
+! ioctl(int fd, unsigned long request, caddr_t arg)
+ {
+ int ret;
+
+ if (fd < 0 || fd >= dtablesize)
+ ret = NOTOK;
+--- 1057,1071 ----
+ * ala select()... --SNL
+ */
+ int
+! ioctl(int fd, int request, ...)
+ {
+ int ret;
++ pthread_va_list ap;
++ caddr_t arg;
++
++ va_start( ap, request ); /* Get the arg */
++ arg = va_arg(ap,caddr_t);
++ va_end( ap );
+
+ if (fd < 0 || fd >= dtablesize)
+ ret = NOTOK;
+***************
+*** 906,911 ****
+--- 1073,1086 ----
+ ret = machdep_sys_ioctl(fd, request, arg);
+ else if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
+ ret = machdep_sys_ioctl(fd_table[fd]->fd.i, request, arg);
++ if( ret == 0 && request == FIONBIO ) {
++ /* Properly set NONBLOCK flag */
++ int v = *(int *)arg;
++ if( v )
++ fd_table[fd]->flags |= __FD_NONBLOCK;
++ else
++ fd_table[fd]->flags &= ~__FD_NONBLOCK;
++ }
+ fd_unlock(fd, FD_RDWR);
+ }
+ return ret;
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/pthreads/fd_kern.c,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 fd_kern.c
+*** fd_kern.c 1996/02/12 00:58:30 1.1.1.1
+--- fd_kern.c 1996/10/03 01:54:15
+***************
+*** 128,134 ****
+
+
+ if ((count = machdep_sys_select(dtablesize, &fd_set_read,
+! &fd_set_write, NULL, &__fd_kern_poll_timeout)) < OK) {
+ if (count == -EINTR) {
+ return;
+ }
+--- 128,134 ----
+
+
+ if ((count = machdep_sys_select(dtablesize, &fd_set_read,
+! &fd_set_write, &fd_set_except, &__fd_kern_poll_timeout)) < OK) {
+ if (count == -EINTR) {
+ return;
+ }
+***************
+*** 167,200 ****
+
+ for (pthread = fd_wait_select.q_next; count && pthread; ) {
+ int found_one = 0;
+
+ for (i = 0; i < pthread->data.select_data->nfds; i++) {
+ int count_dec = 0;
+
+! if ((FD_ISSET(i, &pthread->data.select_data->exceptfds) &&
+! ! FD_ISSET(i, &fd_set_except))) {
+! FD_CLR(i, &pthread->data.select_data->exceptfds);
+! } else {
+! count_dec++;
+ }
+! if ((FD_ISSET(i, &pthread->data.select_data->writefds) &&
+! ! FD_ISSET(i, &fd_set_write))) {
+! FD_CLR(i, &pthread->data.select_data->writefds);
+! } else {
+! count_dec++;
+ }
+! if ((FD_ISSET(i, &pthread->data.select_data->readfds) &&
+! ! FD_ISSET(i, &fd_set_read))) {
+! FD_CLR(i, &pthread->data.select_data->readfds);
+! } else {
+! count_dec++;
+ }
+ if (count_dec) {
+ found_one++;
+ count--;
+ }
+ }
+ if (found_one) {
+ deq = pthread;
+ pthread = pthread->next;
+ pthread_queue_remove(&fd_wait_select, deq);
+--- 167,223 ----
+
+ for (pthread = fd_wait_select.q_next; count && pthread; ) {
+ int found_one = 0;
++ fd_set tmp_readfds, tmp_writefds, tmp_exceptfds;
++
++ memcpy(&tmp_readfds, &pthread->data.select_data->readfds,
++ sizeof(fd_set));
++ memcpy(&tmp_writefds, &pthread->data.select_data->writefds,
++ sizeof(fd_set));
++ memcpy(&tmp_exceptfds, &pthread->data.select_data->exceptfds,
++ sizeof(fd_set));
+
+ for (i = 0; i < pthread->data.select_data->nfds; i++) {
+ int count_dec = 0;
+
+! if( (FD_ISSET(i, &tmp_exceptfds)) ) {
+! if( FD_ISSET(i, &fd_set_except) ) {
+! count_dec++; /* got a hit */
+! } else {
+! FD_CLR(i, &tmp_exceptfds);
+! }
+ }
+!
+! if( (FD_ISSET(i, &tmp_writefds)) ) {
+! if( FD_ISSET(i, &fd_set_write) ) {
+! count_dec++; /* got a hit */
+! } else {
+! FD_CLR(i, &tmp_writefds);
+! }
+ }
+!
+! if( (FD_ISSET(i, &tmp_readfds)) ) {
+! if( FD_ISSET(i, &fd_set_read) ) {
+! count_dec++; /* got a hit */
+! } else {
+! FD_CLR(i, &tmp_readfds);
+! }
+ }
++
+ if (count_dec) {
+ found_one++;
+ count--;
+ }
+ }
++
+ if (found_one) {
++ /* Update the threads saved select data fd sets */
++ memcpy(&pthread->data.select_data->readfds, &tmp_readfds,
++ sizeof(fd_set));
++ memcpy(&pthread->data.select_data->writefds, &tmp_writefds,
++ sizeof(fd_set));
++ memcpy(&pthread->data.select_data->exceptfds, &tmp_exceptfds,
++ sizeof(fd_set));
++
+ deq = pthread;
+ pthread = pthread->next;
+ pthread_queue_remove(&fd_wait_select, deq);
+***************
+*** 266,272 ****
+ */
+
+ while ((count = machdep_sys_select(dtablesize, &fd_set_read,
+! &fd_set_write, NULL, &__fd_kern_wait_timeout)) < OK) {
+ if (count == -EINTR) {
+ return;
+ }
+--- 289,295 ----
+ */
+
+ while ((count = machdep_sys_select(dtablesize, &fd_set_read,
+! &fd_set_write, &fd_set_except, &__fd_kern_wait_timeout)) < OK) {
+ if (count == -EINTR) {
+ return;
+ }
+***************
+*** 305,338 ****
+
+ for (pthread = fd_wait_select.q_next; count && pthread; ) {
+ int found_one = 0;
+
+ for (i = 0; i < pthread->data.select_data->nfds; i++) {
+ int count_dec = 0;
+
+! if ((FD_ISSET(i, &pthread->data.select_data->exceptfds) &&
+! ! FD_ISSET(i, &fd_set_except))) {
+! FD_CLR(i, &pthread->data.select_data->exceptfds);
+! } else {
+! count_dec++;
+ }
+! if ((FD_ISSET(i, &pthread->data.select_data->writefds) &&
+! ! FD_ISSET(i, &fd_set_write))) {
+! FD_CLR(i, &pthread->data.select_data->writefds);
+! } else {
+! count_dec++;
+ }
+! if ((FD_ISSET(i, &pthread->data.select_data->readfds) &&
+! ! FD_ISSET(i, &fd_set_read))) {
+! FD_CLR(i, &pthread->data.select_data->readfds);
+! } else {
+! count_dec++;
+ }
+ if (count_dec) {
+ found_one++;
+ count--;
+ }
+ }
+ if (found_one) {
+ deq = pthread;
+ pthread = pthread->next;
+ pthread_queue_remove(&fd_wait_select, deq);
+--- 328,383 ----
+
+ for (pthread = fd_wait_select.q_next; count && pthread; ) {
+ int found_one = 0;
++ fd_set tmp_readfds, tmp_writefds, tmp_exceptfds;
++
++ memcpy(&tmp_readfds, &pthread->data.select_data->readfds,
++ sizeof(fd_set));
++ memcpy(&tmp_writefds, &pthread->data.select_data->writefds,
++ sizeof(fd_set));
++ memcpy(&tmp_exceptfds, &pthread->data.select_data->exceptfds,
++ sizeof(fd_set));
+
+ for (i = 0; i < pthread->data.select_data->nfds; i++) {
+ int count_dec = 0;
+
+! if( (FD_ISSET(i, &tmp_exceptfds)) ) {
+! if( FD_ISSET(i, &fd_set_except) ) {
+! count_dec++; /* got a hit */
+! } else {
+! FD_CLR(i, &tmp_exceptfds);
+! }
+ }
+!
+! if( (FD_ISSET(i, &tmp_writefds)) ) {
+! if( FD_ISSET(i, &fd_set_write) ) {
+! count_dec++; /* got a hit */
+! } else {
+! FD_CLR(i, &tmp_writefds);
+! }
+ }
+!
+! if( (FD_ISSET(i, &tmp_readfds)) ) {
+! if( FD_ISSET(i, &fd_set_read) ) {
+! count_dec++; /* got a hit */
+! } else {
+! FD_CLR(i, &tmp_readfds);
+! }
+ }
++
+ if (count_dec) {
+ found_one++;
+ count--;
+ }
+ }
+ if (found_one) {
++ /* Update the threads saved select data fd sets */
++ memcpy(&pthread->data.select_data->readfds, &tmp_readfds,
++ sizeof(fd_set));
++ memcpy(&pthread->data.select_data->writefds, &tmp_writefds,
++ sizeof(fd_set));
++ memcpy(&pthread->data.select_data->exceptfds, &tmp_exceptfds,
++ sizeof(fd_set));
++
+ deq = pthread;
+ pthread = pthread->next;
+ pthread_queue_remove(&fd_wait_select, deq);
+***************
+*** 380,404 ****
+ machdep_gettimeofday(&current_time);
+ sleep_schedule(&current_time, timeout);
+
+ pthread_resched_resume(PS_FDR_WAIT);
+
+ /* We're awake */
+ pthread_sched_prevent();
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+- SET_ERRNO(ETIMEDOUT);
+ ret = -ETIMEDOUT;
+ break;
+ }
+ pthread_sched_resume();
+ } else {
+ pthread_resched_resume(PS_FDR_WAIT);
+ }
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ } else {
+- SET_ERRNO(-ret);
+- ret = NOTOK;
+ break;
+ }
+ }
+--- 425,450 ----
+ machdep_gettimeofday(&current_time);
+ sleep_schedule(&current_time, timeout);
+
++ SET_PF_AT_CANCEL_POINT(pthread_run);
+ pthread_resched_resume(PS_FDR_WAIT);
++ CLEAR_PF_AT_CANCEL_POINT(pthread_run);
+
+ /* We're awake */
+ pthread_sched_prevent();
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ ret = -ETIMEDOUT;
+ break;
+ }
+ pthread_sched_resume();
+ } else {
++ SET_PF_AT_CANCEL_POINT(pthread_run);
+ pthread_resched_resume(PS_FDR_WAIT);
++ CLEAR_PF_AT_CANCEL_POINT(pthread_run);
+ }
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ } else {
+ break;
+ }
+ }
+***************
+*** 437,443 ****
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+- SET_ERRNO(ETIMEDOUT);
+ ret = -ETIMEDOUT;
+ break;
+ }
+--- 483,488 ----
+***************
+*** 447,454 ****
+ }
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ } else {
+- SET_ERRNO(-ret);
+- ret = NOTOK;
+ break;
+ }
+ }
+--- 492,497 ----
+***************
+*** 480,504 ****
+ machdep_gettimeofday(&current_time);
+ sleep_schedule(&current_time, timeout);
+
+ pthread_resched_resume(PS_FDW_WAIT);
+
+ /* We're awake */
+ pthread_sched_prevent();
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+- SET_ERRNO(ETIMEDOUT);
+ ret = -ETIMEDOUT;
+ break;
+ }
+ pthread_sched_resume();
+ } else {
+ pthread_resched_resume(PS_FDW_WAIT);
+ }
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ } else {
+- SET_ERRNO(-ret);
+- ret = NOTOK;
+ break;
+ }
+ }
+--- 523,548 ----
+ machdep_gettimeofday(&current_time);
+ sleep_schedule(&current_time, timeout);
+
++ SET_PF_AT_CANCEL_POINT(pthread_run);
+ pthread_resched_resume(PS_FDW_WAIT);
++ CLEAR_PF_AT_CANCEL_POINT(pthread_run);
+
+ /* We're awake */
+ pthread_sched_prevent();
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ ret = -ETIMEDOUT;
+ break;
+ }
+ pthread_sched_resume();
+ } else {
++ SET_PF_AT_CANCEL_POINT(pthread_run);
+ pthread_resched_resume(PS_FDW_WAIT);
++ CLEAR_PF_AT_CANCEL_POINT(pthread_run);
+ }
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ } else {
+ break;
+ }
+ }
+***************
+*** 537,543 ****
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+- SET_ERRNO(ETIMEDOUT);
+ ret = -ETIMEDOUT;
+ break;
+ }
+--- 581,586 ----
+***************
+*** 547,554 ****
+ }
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ } else {
+- SET_ERRNO(-ret);
+- ret = NOTOK;
+ break;
+ }
+ }
+--- 590,595 ----
+***************
+*** 662,668 ****
+ */
+ int create(const char *path, mode_t mode)
+ {
+! return creat (path, mode);
+ }
+
+ /* ==========================================================================
+--- 703,709 ----
+ */
+ int create(const char *path, mode_t mode)
+ {
+! return creat (path, mode);
+ }
+
+ /* ==========================================================================
+***************
+*** 672,678 ****
+
+ int creat(const char *path, mode_t mode)
+ {
+! return open (path, O_CREAT | O_TRUNC | O_WRONLY, mode);
+ }
+
+ /* ==========================================================================
+--- 713,719 ----
+
+ int creat(const char *path, mode_t mode)
+ {
+! return open (path, O_CREAT | O_TRUNC | O_WRONLY, mode);
+ }
+
+ /* ==========================================================================
+***************
+*** 1079,1090 ****
+ int bind(int fd, const struct sockaddr *name, int namelen)
+ {
+ /* Not much to do in bind */
+- semaphore *plock;
+ int ret;
+
+ if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
+ if ((ret = machdep_sys_bind(fd_table[fd]->fd.i, name, namelen)) < OK) {
+ SET_ERRNO(-ret);
+ }
+ fd_unlock(fd, FD_RDWR);
+ }
+--- 1120,1131 ----
+ int bind(int fd, const struct sockaddr *name, int namelen)
+ {
+ /* Not much to do in bind */
+ int ret;
+
+ if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
+ if ((ret = machdep_sys_bind(fd_table[fd]->fd.i, name, namelen)) < OK) {
+ SET_ERRNO(-ret);
++ ret = NOTOK;
+ }
+ fd_unlock(fd, FD_RDWR);
+ }
+***************
+*** 1100,1113 ****
+ */
+ int connect(int fd, const struct sockaddr *name, int namelen)
+ {
+! struct sockaddr tmpname;
+! int ret, tmpnamelen;
+
+! if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
+ if ((ret = machdep_sys_connect(fd_table[fd]->fd.i, name, namelen)) < OK) {
+ if (!(fd_table[fd]->flags & __FD_NONBLOCK) &&
+! ((ret == -EWOULDBLOCK) || (ret == -EINPROGRESS) ||
+! (ret == -EALREADY) || (ret == -EAGAIN))) {
+ pthread_sched_prevent();
+
+ /* queue pthread for a FDW_WAIT */
+--- 1141,1154 ----
+ */
+ int connect(int fd, const struct sockaddr *name, int namelen)
+ {
+! struct sockaddr tmpname;
+! int ret, tmpnamelen;
+
+! if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
+ if ((ret = machdep_sys_connect(fd_table[fd]->fd.i, name, namelen)) < OK) {
+ if (!(fd_table[fd]->flags & __FD_NONBLOCK) &&
+! ((ret == -EWOULDBLOCK) || (ret == -EINPROGRESS) ||
+! (ret == -EALREADY) || (ret == -EAGAIN))) {
+ pthread_sched_prevent();
+
+ /* queue pthread for a FDW_WAIT */
+***************
+*** 1121,1131 ****
+ tmpnamelen = sizeof(tmpname);
+ /* OK now lets see if it really worked */
+ if (((ret = machdep_sys_getpeername(fd_table[fd]->fd.i,
+! &tmpname, &tmpnamelen)) < OK) && (ret == -ENOTCONN)) {
+
+ /* Get the error, this function should not fail */
+ machdep_sys_getsockopt(fd_table[fd]->fd.i, SOL_SOCKET,
+! SO_ERROR, &pthread_run->error, &tmpnamelen);
+ }
+ } else {
+ SET_ERRNO(-ret);
+--- 1162,1180 ----
+ tmpnamelen = sizeof(tmpname);
+ /* OK now lets see if it really worked */
+ if (((ret = machdep_sys_getpeername(fd_table[fd]->fd.i,
+! &tmpname, &tmpnamelen)) < OK)
+! && (ret == -ENOTCONN)) {
+
+ /* Get the error, this function should not fail */
+ machdep_sys_getsockopt(fd_table[fd]->fd.i, SOL_SOCKET,
+! SO_ERROR, &ret, &tmpnamelen);
+! SET_ERRNO(-ret);
+! ret = NOTOK;
+! } else {
+! if( ret < 0 ) {
+! SET_ERRNO(-ret);
+! ret = NOTOK;
+! }
+ }
+ } else {
+ SET_ERRNO(-ret);
+***************
+*** 1133,1140 ****
+ }
+ }
+ fd_unlock(fd, FD_RDWR);
+! }
+! return(ret);
+ }
+
+ #endif
+--- 1182,1189 ----
+ }
+ }
+ fd_unlock(fd, FD_RDWR);
+! }
+! return(ret);
+ }
+
+ #endif
+***************
+*** 1164,1170 ****
+ } else {
+ fd_unlock(fd, FD_RDWR);
+ SET_ERRNO(-fd_kern);
+! return(fd_kern);
+ }
+ }
+ fd_unlock(fd, FD_RDWR);
+--- 1213,1219 ----
+ } else {
+ fd_unlock(fd, FD_RDWR);
+ SET_ERRNO(-fd_kern);
+! return(NOTOK);
+ }
+ }
+ fd_unlock(fd, FD_RDWR);
+***************
+*** 1198,1205 ****
+ int ret;
+
+ if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
+! ret = machdep_sys_listen(fd_table[fd]->fd.i, backlog);
+! if ((ret = machdep_sys_listen(fd_table[fd]->fd.i, backlog)) < OK) {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+ }
+--- 1247,1253 ----
+ int ret;
+
+ if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
+! if ((ret = machdep_sys_listen(fd_table[fd]->fd.i, backlog)) < OK) {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+ }
+***************
+*** 1246,1252 ****
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ SET_ERRNO(ETIMEDOUT);
+! ret = -ETIMEDOUT;
+ break;
+ }
+ pthread_sched_resume();
+--- 1294,1300 ----
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ SET_ERRNO(ETIMEDOUT);
+! ret = NOTOK;
+ break;
+ }
+ pthread_sched_resume();
+***************
+*** 1311,1317 ****
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ SET_ERRNO(ETIMEDOUT);
+! ret = -ETIMEDOUT;
+ break;
+ }
+ pthread_sched_resume();
+--- 1359,1365 ----
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ SET_ERRNO(ETIMEDOUT);
+! ret = NOTOK;
+ break;
+ }
+ pthread_sched_resume();
+***************
+*** 1405,1411 ****
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ SET_ERRNO(ETIMEDOUT);
+! ret = -ETIMEDOUT;
+ break;
+ }
+ pthread_sched_resume();
+--- 1453,1459 ----
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ SET_ERRNO(ETIMEDOUT);
+! ret = NOTOK;
+ break;
+ }
+ pthread_sched_resume();
+***************
+*** 1471,1477 ****
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ SET_ERRNO(ETIMEDOUT);
+! ret = -ETIMEDOUT;
+ break;
+ }
+ pthread_sched_resume();
+--- 1519,1525 ----
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ SET_ERRNO(ETIMEDOUT);
+! ret = NOTOK;
+ break;
+ }
+ pthread_sched_resume();
+***************
+*** 1536,1542 ****
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ SET_ERRNO(ETIMEDOUT);
+! ret = -ETIMEDOUT;
+ break;
+ }
+ pthread_sched_resume();
+--- 1584,1590 ----
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ SET_ERRNO(ETIMEDOUT);
+! ret = NOTOK;
+ break;
+ }
+ pthread_sched_resume();
+***************
+*** 1603,1609 ****
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ SET_ERRNO(ETIMEDOUT);
+! ret = -ETIMEDOUT;
+ break;
+ }
+ pthread_sched_resume();
+--- 1651,1657 ----
+ CLEAR_PF_DONE_EVENT(pthread_run);
+ pthread_sched_resume();
+ SET_ERRNO(ETIMEDOUT);
+! ret = NOTOK;
+ break;
+ }
+ pthread_sched_resume();
+***************
+*** 1734,1744 ****
+ */
+ int getsockopt(int fd, int level, int optname, void * optval, int * optlen)
+ {
+! int ret;
+
+! if ((ret = fd_lock(fd, FD_READ, NULL)) == OK) {
+ if ((ret = machdep_sys_getsockopt(fd_table[fd]->fd.i, level,
+! optname, optval, optlen)) < OK) {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+ }
+--- 1782,1792 ----
+ */
+ int getsockopt(int fd, int level, int optname, void * optval, int * optlen)
+ {
+! int ret;
+
+! if ((ret = fd_lock(fd, FD_READ, NULL)) == OK) {
+ if ((ret = machdep_sys_getsockopt(fd_table[fd]->fd.i, level,
+! optname, optval, optlen)) < OK) {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+ }
+***************
+*** 1756,1772 ****
+ */
+ int getsockname(int fd, struct sockaddr * name, int * naddrlen)
+ {
+! int ret;
+
+! if ((ret = fd_lock(fd, FD_READ, NULL)) == OK) {
+! if ((ret = machdep_sys_getsockname(fd_table[fd]->fd.i,
+! name, naddrlen)) < OK) {
+! SET_ERRNO(-ret);
+! ret = NOTOK;
+! }
+! fd_unlock(fd, FD_RDWR);
+! }
+! return ret;
+ }
+
+ #endif
+--- 1804,1820 ----
+ */
+ int getsockname(int fd, struct sockaddr * name, int * naddrlen)
+ {
+! int ret;
+
+! if ((ret = fd_lock(fd, FD_READ, NULL)) == OK) {
+! if ((ret = machdep_sys_getsockname(fd_table[fd]->fd.i,
+! name, naddrlen)) < OK) {
+! SET_ERRNO(-ret);
+! ret = NOTOK;
+! }
+! fd_unlock(fd, FD_RDWR);
+! }
+! return ret;
+ }
+
+ #endif
+***************
+*** 1778,1793 ****
+ */
+ int getpeername(int fd, struct sockaddr * peer, int * paddrlen)
+ {
+! int ret;
+
+! if ((ret = fd_lock(fd, FD_READ, NULL)) == OK) {
+! if ((ret = machdep_sys_getpeername(fd_table[fd]->fd.i,
+! peer, paddrlen)) < OK) {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+! }
+! fd_unlock(fd, FD_READ);
+! }
+ return ret;
+ }
+
+--- 1826,1841 ----
+ */
+ int getpeername(int fd, struct sockaddr * peer, int * paddrlen)
+ {
+! int ret;
+
+! if ((ret = fd_lock(fd, FD_READ, NULL)) == OK) {
+! if ((ret = machdep_sys_getpeername(fd_table[fd]->fd.i,
+! peer, paddrlen)) < OK) {
+ SET_ERRNO(-ret);
+ ret = NOTOK;
+! }
+! fd_unlock(fd, FD_READ);
+! }
+ return ret;
+ }
+
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/pthreads/pthread.c,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 pthread.c
+*** pthread.c 1995/12/13 05:53:01 1.1.1.1
+--- pthread.c 1996/10/01 21:42:01
+***************
+*** 129,134 ****
+--- 129,160 ----
+
+ }
+
++ /*----------------------------------------------------------------------
++ * Function: __pthread_is_valid
++ * Purpose: Scan the list of threads to see if a specified thread exists
++ * Args:
++ * pthread = The thread to scan for
++ * Returns:
++ * int = 1 if found, 0 if not
++ * Notes:
++ * The kernel is assumed to be locked
++ *----------------------------------------------------------------------*/
++ int
++ __pthread_is_valid( pthread_t pthread )
++ {
++ int rtn = 0; /* Assume not found */
++ pthread_t t;
++
++ for( t = pthread_link_list; t; t = t->pll ) {
++ if( t == pthread ) {
++ rtn = 1; /* Found it */
++ break;
++ }
++ }
++
++ return rtn;
++ }
++
+ /* ==========================================================================
+ * __pthread_free()
+ */
+***************
+*** 242,247 ****
+--- 268,277 ----
+ new_thread->next = NULL;
+ new_thread->flags = 0;
+
++ /* PTHREADS spec says we start with cancellability on and deferred */
++ SET_PF_CANCEL_STATE(new_thread, PTHREAD_CANCEL_ENABLE);
++ SET_PF_CANCEL_TYPE(new_thread, PTHREAD_CANCEL_DEFERRED);
++
+ new_thread->error_p = NULL;
+ new_thread->sll = NULL;
+
+***************
+*** 261,269 ****
+ }
+ return(retval);
+ }
+-
+- /* ==========================================================================
+- * pthread_cancel()
+- *
+- * This routine will also require a sig_prevent/sig_check_and_resume()
+- */
+--- 291,293 ----
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/pthreads/pthread_init.c,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 pthread_init.c
+*** pthread_init.c 1996/03/13 04:33:10 1.1.1.1
+--- pthread_init.c 1996/10/01 21:43:59
+***************
+*** 92,99 ****
+ pthread_initial->next = NULL;
+ pthread_initial->flags = 0;
+ pthread_initial->pll = NULL;
+- pthread_initial->flags = 0;
+ pthread_initial->sll = NULL;
+
+ /* Ugly errno hack */
+ pthread_initial->error_p = &errno;
+--- 92,103 ----
+ pthread_initial->next = NULL;
+ pthread_initial->flags = 0;
+ pthread_initial->pll = NULL;
+ pthread_initial->sll = NULL;
++
++ /* PTHREADS spec says we start with cancellability on and deferred */
++ SET_PF_CANCEL_STATE(pthread_initial, PTHREAD_CANCEL_ENABLE);
++ SET_PF_CANCEL_TYPE(pthread_initial, PTHREAD_CANCEL_DEFERRED);
++
+
+ /* Ugly errno hack */
+ pthread_initial->error_p = &errno;
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/pthreads/pthread_join.c,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 pthread_join.c
+*** pthread_join.c 1995/12/13 05:53:07 1.1.1.1
+--- pthread_join.c 1996/10/02 16:54:36
+***************
+*** 42,47 ****
+--- 42,49 ----
+ #include <pthread.h>
+ #include <errno.h>
+
++ static int testDeadlock( struct pthread_queue *queue, pthread_t target );
++
+ /* ==========================================================================
+ * pthread_join()
+ */
+***************
+*** 51,56 ****
+--- 53,64 ----
+
+ pthread_sched_prevent();
+
++ /* Ensure they gave us a legal pthread pointer */
++ if( ! __pthread_is_valid( pthread ) ) {
++ pthread_sched_resume();
++ return(EINVAL);
++ }
++
+ /* Check that thread isn't detached already */
+ if (pthread->attr.flags & PTHREAD_DETACHED) {
+ pthread_sched_resume();
+***************
+*** 62,81 ****
+ * Note: This must happen after checking detached state.
+ */
+ if (pthread_queue_remove(&pthread_dead_queue, pthread) != OK) {
+! pthread_queue_enq(&(pthread->join_queue), pthread_run);
+! pthread_resched_resume(PS_JOIN);
+! pthread_sched_prevent();
+!
+! if (pthread_queue_remove(&pthread_dead_queue, pthread) == OK) {
+! pthread_queue_enq(&pthread_alloc_queue, pthread);
+! pthread->attr.flags |= PTHREAD_DETACHED;
+! pthread->state = PS_UNALLOCED;
+! if (thread_return) {
+! *thread_return = pthread->ret;
+! }
+! ret = OK;
+ } else {
+! ret = ESRCH;
+ }
+ } else {
+ /* Just get the return value and detach the thread */
+--- 70,98 ----
+ * Note: This must happen after checking detached state.
+ */
+ if (pthread_queue_remove(&pthread_dead_queue, pthread) != OK) {
+!
+! /* Before we pend on the join, ensure there is no dead lock */
+!
+! if( testDeadlock( &pthread_run->join_queue, pthread ) == NOTOK ) {
+! ret = EDEADLK;
+ } else {
+! pthread_queue_enq(&(pthread->join_queue), pthread_run);
+! SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
+! pthread_resched_resume(PS_JOIN);
+! CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
+! pthread_sched_prevent();
+!
+! if (pthread_queue_remove(&pthread_dead_queue, pthread) == OK) {
+! pthread_queue_enq(&pthread_alloc_queue, pthread);
+! pthread->attr.flags |= PTHREAD_DETACHED;
+! pthread->state = PS_UNALLOCED;
+! if (thread_return) {
+! *thread_return = pthread->ret;
+! }
+! ret = OK;
+! } else {
+! ret = ESRCH;
+! }
+ }
+ } else {
+ /* Just get the return value and detach the thread */
+***************
+*** 89,92 ****
+--- 106,139 ----
+ }
+ pthread_sched_resume();
+ return(ret);
++ }
++
++ /*----------------------------------------------------------------------
++ * Function: testDeadlock
++ * Purpose: recursive queue walk to check for deadlocks
++ * Args:
++ * queue = the queue to walk
++ * pthread = target to scan for
++ * Returns:
++ * OK = no deadlock, NOTOK = deadlock
++ * Notes:
++ *----------------------------------------------------------------------*/
++ static int
++ testDeadlock( struct pthread_queue *queue, pthread_t target )
++ {
++ pthread_t t;
++
++ if( queue == NULL )
++ return OK; /* Empty queue, obviously ok */
++
++ for( t = queue->q_next; t; t = t->next ) {
++ if( t == target )
++ return NOTOK; /* bang, your dead */
++
++ if( testDeadlock( &t->join_queue, target ) == NOTOK ) {
++ return NOTOK;
++ }
++ }
++
++ return OK; /* No deadlock */
+ }
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/pthreads/select.c,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 select.c
+*** select.c 1996/03/05 08:29:14 1.1.1.1
+--- select.c 1996/10/02 16:56:27
+***************
+*** 56,220 ****
+ int select(int numfds, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timeval *timeout)
+ {
+! fd_set real_exceptfds, real_readfds, real_writefds; /* mapped fd_sets */
+! fd_set * real_readfds_p, * real_writefds_p, * real_exceptfds_p;
+! fd_set read_locks, write_locks, rdwr_locks;
+! struct timespec timeout_time, current_time;
+! struct timeval zero_timeout = { 0, 0 };
+! int i, j, ret = 0, got_all_locks = 1;
+! struct pthread_select_data data;
+!
+! if (numfds > dtablesize) {
+! numfds = dtablesize;
+! }
+!
+! data.nfds = 0;
+! FD_ZERO(&data.readfds);
+! FD_ZERO(&data.writefds);
+! FD_ZERO(&data.exceptfds);
+
+! /* Do this first */
+! if (timeout) {
+ machdep_gettimeofday(&current_time);
+! timeout_time.tv_sec = current_time.tv_sec + timeout->tv_sec;
+! if ((timeout_time.tv_nsec = current_time.tv_nsec +
+! (timeout->tv_usec * 1000)) > 1000000000) {
+! timeout_time.tv_nsec -= 1000000000;
+! timeout_time.tv_sec++;
+! }
+! }
+!
+! FD_ZERO(&read_locks);
+! FD_ZERO(&write_locks);
+! FD_ZERO(&rdwr_locks);
+! FD_ZERO(&real_readfds);
+! FD_ZERO(&real_writefds);
+! FD_ZERO(&real_exceptfds);
+!
+! /* lock readfds */
+! if (readfds || writefds || exceptfds) {
+! for (i = 0; i < numfds; i++) {
+! if ((readfds && (FD_ISSET(i, readfds))) ||
+! (exceptfds && FD_ISSET(i, exceptfds))) {
+! if (writefds && FD_ISSET(i ,writefds)) {
+! if ((ret = fd_lock(i, FD_RDWR, NULL)) != OK) {
+! got_all_locks = 0;
+! break;
+! }
+! FD_SET(i, &rdwr_locks);
+! FD_SET(fd_table[i]->fd.i,&real_writefds);
+! } else {
+! if ((ret = fd_lock(i, FD_READ, NULL)) != OK) {
+! got_all_locks = 0;
+! break;
+! }
+! FD_SET(i, &read_locks);
+! }
+! if (readfds && FD_ISSET(i,readfds)) {
+! FD_SET(fd_table[i]->fd.i, &real_readfds);
+! }
+! if (exceptfds && FD_ISSET(i,exceptfds)) {
+! FD_SET(fd_table[i]->fd.i, &real_exceptfds);
+! }
+! if (fd_table[i]->fd.i >= data.nfds) {
+! data.nfds = fd_table[i]->fd.i + 1;
+! }
+! } else {
+! if (writefds && FD_ISSET(i, writefds)) {
+! if ((ret = fd_lock(i, FD_WRITE, NULL)) != OK) {
+! got_all_locks = 0;
+! break;
+! }
+! FD_SET(i, &write_locks);
+! FD_SET(fd_table[i]->fd.i,&real_writefds);
+! }
+! if (fd_table[i]->fd.i >= data.nfds) {
+! data.nfds = fd_table[i]->fd.i + 1;
+! }
+! }
+! }
+! }
+!
+! if (got_all_locks) {
+!
+! memcpy(&data.readfds,&real_readfds,sizeof(fd_set));
+! memcpy(&data.writefds,&real_writefds,sizeof(fd_set));
+! memcpy(&data.exceptfds,&real_exceptfds,sizeof(fd_set));
+!
+! real_readfds_p = (readfds == NULL) ? NULL : &real_readfds;
+! real_writefds_p = (writefds == NULL) ? NULL : &real_writefds;
+! real_exceptfds_p = (exceptfds == NULL) ? NULL : &real_exceptfds;
+!
+! if ((ret = machdep_sys_select(data.nfds, real_readfds_p,
+! real_writefds_p, real_exceptfds_p, &zero_timeout)) == OK) {
+!
+! pthread_sched_prevent();
+!
+! real_exceptfds_p = (exceptfds == NULL) ? NULL : &data.exceptfds;
+! real_writefds_p = (writefds == NULL) ? NULL : &data.writefds;
+! real_readfds_p = (readfds == NULL) ? NULL : &data.readfds;
+!
+! pthread_queue_enq(&fd_wait_select, pthread_run);
+! pthread_run->data.select_data = &data;
+! SET_PF_WAIT_EVENT(pthread_run);
+!
+! if (timeout) {
+! machdep_gettimeofday(&current_time);
+! sleep_schedule(&current_time, &timeout_time);
+!
+! pthread_resched_resume(PS_SELECT_WAIT);
+!
+! /* We're awake */
+! CLEAR_PF_DONE_EVENT(pthread_run);
+! if (sleep_cancel(pthread_run) == NOTOK) {
+! ret = OK;
+! } else {
+! ret = data.nfds;
+! }
+! } else {
+! pthread_resched_resume(PS_SELECT_WAIT);
+! CLEAR_PF_DONE_EVENT(pthread_run);
+! ret = data.nfds; /* XXX ??? snl */
+! }
+! } else if (ret < 0) {
+! SET_ERRNO(-ret);
+! ret = NOTOK;
+! }
+! }
+!
+! /* clean up the locks */
+! for (i = 0; i < numfds; i++)
+! if (FD_ISSET(i,&read_locks)) fd_unlock(i,FD_READ);
+! for (i = 0; i < numfds; i++)
+! if (FD_ISSET(i,&rdwr_locks)) fd_unlock(i,FD_RDWR);
+! for (i = 0; i < numfds; i++)
+! if (FD_ISSET(i,&write_locks)) fd_unlock(i,FD_WRITE);
+!
+! if (ret > 0) {
+! if (readfds != NULL) {
+! for (i = 0; i < numfds; i++) {
+! if (! (FD_ISSET(i,readfds) &&
+! FD_ISSET(fd_table[i]->fd.i,real_readfds_p)))
+! FD_CLR(i,readfds);
+! }
+! }
+! if (writefds != NULL) {
+! for (i = 0; i < numfds; i++)
+! if (! (FD_ISSET(i,writefds) &&
+! FD_ISSET(fd_table[i]->fd.i,real_writefds_p)))
+! FD_CLR(i,writefds);
+! }
+! if (exceptfds != NULL) {
+! for (i = 0; i < numfds; i++)
+! if (! (FD_ISSET(i,exceptfds) &&
+! FD_ISSET(fd_table[i]->fd.i,real_exceptfds_p)))
+! FD_CLR(i,exceptfds);
+! }
+! } else {
+! if (exceptfds != NULL) FD_ZERO(exceptfds);
+! if (writefds != NULL) FD_ZERO(writefds);
+! if (readfds != NULL) FD_ZERO(readfds);
+ }
+
+! return(ret);
+ }
+--- 56,223 ----
+ int select(int numfds, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timeval *timeout)
+ {
+! fd_set real_exceptfds, real_readfds, real_writefds; /* mapped fd_sets */
+! fd_set * real_readfds_p, * real_writefds_p, * real_exceptfds_p;
+! fd_set read_locks, write_locks, rdwr_locks;
+! struct timespec timeout_time, current_time;
+! struct timeval zero_timeout = { 0, 0 };
+! int i, j, ret = 0, got_all_locks = 1;
+! struct pthread_select_data data;
+!
+! if (numfds > dtablesize) {
+! numfds = dtablesize;
+! }
+!
+! data.nfds = 0;
+! FD_ZERO(&data.readfds);
+! FD_ZERO(&data.writefds);
+! FD_ZERO(&data.exceptfds);
+!
+! /* Do this first */
+! if (timeout) {
+! machdep_gettimeofday(&current_time);
+! timeout_time.tv_sec = current_time.tv_sec + timeout->tv_sec;
+! if ((timeout_time.tv_nsec = current_time.tv_nsec +
+! (timeout->tv_usec * 1000)) > 1000000000) {
+! timeout_time.tv_nsec -= 1000000000;
+! timeout_time.tv_sec++;
+! }
+! }
+!
+! FD_ZERO(&read_locks);
+! FD_ZERO(&write_locks);
+! FD_ZERO(&rdwr_locks);
+! FD_ZERO(&real_readfds);
+! FD_ZERO(&real_writefds);
+! FD_ZERO(&real_exceptfds);
+!
+! /* lock readfds */
+! if (readfds || writefds || exceptfds) {
+! for (i = 0; i < numfds; i++) {
+! if ((readfds && (FD_ISSET(i, readfds))) ||
+! (exceptfds && FD_ISSET(i, exceptfds))) {
+! if (writefds && FD_ISSET(i ,writefds)) {
+! if ((ret = fd_lock(i, FD_RDWR, NULL)) != OK) {
+! got_all_locks = 0;
+! break;
+! }
+! FD_SET(i, &rdwr_locks);
+! FD_SET(fd_table[i]->fd.i,&real_writefds);
+! } else {
+! if ((ret = fd_lock(i, FD_READ, NULL)) != OK) {
+! got_all_locks = 0;
+! break;
+! }
+! FD_SET(i, &read_locks);
+! }
+! if (readfds && FD_ISSET(i,readfds)) {
+! FD_SET(fd_table[i]->fd.i, &real_readfds);
+! }
+! if (exceptfds && FD_ISSET(i,exceptfds)) {
+! FD_SET(fd_table[i]->fd.i, &real_exceptfds);
+! }
+! if (fd_table[i]->fd.i >= data.nfds) {
+! data.nfds = fd_table[i]->fd.i + 1;
+! }
+! } else {
+! if (writefds && FD_ISSET(i, writefds)) {
+! if ((ret = fd_lock(i, FD_WRITE, NULL)) != OK) {
+! got_all_locks = 0;
+! break;
+! }
+! FD_SET(i, &write_locks);
+! FD_SET(fd_table[i]->fd.i,&real_writefds);
+! if (fd_table[i]->fd.i >= data.nfds) {
+! data.nfds = fd_table[i]->fd.i + 1;
+! }
+! }
+! }
+! }
+! }
+!
+! if (got_all_locks) {
+! memcpy(&data.readfds,&real_readfds,sizeof(fd_set));
+! memcpy(&data.writefds,&real_writefds,sizeof(fd_set));
+! memcpy(&data.exceptfds,&real_exceptfds,sizeof(fd_set));
+!
+! real_readfds_p = (readfds == NULL) ? NULL : &real_readfds;
+! real_writefds_p = (writefds == NULL) ? NULL : &real_writefds;
+! real_exceptfds_p = (exceptfds == NULL) ? NULL : &real_exceptfds;
+!
+! if ((ret = machdep_sys_select(data.nfds, real_readfds_p,
+! real_writefds_p, real_exceptfds_p,
+! &zero_timeout)) == OK) {
+! pthread_sched_prevent();
+!
+! real_exceptfds_p = (exceptfds == NULL) ? NULL : &data.exceptfds;
+! real_writefds_p = (writefds == NULL) ? NULL : &data.writefds;
+! real_readfds_p = (readfds == NULL) ? NULL : &data.readfds;
+!
+! pthread_queue_enq(&fd_wait_select, pthread_run);
+! pthread_run->data.select_data = &data;
+! SET_PF_WAIT_EVENT(pthread_run);
+
+! if (timeout) {
+ machdep_gettimeofday(&current_time);
+! sleep_schedule(&current_time, &timeout_time);
+!
+! SET_PF_AT_CANCEL_POINT(pthread_run);
+! pthread_resched_resume(PS_SELECT_WAIT);
+! CLEAR_PF_AT_CANCEL_POINT(pthread_run);
+!
+! /* We're awake */
+! CLEAR_PF_DONE_EVENT(pthread_run);
+! if (sleep_cancel(pthread_run) == NOTOK) {
+! ret = OK;
+! } else {
+! ret = data.nfds;
+! }
+! } else {
+! SET_PF_AT_CANCEL_POINT(pthread_run);
+! pthread_resched_resume(PS_SELECT_WAIT);
+! CLEAR_PF_AT_CANCEL_POINT(pthread_run);
+! CLEAR_PF_DONE_EVENT(pthread_run);
+! ret = data.nfds; /* XXX ??? snl */
+! }
+! } else if (ret < 0) {
+! SET_ERRNO(-ret);
+! ret = NOTOK;
+! }
+! }
+!
+! /* clean up the locks */
+! for (i = 0; i < numfds; i++)
+! if (FD_ISSET(i,&read_locks)) fd_unlock(i,FD_READ);
+! for (i = 0; i < numfds; i++)
+! if (FD_ISSET(i,&rdwr_locks)) fd_unlock(i,FD_RDWR);
+! for (i = 0; i < numfds; i++)
+! if (FD_ISSET(i,&write_locks)) fd_unlock(i,FD_WRITE);
+!
+! if (ret > 0) {
+! if (readfds != NULL) {
+! for (i = 0; i < numfds; i++) {
+! if (! (FD_ISSET(i,readfds) &&
+! FD_ISSET(fd_table[i]->fd.i,real_readfds_p)))
+! FD_CLR(i,readfds);
+! }
+! }
+! if (writefds != NULL) {
+! for (i = 0; i < numfds; i++)
+! if (! (FD_ISSET(i,writefds) &&
+! FD_ISSET(fd_table[i]->fd.i,real_writefds_p)))
+! FD_CLR(i,writefds);
+! }
+! if (exceptfds != NULL) {
+! for (i = 0; i < numfds; i++)
+! if (! (FD_ISSET(i,exceptfds) &&
+! FD_ISSET(fd_table[i]->fd.i,real_exceptfds_p)))
+! FD_CLR(i,exceptfds);
+ }
++ } else {
++ if (exceptfds != NULL) FD_ZERO(exceptfds);
++ if (writefds != NULL) FD_ZERO(writefds);
++ if (readfds != NULL) FD_ZERO(readfds);
++ }
+
+! return(ret);
+ }
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/pthreads/sig.c,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 sig.c
+*** sig.c 1996/03/13 04:33:13 1.1.1.1
+--- sig.c 1996/10/03 01:07:54
+***************
+*** 301,307 ****
+--- 301,310 ----
+ pthread_run->data.sigwait = set;
+ pthread_run->ret = sig;
+
++ SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
+ pthread_resched_resume(PS_SIGWAIT);
++ CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
++
+ return(OK);
+ }
+
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/pthreads/signal.c,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 signal.c
+*** signal.c 1996/03/13 04:33:17 1.1.1.1
+--- signal.c 1996/10/03 17:30:16
+***************
+*** 72,77 ****
+--- 72,78 ----
+
+ static void sig_handler(int signal);
+ static void set_thread_timer();
++ static void __cleanup_after_resume( void );
+ void sig_prevent(void);
+ void sig_resume(void);
+
+***************
+*** 482,502 ****
+ }
+ }
+
+! /* Only bother if we are truly unlocking the kernel */
+! while (!(--pthread_kernel_lock)) {
+! if (sig_to_process) {
+! /* if (SIG_ANY(sig_to_process)) { */
+! pthread_kernel_lock++;
+! sig_handler(0);
+! continue;
+! }
+! if (pthread_run && pthread_run->sigcount) {
+! pthread_kernel_lock++;
+! pthread_sig_process();
+! continue;
+! }
+! break;
+! }
+ }
+
+ /* ==========================================================================
+--- 483,489 ----
+ }
+ }
+
+! __cleanup_after_resume();
+ }
+
+ /* ==========================================================================
+***************
+*** 508,530 ****
+ void pthread_resched_resume(enum pthread_state state)
+ {
+ pthread_run->state = state;
+- sig_handler(SIGVTALRM);
+
+! /* Only bother if we are truely unlocking the kernel */
+! while (!(--pthread_kernel_lock)) {
+! if (sig_to_process) {
+! /* if (SIG_ANY(sig_to_process)) { */
+! pthread_kernel_lock++;
+! sig_handler(0);
+! continue;
+! }
+! if (pthread_run && pthread_run->sigcount) {
+! pthread_kernel_lock++;
+! pthread_sig_process();
+! continue;
+! }
+! break;
+ }
+ }
+
+ /* ==========================================================================
+--- 495,523 ----
+ void pthread_resched_resume(enum pthread_state state)
+ {
+ pthread_run->state = state;
+
+! /* Since we are about to block this thread, lets see if we are
+! * at a cancel point and if we've been cancelled.
+! * Avoid cancelling dead or unalloced threads.
+! */
+! if( ! TEST_PF_RUNNING_TO_CANCEL(pthread_run) &&
+! TEST_PTHREAD_IS_CANCELLABLE(pthread_run) &&
+! state != PS_DEAD && state != PS_UNALLOCED ) {
+!
+! /* Set this flag to avoid recursively calling pthread_exit */
+! /* We have to set this flag here because we will unlock the
+! * kernel prior to calling pthread_cancel_internal.
+! */
+! SET_PF_RUNNING_TO_CANCEL(pthread_run);
+!
+! pthread_run->old_state = state; /* unlock needs this data */
+! pthread_sched_resume(); /* Unlock kernel before cancel */
+! pthread_cancel_internal( 1 ); /* free locks and exit */
+ }
++
++ sig_handler(SIGVTALRM);
++
++ __cleanup_after_resume();
+ }
+
+ /* ==========================================================================
+***************
+*** 532,537 ****
+--- 525,543 ----
+ */
+ void pthread_sched_resume()
+ {
++ __cleanup_after_resume();
++ }
++
++ /*----------------------------------------------------------------------
++ * Function: __cleanup_after_resume
++ * Purpose: cleanup kernel locks after a resume
++ * Args: void
++ * Returns: void
++ * Notes:
++ *----------------------------------------------------------------------*/
++ static void
++ __cleanup_after_resume( void )
++ {
+ /* Only bother if we are truely unlocking the kernel */
+ while (!(--pthread_kernel_lock)) {
+ /* if (SIG_ANY(sig_to_process)) { */
+***************
+*** 546,551 ****
+--- 552,568 ----
+ continue;
+ }
+ break;
++ }
++
++ if( pthread_run == NULL )
++ return; /* Must be during init processing */
++
++ /* Test for cancel that should be handled now */
++
++ if( ! TEST_PF_RUNNING_TO_CANCEL(pthread_run) &&
++ TEST_PTHREAD_IS_CANCELLABLE(pthread_run) ) {
++ /* Kernel is already unlocked */
++ pthread_cancel_internal( 1 ); /* free locks and exit */
+ }
+ }
+
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/pthreads/sleep.c,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 sleep.c
+*** sleep.c 1996/03/11 08:33:32 1.1.1.1
+--- sleep.c 1996/10/03 01:14:58
+***************
+*** 249,255 ****
+--- 249,257 ----
+
+ /* Reschedule thread */
+ SET_PF_WAIT_EVENT(pthread_run);
++ SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
+ pthread_resched_resume(PS_SLEEP_WAIT);
++ CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
+ CLEAR_PF_DONE_EVENT(pthread_run);
+
+ /* Return actual time slept */
+***************
+*** 332,338 ****
+ current_time.tv_sec++;
+ }
+ machdep_start_timer(&(current_time),
+! &(pthread_sleep->wakeup_time));
+ }
+ } else {
+ for (pthread_last = pthread_sleep; pthread_last;
+--- 334,340 ----
+ current_time.tv_sec++;
+ }
+ machdep_start_timer(&(current_time),
+! &(pthread_sleep->wakeup_time));
+ }
+ } else {
+ for (pthread_last = pthread_sleep; pthread_last;
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/pthreads/stat.c,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 stat.c
+*** stat.c 1995/09/21 02:36:05 1.1.1.1
+--- stat.c 1996/06/04 19:17:33
+***************
+*** 43,48 ****
+--- 43,49 ----
+ #include <errno.h>
+
+ struct stat;
++ struct statfs;
+
+ /* ==========================================================================
+ * fstat()
+***************
+*** 91,95 ****
+--- 92,115 ----
+ }
+ return(ret);
+
++ }
++
++ /* ==========================================================================
++ * fstatfs()
++ *
++ * Might want to indirect this.
++ */
++ int fstatfs(int fd, struct statfs *buf)
++ {
++ int ret;
++
++ if ((ret = fd_lock(fd, FD_READ, NULL)) == OK) {
++ if ((ret = machdep_sys_fstatfs(fd_table[fd]->fd.i, buf)) < OK) {
++ SET_ERRNO(-ret);
++ ret = NOTOK;
++ }
++ fd_unlock(fd, FD_READ);
++ }
++ return(ret);
+ }
+
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/pthreads/wait.c,v retrieving revision 1.1.1.1
+diff -c -r1.1.1.1 wait.c
+*** wait.c 1995/02/21 08:07:24 1.1.1.1
+--- wait.c 1996/10/03 01:20:02
+***************
+*** 103,109 ****
+--- 103,111 ----
+ pthread_queue_enq(&wait_queue, pthread_run);
+
+ /* reschedule unlocks scheduler */
++ SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
+ pthread_resched_resume(PS_WAIT_WAIT);
++ CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
+
+ pthread_sched_prevent();
+ }
+***************
+*** 126,132 ****
+--- 128,136 ----
+ pthread_queue_enq(&wait_queue, pthread_run);
+
+ /* reschedule unlocks scheduler */
++ SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
+ pthread_resched_resume(PS_WAIT_WAIT);
++ CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
+
+ pthread_sched_prevent();
+ }
+<pre><font size=-1>
diff --git a/lib/libpthread/patches/Streepy2.html b/lib/libpthread/patches/Streepy2.html
new file mode 100755
index 00000000000..80d44d6440c
--- /dev/null
+++ b/lib/libpthread/patches/Streepy2.html
@@ -0,0 +1,93 @@
+<html>
+<head>
+ <title>Diffs on diffs :-) by Larry V. Streepy, Jr.</title>
+ <base target=_top>
+ <meta name="GENERATOR" content="FindMail Communications">
+ <meta name="Date" content="Monday, October 07, 1996 02:03 PM PST">
+ <meta name="Author" content="Larry V. Streepy, Jr.">
+</head>
+<body background="/gifs/betafm.gif" bgcolor="#ffffff" text="#000000" link="#0000ee" vlink="#ff0000" alink="#000099">
+<h3>Diffs on diffs :-)</h3>
+Larry V. Streepy, Jr. (<a href="mailto.html?mid=2079859748&num=398" target="_top">@healthcare.com</a>)<br>Monday, October 07, 1996 02:03 PM PST<br>
+<p>
+This is a multi-part message in MIME format.<p>
+--------------65BE18E23639BCDD7BE55F7F <br>
+Content-Type: text/plain; charset=us-ascii <br>
+Content-Transfer-Encoding: 7bit<p>
+Unfortunately, there are a couple of bugs in my pthread_cancel support (no, say it isn't so :-)<p>
+Oh well, I cam across a couple of cases that I missed in my testing last week. Here are the bugs:<p>
+1. If a thread calls pthread_testcancel during it's cleanup processing after being cancelled, the pthread kernel would hang.<p>
+2. I didn't realize that threads in PS_SLEEP_WAIT state are *NOT* on any queue, they are handled using a linked list. So, when cancelling a thread that was sleeping, a PANIC() I put in possiblymakeRunnable would go off.<p>
+Both of these are fixed. The diffs are attached.<br>
+-- <br>
+Larry V. Streepy, Jr. <br>
+Chief Technical Officer, Healthcare Communications, Inc. mailto:<a href="mailto.html?mid=2079859748&num=398" target="_top">@healthcare.com</a> <br>
+(214) 851-7033 (Dallas Main #) <br>
+(970) 626-5028 (My office #) (970) 626-4425 (Fax)<p>
+--------------65BE18E23639BCDD7BE55F7F <br>
+Content-Type: text/plain; charset=us-ascii; name=&#34;cancel.diffs&#34; Content-Transfer-Encoding: 7bit <br>
+Content-Disposition: inline; filename=&#34;cancel.diffs&#34;<p>
+Index: pthread_cancel.c<br>
+=================================================================== RCS file: /usr/cvssrc/pthreads-1_60_beta5/pthreads/pthread_cancel.c,v retrieving revision 1.1 <br>
+diff -c -r1.1 pthread_cancel.c<br>
+*** pthread_cancel.c 1996/10/06 00:31:27 1.1<br>
+--- pthread_cancel.c 1996/10/07 18:33:27<br>
+***************<br>
+*** 187,192 ****<br>
+--- 187,197 ----<br>
+ return; /* Can't be cancelled */<br>
+ }<br>
+ <br>
++ /* Ensure that we aren't in the process of exiting already */<br>
++ if( TEST_PF_RUNNING_TO_CANCEL(pthread_run) ) {<br>
++ return;<br>
++ }<br>
++ <br>
+ /* See if we have been cancelled */<br>
+ if( TEST_PF_CANCELLED(pthread_run) ) {<br>
+ /* Set this flag to avoid recursively calling pthread_exit */<br>
+***************<br>
+*** 266,277 ****<br>
+ if( pthread-&gt;state == PS_RUNNING )<br>
+ return; /* will happen at context switch */<br>
+ <br>
+! /* Otherwise, we need to take it off the queue and make it runnable */<br>
+! if( pthread-&gt;queue == NULL ) {<br>
+! PANIC(); /* Must be on a queue */<br>
+! }<br>
+ <br>
+- pthread_queue_remove(pthread-&gt;queue, pthread);<br>
+ pthread_prio_queue_enq(pthread_current_prio_queue, pthread);<br>
+ pthread-&gt;old_state = pthread-&gt;state;<br>
+ pthread-&gt;state = PS_RUNNING;<br>
+--- 271,291 ----<br>
+ if( pthread-&gt;state == PS_RUNNING )<br>
+ return; /* will happen at context switch */<br>
+ <br>
+! /* If the thread is sleeping, the it isn't on a queue. */<br>
+! if( pthread-&gt;state == PS_SLEEP_WAIT ) {<br>
+! sleep_cancel( pthread ); /* Remove from sleep list */<br>
+! } else {<br>
+! /* Otherwise, we need to take it off the queue and make it runnable */<br>
+! <br>
+! if( pthread-&gt;queue == NULL ) {<br>
+! PANIC(); /* Must be on a queue */<br>
+! }<br>
+! <br>
+! pthread_queue_remove(pthread-&gt;queue, pthread);<br>
+! }<br>
+! <br>
+! /* And make it runnable */<br>
+ <br>
+ pthread_prio_queue_enq(pthread_current_prio_queue, pthread);<br>
+ pthread-&gt;old_state = pthread-&gt;state;<br>
+ pthread-&gt;state = PS_RUNNING;<p>
+<pre><font size=-1>
+--------------65BE18E23639BCDD7BE55F7F--
+
+</pre><p></pre>
+<hr>
+<a href="http://www.findmail.com/" target="_top"><font size=-1>Powered by FindMail Communications</font><br></a>
+<br>Please email comments and suggestions to:<a href="/cgi-bin/comments.py" target="_top">comments@findmail.com</a>
+<br><font size=-3 color="#ffffff">xmlarchive</font>
+</body></html> \ No newline at end of file
diff --git a/lib/libpthread/patches/bill_lear b/lib/libpthread/patches/bill_lear
new file mode 100755
index 00000000000..f49b79c4272
--- /dev/null
+++ b/lib/libpthread/patches/bill_lear
@@ -0,0 +1,70 @@
+From rael@dejanews.com Wed Jan 29 06:06:14 1997
+X-VM-v5-Data: ([nil nil nil t nil nil nil nil nil]
+ ["1497" "Tue" "28" "January" "1997" "21:52:57" "-0600" "William S. Lear" "rael@dejanews.com" "<199701290352.VAA08678@homer.dejanews.com>" "53" "Patches for linux2.0" "^From:" nil nil "1" "1997012903:52:57" "Patches for linux2.0" nil nil]
+ nil)
+Received: from MIT.EDU (PACIFIC-CARRIER-ANNEX.MIT.EDU [18.69.0.28])
+ by analytik.analytikerna.se (8.8.4/8.8.4) with SMTP
+ id GAA23245 for <monty@analytikerna.se>; Wed, 29 Jan 1997 06:06:12 +0100 (MET)
+Received: from host-205-238-143-2.dejanews.com by MIT.EDU with SMTP
+ id AA25254; Tue, 28 Jan 97 22:53:08 EST
+Received: (from rael@localhost) by homer.dejanews.com (8.7.6/8.6.12) id VAA08678 for pthreads@mit.edu; Tue, 28 Jan 1997 21:52:57 -0600 (CST)
+Message-Id: <199701290352.VAA08678@homer.dejanews.com>
+Content-Length: 1496
+From: "William S. Lear" <rael@dejanews.com>
+To: pthreads@MIT.EDU
+Subject: Patches for linux2.0
+Date: Tue, 28 Jan 1997 21:52:57 -0600 (CST)
+
+
+The following are some patches I found necessary to run smoothly
+under linux2.0. The PTEST directory below refers to the original
+pthreads 1.60 beta 6 release. Of course, the '-O2' "fix" is not strictly
+needed.
+
+#============================================================
+# < pthreads-1_60beta6/config/configure
+# > PTEST/pthreads-1_60beta6/config/configure
+#------------------------------------------------------------
+642c642
+< CFLAGS="-g -O2"
+---
+> CFLAGS="-g -O"
+1104,1106d1103
+< cat >> confdefs.h <<EOF
+< #define BSD_TM 1
+< EOF
+
+# Diff for:
+#============================================================
+# < pthreads-1_60beta6/config/config.h.in
+# > PTEST/pthreads-1_60beta6/config/config.h.in
+#------------------------------------------------------------
+3,8d2
+< /* Does the OS have tm needing bsd'ish initialization? */
+< #undef BSD_TM
+<
+< /* Does the OS already support struct timespec */
+< #undef _OS_HAS_TIMESPEC
+<
+
+# Diff for:
+#============================================================
+# < pthreads-1_60beta6/gen/ctime.c
+# > PTEST/pthreads-1_60beta6/gen/ctime.c
+#------------------------------------------------------------
+49c49
+< #include "config.h"
+---
+>
+
+# Diff for:
+#============================================================
+# < pthreads-1_60beta6/include/math.h
+# > PTEST/pthreads-1_60beta6/include/math.h
+#------------------------------------------------------------
+54d53
+< double hypot __P((double, double));
+
+
+Bill Lear (rael@dejanews.com)
+
diff --git a/lib/libpthread/patches/chris_demetriou b/lib/libpthread/patches/chris_demetriou
new file mode 100755
index 00000000000..41d2dfefe82
--- /dev/null
+++ b/lib/libpthread/patches/chris_demetriou
@@ -0,0 +1,149 @@
+From cgd@pa.dec.com Fri Aug 15 04:22:21 1997
+X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
+ ["3982" "Thu" "14" "August" "1997" "18:57:55" "-0700" "Chris G. Demetriou" "cgd@pa.dec.com" "<15218.871610275@dnaunix.pa.dec.com>" "126" "patches to get 1.60 beta6 to build on ELF NetBSD/alpha systems" "^From:" nil nil "8" "1997081501:57:55" "patches to get 1.60 beta6 to build on ELF NetBSD/alpha systems" nil nil]
+ nil)
+Received: from MIT.EDU (PACIFIC-CARRIER-ANNEX.MIT.EDU [18.69.0.28])
+ by analytik.analytikerna.se (8.8.4/8.8.4) with SMTP
+ id EAA10207 for <monty@analytikerna.se>; Fri, 15 Aug 1997 04:22:19 +0200 (MET DST)
+Received: from mail2.digital.com by MIT.EDU with SMTP
+ id AA13470; Thu, 14 Aug 97 22:01:37 EDT
+Received: from dnaunix.pa.dec.com (dnaunix.pa.dec.com [16.4.208.21])
+ by mail2.digital.com (8.7.5/UNX 1.5/1.0/WV) with SMTP id SAA15366;
+ Thu, 14 Aug 1997 18:58:16 -0700 (PDT)
+Received: by dnaunix.pa.dec.com; id AA15044; Thu, 14 Aug 1997 18:57:56 -0700
+Message-Id: <15218.871610275@dnaunix.pa.dec.com>
+X-Mts: smtp
+Content-Length: 3981
+From: "Chris G. Demetriou" <cgd@pa.dec.com>
+Sender: cgd@pa.dec.com
+To: pthreads-bugs@MIT.EDU
+Cc: "Chris G. Demetriou" <cgd@pa.dec.com>, pthreads@MIT.EDU
+Subject: patches to get 1.60 beta6 to build on ELF NetBSD/alpha systems
+Date: Thu, 14 Aug 97 18:57:55 -0700
+
+Enclosed below are patches to pthreads 1.60 beta6 to build on
+current NetBSD/alpha systems (which use ELF). With these patches,
+pthreads passes 'make check.'
+
+As an aside, the test_switch test generates _340k_ of output ("a"
+for a while, then "ab" for a while) when run one the machine I was
+testing on. In my opinion, that's a ... bit excessive, especially
+since 'make check' has to be run interactively!
+
+
+
+chris
+============================================================================
+diff -rc pthreads-1_60_beta6.orig/config/Makefile.in pthreads-1_60_beta6/config/Makefile.in
+*** pthreads-1_60_beta6.orig/config/Makefile.in Thu Mar 21 20:29:54 1996
+--- pthreads-1_60_beta6/config/Makefile.in Thu Aug 14 17:56:55 1997
+***************
+*** 29,35 ****
+ # pathname for srcdir here, and live with it.
+ srcdir = $(srctop)
+
+! beforeinstall:: install-dirs
+
+ .include "${srcdir}/pthreads/Makefile.inc"
+ .include "${srcdir}/stdlib/Makefile.inc"
+--- 29,35 ----
+ # pathname for srcdir here, and live with it.
+ srcdir = $(srctop)
+
+! beforeinstall: install-dirs
+
+ .include "${srcdir}/pthreads/Makefile.inc"
+ .include "${srcdir}/stdlib/Makefile.inc"
+diff -rc pthreads-1_60_beta6.orig/machdep/syscall-alpha-netbsd-1.1.S pthreads-1_60_beta6/machdep/syscall-alpha-netbsd-1.1.S
+*** pthreads-1_60_beta6.orig/machdep/syscall-alpha-netbsd-1.1.S Wed Nov 13 13:03:28 1996
+--- pthreads-1_60_beta6/machdep/syscall-alpha-netbsd-1.1.S Thu Aug 14 18:03:27 1997
+***************
+*** 35,54 ****
+ .frame sp,0,ra ;\
+ ldiq v0, CONCAT(SYS_,x) ;\
+ CHMK() ;\
+! beq a3, 2f ;\
+! br gp, 1f ;\
+! 1: ;\
+ /* Load gp so we can find cerror to jump to. */;\
+ ldgp gp, 0(gp) ;\
+! jmp zero, machdep_cerror ;\
+! 2:
+
+ #define XSYSCALL(x) SYSCALL(x) ; RET ; .end CONCAT(machdep_sys_,x)
+
+ .globl machdep_cerror
+ machdep_cerror:
+! br t0, 1f
+! 1:
+ ldgp gp, 0(t0)
+ stl v0, errno
+ #if 0
+--- 35,54 ----
+ .frame sp,0,ra ;\
+ ldiq v0, CONCAT(SYS_,x) ;\
+ CHMK() ;\
+! beq a3, CONCAT(Lsys_noerr_,x) ;\
+! br gp, CONCAT(Lsys_err_,x) ;\
+! CONCAT(Lsys_err_,x): ;\
+ /* Load gp so we can find cerror to jump to. */;\
+ ldgp gp, 0(gp) ;\
+! jmp zero, machdep_cerror ;\
+! CONCAT(Lsys_noerr_,x):
+
+ #define XSYSCALL(x) SYSCALL(x) ; RET ; .end CONCAT(machdep_sys_,x)
+
+ .globl machdep_cerror
+ machdep_cerror:
+! br t0, Lmachdep_cerror_setgp
+! Lmachdep_cerror_setgp:
+ ldgp gp, 0(t0)
+ stl v0, errno
+ #if 0
+diff -rc pthreads-1_60_beta6.orig/machdep/syscall-template-alpha-netbsd-1.1.S pthreads-1_60_beta6/machdep/syscall-template-alpha-netbsd-1.1.S
+*** pthreads-1_60_beta6.orig/machdep/syscall-template-alpha-netbsd-1.1.S Mon Apr 22 23:15:42 1996
+--- pthreads-1_60_beta6/machdep/syscall-template-alpha-netbsd-1.1.S Thu Aug 14 17:58:14 1997
+***************
+*** 31,43 ****
+ .frame sp,0,ra ;\
+ ldiq v0, SYS_##x ;\
+ CHMK() ;\
+! beq a3, 2f ;\
+! br gp, 1f ;\
+! 1: ;\
+ /* Load gp so we can find cerror to jump to. */;\
+ ldgp gp, 0(gp) ;\
+! jmp zero, machdep_cerror ;\
+! 2:
+
+ #define SIMPLE_SYSCALL(x) SYSCALL(x) ; ret ; .end machdep_sys_##x
+
+--- 31,43 ----
+ .frame sp,0,ra ;\
+ ldiq v0, SYS_##x ;\
+ CHMK() ;\
+! beq a3, Lsys_noerr_##x ;\
+! br gp, Lsys_err_##x ;\
+! Lsys_err_##x: ;\
+ /* Load gp so we can find cerror to jump to. */;\
+ ldgp gp, 0(gp) ;\
+! jmp zero, machdep_cerror ;\
+! Lsys_noerr_##x:
+
+ #define SIMPLE_SYSCALL(x) SYSCALL(x) ; ret ; .end machdep_sys_##x
+
+diff -rc pthreads-1_60_beta6.orig/pthreads/process.c pthreads-1_60_beta6/pthreads/process.c
+*** pthreads-1_60_beta6.orig/pthreads/process.c Tue Nov 12 05:45:16 1996
+--- pthreads-1_60_beta6/pthreads/process.c Thu Aug 14 18:12:49 1997
+***************
+*** 40,45 ****
+--- 40,47 ----
+ #include <stdarg.h>
+ #include <unistd.h>
+
++ extern void *alloca();
++
+ #ifndef lint
+ static const char rcsid[] = "$Id: chris_demetriou,v 1.1 1998/07/21 13:22:22 peter Exp $";
+ #endif
+
diff --git a/lib/libpthread/patches/mevans b/lib/libpthread/patches/mevans
new file mode 100755
index 00000000000..d5ff2f27610
--- /dev/null
+++ b/lib/libpthread/patches/mevans
@@ -0,0 +1,642 @@
+=A0
+Attached are several patches for pthreads-1_60_beta6. The patches fall
+into 3 catagories:
+
+ 1. Crashes and hangs.
+ 2. Missing functionality (namely flock())
+ 3. Use of POSIX reentrant safe routines.
+
+Most of the patches contain a comment as to why the change was made.
+The one major exception is to fd_kern.c at line 257 (unpatched). The
+change to that line is to fix a "hang" that prevents threads for
+scheduling for an hour if there is no external I/O event.
+
+I also include patches that modify several functions to use POSIX
+reentrant safe routines. I know that MIT pthreads implements routine
+like gethostbyname in a thread safe manner, but we're pretty, um, anal
+about trying to keep our code as portable as possible. By excluding
+using routines that are not reentrant safe according to the PTHREAD
+safe, it's easy for us to stub out the unsafe routines and catch
+non-compliant code. I almost left these patches out, but I'm hoping
+they'll be adopted. :-)
+
+WARNING: None of the MIT pthreads routines that convert floats/doubles
+between their native forms and strings are thread safe! (i.e printf,
+sprintf, fprintf, atod, strtod, etc) I have replacements, but I need to
+check with the author of the replacements and my employer.
+
+Mark Evans
+
+------------69CDAAF52A3566916F8ED01A0
+Content-Disposition: inline; filename="pthreads-1_60_beta6.patch"
+Content-Type: text/plain; charset=us-ascii; name="pthreads-1_60_beta6.patch"
+Content-Transfer-Encoding: 7bit
+
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/config/config.h.in pthreads-1_60_beta6+/config/config.h.in
+*** pthreads-1_60_beta6/config/config.h.in Thu Mar 21 21:30:04 1996
+--- pthreads-1_60_beta6+/config/config.h.in Sat Mar 15 14:08:55 1997
+***************
+*** 137,142 ****
+--- 137,145 ----
+ /* Define if you have the syscall_ftruncate function. */
+ #undef HAVE_SYSCALL_FTRUNCATE
+
++ /* Define if you have the syscall_flock function. */
++ #undef HAVE_SYSCALL_FLOCK
++
+ /* Define if you have the syscall_getdents function. */
+ #undef HAVE_SYSCALL_GETDENTS
+
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/config/configure.in pthreads-1_60_beta6+/config/configure.in
+*** pthreads-1_60_beta6/config/configure.in Wed Nov 13 14:03:08 1996
+--- pthreads-1_60_beta6+/config/configure.in Sat Mar 15 14:08:55 1997
+***************
+*** 241,247 ****
+
+ PTHREADS_CHECK_SYSCALLS(open write read creat close fcntl lseek dup2 dup pipe
+ fchmod fchown execve fstat lstat link unlink chdir chown chmod stat
+! rename select getdtablesize ioctl ftruncate
+ dnl - signals
+ sigsuspend sigaction sigpause sigprocmask ksigaction
+ dnl - directory reading
+--- 241,247 ----
+
+ PTHREADS_CHECK_SYSCALLS(open write read creat close fcntl lseek dup2 dup pipe
+ fchmod fchown execve fstat lstat link unlink chdir chown chmod stat
+! rename select getdtablesize ioctl ftruncate flock
+ dnl - signals
+ sigsuspend sigaction sigpause sigprocmask ksigaction
+ dnl - directory reading
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/gen/directory.c pthreads-1_60_beta6+/gen/directory.c
+*** pthreads-1_60_beta6/gen/directory.c Sat May 20 10:55:34 1995
+--- pthreads-1_60_beta6+/gen/directory.c Sat Mar 15 14:08:55 1997
+***************
+*** 251,262 ****
+--- 251,266 ----
+ /*
+ * Seek to an entry in a directory.
+ * _seekdir is in telldir.c so that it can share opaque data structures.
++ *
++ * Use the POSIX reentrant safe readdir_r to simplify varifying POSIX
++ * thread-safe compliance.
+ */
+ void seekdir(DIR * dirp, long loc)
+ {
+ register struct ddloc ** prevlp;
+ register struct ddloc * lp;
+ struct dirent * dp;
++ struct dirent de;
+
+ pthread_mutex_lock (dirp->dd_lock);
+ prevlp = (struct ddloc **)&(dirp->dd_ddloc);
+***************
+*** 277,283 ****
+ dirp->dd_seek = lp->loc_seek;
+ dirp->dd_loc = 0;
+ while (dirp->dd_loc < lp->loc_loc) {
+! if (!(dp = readdir(dirp))) {
+ *prevlp = lp->loc_next;
+ break;
+ }
+--- 281,287 ----
+ dirp->dd_seek = lp->loc_seek;
+ dirp->dd_loc = 0;
+ while (dirp->dd_loc < lp->loc_loc) {
+! if (readdir_r(dirp, &de, &dp)) {
+ *prevlp = lp->loc_next;
+ break;
+ }
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/gen/getcwd.c pthreads-1_60_beta6+/gen/getcwd.c
+*** pthreads-1_60_beta6/gen/getcwd.c Sat Sep 2 17:39:30 1995
+--- pthreads-1_60_beta6+/gen/getcwd.c Sat Mar 15 14:08:55 1997
+***************
+*** 50,67 ****
+ (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \
+ dp->d_name[1] == '.' && dp->d_name[2] == '\0'))
+
+ char *
+ getcwd(pt, size)
+ char *pt;
+ size_t size;
+ {
+- register struct dirent *dp;
+ register DIR *dir;
+ register dev_t dev;
+ register ino_t ino;
+ register int first;
+ register char *bpt, *bup;
+ struct stat s;
+ dev_t root_dev;
+ ino_t root_ino;
+ size_t ptsize, upsize;
+--- 50,71 ----
+ (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \
+ dp->d_name[1] == '.' && dp->d_name[2] == '\0'))
+
++ /* Only use reentrant safe routines to simplify varifying POSIX thread-safe
++ * compliance. (mevans).
++ */
+ char *
+ getcwd(pt, size)
+ char *pt;
+ size_t size;
+ {
+ register DIR *dir;
+ register dev_t dev;
+ register ino_t ino;
+ register int first;
+ register char *bpt, *bup;
+ struct stat s;
++ struct dirent *dp;
++ struct dirent de;
+ dev_t root_dev;
+ ino_t root_ino;
+ size_t ptsize, upsize;
+***************
+*** 166,179 ****
+ save_errno = 0;
+ if (s.st_dev == dev) {
+ for (;;) {
+! if (!(dp = readdir(dir)))
+ goto notfound;
+ if (dp->d_fileno == ino)
+ break;
+ }
+ } else
+ for (;;) {
+! if (!(dp = readdir(dir)))
+ goto notfound;
+ if (ISDOT(dp))
+ continue;
+--- 170,183 ----
+ save_errno = 0;
+ if (s.st_dev == dev) {
+ for (;;) {
+! if (readdir_r(dir, &de, &dp))
+ goto notfound;
+ if (dp->d_fileno == ino)
+ break;
+ }
+ } else
+ for (;;) {
+! if (readdir_r(dir, &de, &dp))
+ goto notfound;
+ if (ISDOT(dp))
+ continue;
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/include/syslog.h pthreads-1_60_beta6+/include/syslog.h
+*** pthreads-1_60_beta6/include/syslog.h Mon Sep 26 21:26:29 1994
+--- pthreads-1_60_beta6+/include/syslog.h Sat Mar 15 14:08:56 1997
+***************
+*** 9,14 ****
+--- 9,16 ----
+ #ifndef SYSLOG_H
+ #define SYSLOG_H
+
++ /* Added __[BEGIN/END]_DECLS so this file would work with C++. (mevans) */
++ #include <sys/cdefs.h>
+ #include <stdarg.h>
+
+ /* Discipline: openlog(), closelog(), and setlogmask() are not thread-safe
+***************
+*** 84,95 ****
+--- 86,101 ----
+ #define LOG_NDELAY 0x08 /* don't delay open */
+ #define LOG_NOWAIT 0x10 /* if forking to log on console, don't wait() */
+
++ __BEGIN_DECLS
++
+ /* Syslogging functions. */
+ void syslog(int pri, char *fmt, ...);
+ void vsyslog(int pri, char *fmt, va_list args);
+ void openlog(char *ident, int logstat, int logfac);
+ void closelog(void);
+ int setlogmask(int pmask);
++
++ __END_DECLS
+
+ #endif
+
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/machdep/engine-i386-linux-1.0.c pthreads-1_60_beta6+/machdep/engine-i386-linux-1.0.c
+*** pthreads-1_60_beta6/machdep/engine-i386-linux-1.0.c Mon Oct 21 20:39:13 1996
+--- pthreads-1_60_beta6+/machdep/engine-i386-linux-1.0.c Sat Mar 15 14:08:56 1997
+***************
+*** 142,147 ****
+--- 142,149 ----
+ * machdep_pthread_start().
+ */
+ machdep_pthread->machdep_state->__pc = (char *)machdep_pthread_start;
++ machdep_pthread->machdep_state->__bp = (char *)0;/* So the backtrace
++ * is sensible (mevans) */
+
+ /* Stack starts high and builds down. */
+ machdep_pthread->machdep_state->__sp =
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/machdep/syscall-i386-linux-1.0.S pthreads-1_60_beta6+/machdep/syscall-i386-linux-1.0.S
+*** pthreads-1_60_beta6/machdep/syscall-i386-linux-1.0.S Mon Oct 21 22:17:32 1996
+--- pthreads-1_60_beta6+/machdep/syscall-i386-linux-1.0.S Sat Mar 15 14:08:56 1997
+***************
+*** 148,156 ****
+ /* =========================================================================
+ * exit 1 select 82
+ * fork 2 socketcall 102
+! * read 3 readv 145
+! * write 4 writev 146
+! * open 5
+ * creat 8
+ * link 9
+ * unlink 10
+--- 148,156 ----
+ /* =========================================================================
+ * exit 1 select 82
+ * fork 2 socketcall 102
+! * read 3 flock 143
+! * write 4 readv 145
+! * open 5 writev 146
+ * creat 8
+ * link 9
+ * unlink 10
+***************
+*** 390,394 ****
+--- 390,401 ----
+ */
+ #ifdef HAVE_SYSCALL_WRITEV
+ SYSCALL3(writev)
++ #endif
++
++ /* ==========================================================================
++ * machdep_sys_flock()
++ */
++ #ifdef HAVE_SYSCALL_FLOCK
++ SYSCALL2(flock)
+ #endif
+
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/net/gethostbyname.c pthreads-1_60_beta6+/net/gethostbyname.c
+*** pthreads-1_60_beta6/net/gethostbyname.c Mon Apr 22 22:41:21 1996
+--- pthreads-1_60_beta6+/net/gethostbyname.c Sat Mar 15 14:08:58 1997
+***************
+*** 146,161 ****
+ {
+ char **alias;
+ FILE *fp = NULL;
+
+ pthread_mutex_lock(&host_iterate_lock);
+ sethostent(0);
+! while ((result = gethostent_r(result, buf, bufsize, errval)) != NULL) {
+ /* Check the entry's name and aliases against the given name. */
+ if (strcasecmp(result->h_name, name) == 0)
+ break;
+ for (alias = result->h_aliases; *alias; alias++) {
+! if (strcasecmp(*alias, name) == 0)
+ break;
+ }
+ }
+ pthread_mutex_unlock(&host_iterate_lock);
+--- 146,166 ----
+ {
+ char **alias;
+ FILE *fp = NULL;
++ int fFound = FALSE;
+
+ pthread_mutex_lock(&host_iterate_lock);
+ sethostent(0);
+! while (!fFound && (result = gethostent_r(result, buf, bufsize, errval))
+! != NULL) {
+ /* Check the entry's name and aliases against the given name. */
+ if (strcasecmp(result->h_name, name) == 0)
+ break;
+ for (alias = result->h_aliases; *alias; alias++) {
+! if (strcasecmp(*alias, name) == 0) {
+! /* fFound will exit while loop. (mevans). */
+! fFound = TRUE;
+ break;
++ }
+ }
+ }
+ pthread_mutex_unlock(&host_iterate_lock);
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/net/res_debug.c pthreads-1_60_beta6+/net/res_debug.c
+*** pthreads-1_60_beta6/net/res_debug.c Thu Feb 23 22:42:35 1995
+--- pthreads-1_60_beta6+/net/res_debug.c Sat Mar 15 14:08:58 1997
+***************
+*** 375,380 ****
+--- 375,383 ----
+
+ /*
+ * Print resource record fields in human readable form.
++ *
++ * Removed calls to non-reentrant routines to simplify varifying
++ * POSIX thread-safe implementations. (mevans).
+ */
+ char *
+ p_rr(cp, msg, file)
+***************
+*** 386,391 ****
+--- 389,395 ----
+ char *cp1, *cp2;
+ u_long tmpttl, t;
+ int lcnt;
++ char buf[32];
+
+ if ((cp = p_fqname(cp, msg, file)) == NULL)
+ return (NULL); /* compression error */
+***************
+*** 413,426 ****
+ case C_HS:
+ bcopy(cp, (char *)&inaddr, sizeof(inaddr));
+ if (dlen == 4) {
+! fprintf(file,"\t%s", inet_ntoa(inaddr));
+ cp += dlen;
+ } else if (dlen == 7) {
+ char *address;
+ u_char protocol;
+ u_short port;
+
+! address = inet_ntoa(inaddr);
+ cp += sizeof(inaddr);
+ protocol = *(u_char*)cp;
+ cp += sizeof(u_char);
+--- 417,432 ----
+ case C_HS:
+ bcopy(cp, (char *)&inaddr, sizeof(inaddr));
+ if (dlen == 4) {
+! fprintf(file,"\t%s",
+! inet_ntoa_r(inaddr, buf, sizeof(buf)));
+ cp += dlen;
+ } else if (dlen == 7) {
+ char *address;
+ u_char protocol;
+ u_short port;
+
+! address = inet_ntoa_r(inaddr,
+! buf, sizeof(buf));
+ cp += sizeof(inaddr);
+ protocol = *(u_char*)cp;
+ cp += sizeof(u_char);
+***************
+*** 524,530 ****
+ bcopy(cp, (char *)&inaddr, sizeof(inaddr));
+ cp += sizeof(u_long);
+ fprintf(file, "\t%s %s ( ",
+! inet_ntoa(inaddr),
+ deproto((int) *cp));
+ cp += sizeof(u_char);
+ n = 0;
+--- 530,536 ----
+ bcopy(cp, (char *)&inaddr, sizeof(inaddr));
+ cp += sizeof(u_long);
+ fprintf(file, "\t%s %s ( ",
+! inet_ntoa_r(inaddr, buf, sizeof(buf)),
+ deproto((int) *cp));
+ cp += sizeof(u_char);
+ n = 0;
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/pthreads/fd_kern.c pthreads-1_60_beta6+/pthreads/fd_kern.c
+*** pthreads-1_60_beta6/pthreads/fd_kern.c Tue Oct 1 12:26:48 1996
+--- pthreads-1_60_beta6+/pthreads/fd_kern.c Sat Mar 15 14:09:00 1997
+***************
+*** 215,221 ****
+ * Called when there is no active thread to run.
+ */
+ extern struct timeval __fd_kern_wait_timeout;
+!
+ void fd_kern_wait()
+ {
+ fd_set fd_set_read, fd_set_write, fd_set_except;
+--- 215,221 ----
+ * Called when there is no active thread to run.
+ */
+ extern struct timeval __fd_kern_wait_timeout;
+! extern volatile sig_atomic_t sig_to_process;
+ void fd_kern_wait()
+ {
+ fd_set fd_set_read, fd_set_write, fd_set_except;
+***************
+*** 254,260 ****
+
+ machdep_unset_thread_timer(NULL);
+ __fd_kern_wait_timeout.tv_usec = 0;
+! __fd_kern_wait_timeout.tv_sec = 3600;
+
+ machdep_sys_sigprocmask(SIG_UNBLOCK, &sig_to_block, &oset);
+
+--- 254,260 ----
+
+ machdep_unset_thread_timer(NULL);
+ __fd_kern_wait_timeout.tv_usec = 0;
+! __fd_kern_wait_timeout.tv_sec = (sig_to_process) ? 0 : 3600;
+
+ machdep_sys_sigprocmask(SIG_UNBLOCK, &sig_to_block, &oset);
+
+***************
+*** 726,731 ****
+--- 726,753 ----
+ return(ret);
+ }
+
++ #if defined (HAVE_SYSCALL_FLOCK)
++ /* ==========================================================================
++ * flock()
++ *
++ * Added (mevans)
++ */
++ int flock(int fd, int operation)
++ {
++ int ret;
++
++ if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
++ if ((ret = machdep_sys_flock(fd_table[fd]->fd.i,
++ operation)) < OK) {
++ SET_ERRNO(-ret);
++ ret = NOTOK;
++ }
++ fd_unlock(fd, FD_RDWR);
++ }
++ return(ret);
++ }
++ #endif
++
+ /* ==========================================================================
+ * pipe()
+ */
+***************
+*** 1126,1132 ****
+ /* Get the error, this function should not fail */
+ machdep_sys_getsockopt(fd_table[fd]->fd.i, SOL_SOCKET,
+ SO_ERROR, &ret, &tmpnamelen);
+! SET_ERRNO(-ret);
+ ret = NOTOK;
+ }
+ } else {
+--- 1148,1155 ----
+ /* Get the error, this function should not fail */
+ machdep_sys_getsockopt(fd_table[fd]->fd.i, SOL_SOCKET,
+ SO_ERROR, &ret, &tmpnamelen);
+! /* ret is already positive (mevans) */
+! SET_ERRNO(ret);
+ ret = NOTOK;
+ }
+ } else {
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/pthreads/malloc.c pthreads-1_60_beta6+/pthreads/malloc.c
+*** pthreads-1_60_beta6/pthreads/malloc.c Thu Mar 9 21:06:43 1995
+--- pthreads-1_60_beta6+/pthreads/malloc.c Sat Mar 15 14:09:00 1997
+***************
+*** 196,204 ****
+ else
+ n = n - x;
+ if (n) {
+! if (sbrk(n) == (char *)-1)
+ return (NULL);
+ }
+ bucket = 0;
+ amt = 8;
+ while (pagesz > amt) {
+--- 196,207 ----
+ else
+ n = n - x;
+ if (n) {
+! if (sbrk(n) == (char *)-1) {
+! /* Unlock before returning (mevans) */
+! pthread_mutex_unlock(mutex);
+ return (NULL);
+ }
++ }
+ bucket = 0;
+ amt = 8;
+ while (pagesz > amt) {
+***************
+*** 363,366 ****
+--- 366,382 ----
+ free(cp);
+
+ return (res);
++ }
++ /* ==========================================================================
++ * calloc()
++ *
++ * Added to ensure pthread's allocation is used (mevans).
++ */
++ void *calloc(size_t nmemb, size_t size)
++ {
++ void *p;
++ size *= nmemb;
++ p = malloc(size);
++ if (p) memset(p, 0, size);
++ return (p);
+ }
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/pthreads/select.c pthreads-1_60_beta6+/pthreads/select.c
+*** pthreads-1_60_beta6/pthreads/select.c Sat Jul 6 21:58:55 1996
+--- pthreads-1_60_beta6+/pthreads/select.c Sat Mar 15 14:09:00 1997
+***************
+*** 165,176 ****
+ pthread_resched_resume(PS_SELECT_WAIT);
+
+ /* We're awake */
+- CLEAR_PF_DONE_EVENT(pthread_run);
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ ret = OK;
+ } else {
+ ret = data.nfds;
+ }
+ } else {
+ pthread_resched_resume(PS_SELECT_WAIT);
+ CLEAR_PF_DONE_EVENT(pthread_run);
+--- 165,180 ----
+ pthread_resched_resume(PS_SELECT_WAIT);
+
+ /* We're awake */
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ ret = OK;
+ } else {
+ ret = data.nfds;
+ }
++ /* Moving this after the sleep_cancel() seemed
++ * to fix intermittent crashes during heavy
++ * socket use. (mevans)
++ */
++ CLEAR_PF_DONE_EVENT(pthread_run);
+ } else {
+ pthread_resched_resume(PS_SELECT_WAIT);
+ CLEAR_PF_DONE_EVENT(pthread_run);
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/pthreads/signal.c pthreads-1_60_beta6+/pthreads/signal.c
+*** pthreads-1_60_beta6/pthreads/signal.c Tue Mar 12 21:33:17 1996
+--- pthreads-1_60_beta6+/pthreads/signal.c Sat Mar 15 14:09:00 1997
+***************
+*** 65,71 ****
+ */
+
+ static sig_atomic_t signum_to_process[SIGMAX + 1] = { 0, };
+! static sig_atomic_t sig_to_process = 0;
+
+ /* static volatile sigset_t sig_to_process; */
+ static volatile int sig_count = 0;
+--- 65,71 ----
+ */
+
+ static sig_atomic_t signum_to_process[SIGMAX + 1] = { 0, };
+! volatile sig_atomic_t sig_to_process = 0;
+
+ /* static volatile sigset_t sig_to_process; */
+ static volatile int sig_count = 0;
+***************
+*** 303,309 ****
+ break;
+ case NOTOK:
+ /* Do the registered action, no threads were sleeping */
+! sigdefault(sig);
+ break;
+ }
+ break;
+--- 303,317 ----
+ break;
+ case NOTOK:
+ /* Do the registered action, no threads were sleeping */
+! /* There is a timing window that gets
+! * here when no threads are on the
+! * sleep queue. This is a quick fix.
+! * The real problem is possibly related
+! * to heavy use of condition variables
+! * with time outs.
+! * (mevans)
+! *sigdefault(sig);
+! */
+ break;
+ }
+ break;
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/stdio/setvbuf.c pthreads-1_60_beta6+/stdio/setvbuf.c
+*** pthreads-1_60_beta6/stdio/setvbuf.c Sat Sep 3 20:58:36 1994
+--- pthreads-1_60_beta6+/stdio/setvbuf.c Sat Mar 15 14:09:00 1997
+***************
+*** 142,148 ****
+ flags |= __SLBF;
+ if (flags & __SRW)
+ flags &= ~(__SRD | __SWR);
+! fp->_w = 0;
+ fp->_flags = flags;
+ fp->_bf._base = fp->_p = (unsigned char *)buf;
+ fp->_bf._size = size;
+--- 142,148 ----
+ flags |= __SLBF;
+ if (flags & __SRW)
+ flags &= ~(__SRD | __SWR);
+! fp->_w = size; /* Was 0 (mevans) */
+ fp->_flags = flags;
+ fp->_bf._base = fp->_p = (unsigned char *)buf;
+ fp->_bf._size = size;
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/stdlib/system.c pthreads-1_60_beta6+/stdlib/system.c
+*** pthreads-1_60_beta6/stdlib/system.c Wed Apr 24 21:18:56 1996
+--- pthreads-1_60_beta6+/stdlib/system.c Sat Mar 15 14:09:01 1997
+***************
+*** 62,68 ****
+ argp[2] = (char *) command;
+ sigemptyset(&tmp_mask);
+ sigaddset(&tmp_mask, SIGCHLD);
+! pthread_sigmask(SIG_BLOCK, tmp_mask, &old_mask);
+ switch(pid = fork()) {
+ case -1: /* error */
+ (void)pthread_sigmask(SIG_SETMASK, &old_mask, NULL);
+--- 62,69 ----
+ argp[2] = (char *) command;
+ sigemptyset(&tmp_mask);
+ sigaddset(&tmp_mask, SIGCHLD);
+! /* Pass the address of tmp_mask to avoid a sigfault. (mevans). */
+! pthread_sigmask(SIG_BLOCK, &tmp_mask, &old_mask);
+ switch(pid = fork()) {
+ case -1: /* error */
+ (void)pthread_sigmask(SIG_SETMASK, &old_mask, NULL);
diff --git a/lib/libpthread/patches/p153 b/lib/libpthread/patches/p153
new file mode 100755
index 00000000000..4e374e29a10
--- /dev/null
+++ b/lib/libpthread/patches/p153
@@ -0,0 +1,90 @@
+<HEAD><TITLE>discuss@charon.mit.edu: [153] in "Pthreads Bugs"</TITLE>
+<H1>[153] in Pthreads Bugs</H1></HEAD>
+<A HREF="/"><IMG SRC="/i-d.gif" ALT="root"></A>
+<A HREF="?153"><IMG SRC="/i-back.gif" ALT="meeting"></A>
+<A HREF="/help.html"><IMG SRC="/i-help.gif" ALT="help"></A>
+<A HREF="1"><IMG SRC="/i-first.gif" ALT="first"></A>
+<A HREF="151"><IMG SRC="/i-fref.gif" ALT="first in chain"></A>
+<A HREF="152"><IMG SRC="/i-pref.gif" ALT="previous in chain"></A>
+<A HREF="152"><IMG SRC="/i-prev.gif" ALT="previous"></A>
+<A HREF="154"><IMG SRC="/i-next.gif" ALT="next"></A>
+<IMG SRC="/n-nref.gif" ALT="">
+<IMG SRC="/n-lref.gif" ALT="">
+<A HREF="161"><IMG SRC="/i-last.gif" ALT="last"></A>
+<HR><H2>Re: sleep / SIGALRM problem in 1_60_beta6</H2>
+<H3>daemon@ATHENA.MIT.EDU (Mon Dec 9 19:32:22 1996
+)</H3>
+<PRE>
+Date: Mon, 09 Dec 1996 17:22:50 -0700
+From: "Mark M. Evans" &lt;mevans@cti-ltd.com&gt;
+To: Tim Hinderliter &lt;kyd@internap.com&gt;
+Cc: pthreads-bugs@MIT.EDU
+
+I think I found what caused fd_kern_wait() to block for the entire
+hour (instead of waking up due to the SIGALRM). Basically, the
+SIGALRM that would move the sleeping thread to the run queue occurs
+while pthread_kernel_lock is set, but *before* the critical section in
+fd_kern_wait() that sets __fd_kern_wait_timeout.tv_sec to 3600. So,
+sig_handler_real() clears __fd_kern_wait_timeout.tv_sec "too soon."
+
+I've worked around this by checking sig_to_process in the critical
+section to determine if we are truly idle. To do this I had to make
+sig_to_process publicly available.
+
+Here are the diffs (relative to the pthreads/pthreads directory):
+
+diff -c -r1.2 -r1.3
+*** signal.c 1996/11/20 05:09:50 1.2
+--- signal.c 1996/12/09 23:14:52 1.3
+***************
+*** 65,71 ****
+ */
+
+ static sig_atomic_t signum_to_process[SIGMAX + 1] = { 0, };
+! static sig_atomic_t sig_to_process = 0;
+
+ /* static volatile sigset_t sig_to_process; */
+ static volatile int sig_count = 0;
+--- 65,71 ----
+ */
+
+ static sig_atomic_t signum_to_process[SIGMAX + 1] = { 0, };
+! sig_atomic_t sig_to_process = 0;
+
+ /* static volatile sigset_t sig_to_process; */
+ static volatile int sig_count = 0;
+*** fd_kern.c 1996/12/03 04:14:59 1.6
+--- fd_kern.c 1996/12/09 23:14:51 1.7
+***************
+*** 215,221 ****
+ * Called when there is no active thread to run.
+ */
+ extern struct timeval __fd_kern_wait_timeout;
+!
+ void fd_kern_wait()
+ {
+ fd_set fd_set_read, fd_set_write, fd_set_except;
+--- 215,221 ----
+ * Called when there is no active thread to run.
+ */
+ extern struct timeval __fd_kern_wait_timeout;
+! extern volatile sig_atomic_t sig_to_process;
+ void fd_kern_wait()
+ {
+ fd_set fd_set_read, fd_set_write, fd_set_except;
+***************
+*** 254,260 ****
+
+ machdep_unset_thread_timer(NULL);
+ __fd_kern_wait_timeout.tv_usec = 0;
+! __fd_kern_wait_timeout.tv_sec = 3600;
+
+ machdep_sys_sigprocmask(SIG_UNBLOCK, &amp;sig_to_block, &amp;oset);
+
+--- 254,260 ----
+
+ machdep_unset_thread_timer(NULL);
+ __fd_kern_wait_timeout.tv_usec = 0;
+! __fd_kern_wait_timeout.tv_sec = (sig_to_process) ? 0 : 3600;
+
+ machdep_sys_sigprocmask(SIG_UNBLOCK, &amp;sig_to_block, &amp;oset);
diff --git a/lib/libpthread/patches/p155 b/lib/libpthread/patches/p155
new file mode 100755
index 00000000000..dbdfa7de899
--- /dev/null
+++ b/lib/libpthread/patches/p155
@@ -0,0 +1,96 @@
+<HEAD><TITLE>discuss@charon.mit.edu: [155] in "Pthreads Bugs"</TITLE>
+<H1>[155] in Pthreads Bugs</H1></HEAD>
+<A HREF="/"><IMG SRC="/i-d.gif" ALT="root"></A>
+<A HREF="?155"><IMG SRC="/i-back.gif" ALT="meeting"></A>
+<A HREF="/help.html"><IMG SRC="/i-help.gif" ALT="help"></A>
+<A HREF="1"><IMG SRC="/i-first.gif" ALT="first"></A>
+<IMG SRC="/n-fref.gif" ALT="">
+<IMG SRC="/n-pref.gif" ALT="">
+<A HREF="154"><IMG SRC="/i-prev.gif" ALT="previous"></A>
+<A HREF="156"><IMG SRC="/i-next.gif" ALT="next"></A>
+<IMG SRC="/n-nref.gif" ALT="">
+<IMG SRC="/n-lref.gif" ALT="">
+<A HREF="161"><IMG SRC="/i-last.gif" ALT="last"></A>
+<HR><H2>pthread_kill() Bug</H2>
+<H3>daemon@ATHENA.MIT.EDU (Thu Dec 26 20:34:45 1996
+)</H3>
+<PRE>
+From: Chris Colohan &lt;colohan@eecg.toronto.edu&gt;
+To: pthreads-bugs@MIT.EDU, proven@MIT.EDU
+Date: Thu, 26 Dec 1996 20:33:48 -0500
+
+pthread_kill() has a problem in PThreads 1.60beta6. It checks to see
+if the target thread is in the state PS_SIGWAIT, and if it is it
+reschedules it. But it does not check if there is more than one
+thread in the PS_SIGWAIT state, and hence mangles the pthread_sigwait
+linked list, potentially resulting in threads getting blocked forever,
+and signals never being delivered. I have a *very* contrived test
+case that demonstrates this problem if you would like it. Please let
+me know...
+
+Chris
+===
+
+Diffs created with diff -c:
+
+*** /home/colohan/thesis/t/pthreads-1_60_beta6/pthreads/pthread_kill.c Tue Feb 21 03:07:18 1995
+--- pthread_kill.c Thu Dec 26 19:50:22 1996
+***************
+*** 41,51 ****
+--- 41,58 ----
+
+ #include &lt;pthread.h&gt;
+
++ /* Defined in sig.c, a linked list of threads currently
++ * blocked in sigwait(): */
++ extern struct pthread * pthread_sigwait;
++
++
+ /* ==========================================================================
+ * pthread_kill()
+ */
+ int pthread_kill(struct pthread * pthread, int sig)
+ {
++ struct pthread ** pthread_ptr;
++
+ pthread_sched_prevent();
+
+ /* Check who is the current owner of pthread */
+***************
+*** 53,62 ****
+ if (0) {
+ } else {
+ if (pthread-&gt;state == PS_SIGWAIT) {
+! if (sigismember(pthread-&gt;data.sigwait, sig)) {
+! *(int *)(pthread-&gt;ret) = sig;
+! pthread_sched_other_resume(pthread);
+! return(OK);
+ }
+ }
+ sigaddset(&amp;(pthread-&gt;sigpending), sig);
+--- 60,84 ----
+ if (0) {
+ } else {
+ if (pthread-&gt;state == PS_SIGWAIT) {
+! if(sigismember(pthread-&gt;data.sigwait, sig)) {
+! for (pthread_ptr = &amp;pthread_sigwait;
+! (*pthread_ptr);
+! pthread_ptr = &amp;((*pthread_ptr)-&gt;next)) {
+! if ((*pthread_ptr) == pthread) {
+!
+! /* Take the thread out of the
+! * pthread_sigwait linked list: */
+! *pthread_ptr=(*pthread_ptr)-&gt;next;
+!
+! *(int *)(pthread-&gt;ret) = sig;
+! pthread_sched_other_resume(pthread);
+! return(OK);
+! }
+! }
+! /* A thread should not be in the state PS_SIGWAIT
+! * without being in the pthread_sigwait linked
+! * list: */
+! PANIC();
+ }
+ }
+ sigaddset(&amp;(pthread-&gt;sigpending), sig);
diff --git a/lib/libpthread/stdio/xprintf.c b/lib/libpthread/stdio/xprintf.c
new file mode 100644
index 00000000000..a05de561e72
--- /dev/null
+++ b/lib/libpthread/stdio/xprintf.c
@@ -0,0 +1,883 @@
+/*
+** It turns out that the printf functions in the stock MIT pthread library
+** is busted. It isn't thread safe. If two threads try to do a printf
+** of a floating point value at the same time, a core-dump might result.
+** So this code is substituted.
+*/
+/*
+** NAME: $Source: /cvs/OpenBSD/src/lib/libpthread/stdio/Attic/xprintf.c,v $
+** VERSION: $Revision: 1.1 $
+** DATE: $Date: 1998/07/21 13:22:19 $
+**
+** ONELINER: A replacement for formatted printing programs.
+**
+** COPYRIGHT:
+** Copyright (c) 1990 by D. Richard Hipp. This code is an original
+** work and has been prepared without reference to any prior
+** implementations of similar functions. No part of this code is
+** subject to licensing restrictions of any telephone company or
+** university.
+**
+** This copyright was released and the code placed in the public domain
+** by the author, D. Richard Hipp, on October 3, 1996.
+**
+** DESCRIPTION:
+** This program is an enhanced replacement for the "printf" programs
+** found in the standard library. The following enhancements are
+** supported:
+**
+** + Additional functions. The standard set of "printf" functions
+** includes printf, fprintf, sprintf, vprintf, vfprintf, and
+** vsprintf. This module adds the following:
+**
+** * snprintf -- Works like sprintf, but has an extra argument
+** which is the size of the buffer written to.
+**
+** * mprintf -- Similar to sprintf. Writes output to memory
+** obtained from mem_alloc.
+**
+** * xprintf -- Calls a function to dispose of output.
+**
+** * nprintf -- No output, but returns the number of characters
+** that would have been output by printf.
+**
+** * A v- version (ex: vsnprintf) of every function is also
+** supplied.
+**
+** + A few extensions to the formatting notation are supported:
+**
+** * The "=" flag (similar to "-") causes the output to be
+** be centered in the appropriately sized field.
+**
+** * The %b field outputs an integer in binary notation.
+**
+** * The %c field now accepts a precision. The character output
+** is repeated by the number of times the precision specifies.
+**
+** * The %' field works like %c, but takes as its character the
+** next character of the format string, instead of the next
+** argument. For example, printf("%.78'-") prints 78 minus
+** signs, the same as printf("%.78c",'-').
+**
+** + When compiled using GCC on a SPARC, this version of printf is
+** faster than the library printf for SUN OS 4.1.
+**
+** + All functions are fully reentrant.
+**
+*/
+/*
+** Undefine COMPATIBILITY to make some slight changes in the way things
+** work. I think the changes are an improvement, but they are not
+** backwards compatible.
+*/
+/* #define COMPATIBILITY / * Compatible with SUN OS 4.1 */
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+/*
+** The maximum number of digits of accuracy in a floating-point conversion.
+*/
+#define MAXDIG 20
+
+/*
+** Conversion types fall into various categories as defined by the
+** following enumeration.
+*/
+enum e_type { /* The type of the format field */
+ RADIX, /* Integer types. %d, %x, %o, and so forth */
+ FLOAT, /* Floating point. %f */
+ EXP, /* Exponentional notation. %e and %E */
+ GENERIC, /* Floating or exponential, depending on exponent. %g */
+ SIZE, /* Return number of characters processed so far. %n */
+ STRING, /* Strings. %s */
+ PERCENT, /* Percent symbol. %% */
+ CHAR, /* Characters. %c */
+ ERROR, /* Used to indicate no such conversion type */
+/* The rest are extensions, not normally found in printf() */
+ CHARLIT, /* Literal characters. %' */
+ SEEIT, /* Strings with visible control characters. %S */
+ MEM_STRING, /* A string which should be deleted after use. %z */
+ ORDINAL, /* 1st, 2nd, 3rd and so forth */
+};
+
+/*
+** Each builtin conversion character (ex: the 'd' in "%d") is described
+** by an instance of the following structure
+*/
+typedef struct s_info { /* Information about each format field */
+ int fmttype; /* The format field code letter */
+ int base; /* The base for radix conversion */
+ char *charset; /* The character set for conversion */
+ int flag_signed; /* Is the quantity signed? */
+ char *prefix; /* Prefix on non-zero values in alt format */
+ enum e_type type; /* Conversion paradigm */
+} info;
+
+/*
+** The following table is searched linearly, so it is good to put the
+** most frequently used conversion types first.
+*/
+static info fmtinfo[] = {
+ { 'd', 10, "0123456789", 1, 0, RADIX, },
+ { 's', 0, 0, 0, 0, STRING, },
+ { 'S', 0, 0, 0, 0, SEEIT, },
+ { 'z', 0, 0, 0, 0, MEM_STRING, },
+ { 'c', 0, 0, 0, 0, CHAR, },
+ { 'o', 8, "01234567", 0, "0", RADIX, },
+ { 'u', 10, "0123456789", 0, 0, RADIX, },
+ { 'x', 16, "0123456789abcdef", 0, "x0", RADIX, },
+ { 'X', 16, "0123456789ABCDEF", 0, "X0", RADIX, },
+ { 'r', 10, "0123456789", 0, 0, ORDINAL, },
+ { 'f', 0, 0, 1, 0, FLOAT, },
+ { 'e', 0, "e", 1, 0, EXP, },
+ { 'E', 0, "E", 1, 0, EXP, },
+ { 'g', 0, "e", 1, 0, GENERIC, },
+ { 'G', 0, "E", 1, 0, GENERIC, },
+ { 'i', 10, "0123456789", 1, 0, RADIX, },
+ { 'n', 0, 0, 0, 0, SIZE, },
+ { 'S', 0, 0, 0, 0, SEEIT, },
+ { '%', 0, 0, 0, 0, PERCENT, },
+ { 'b', 2, "01", 0, "b0", RADIX, }, /* Binary notation */
+ { 'p', 10, "0123456789", 0, 0, RADIX, }, /* Pointers */
+ { '\'', 0, 0, 0, 0, CHARLIT, }, /* Literal char */
+};
+#define NINFO (sizeof(fmtinfo)/sizeof(info)) /* Size of the fmtinfo table */
+
+/*
+** If NOFLOATINGPOINT is defined, then none of the floating point
+** conversions will work.
+*/
+#ifndef NOFLOATINGPOINT
+/*
+** "*val" is a double such that 0.1 <= *val < 10.0
+** Return the ascii code for the leading digit of *val, then
+** multiply "*val" by 10.0 to renormalize.
+**
+** Example:
+** input: *val = 3.14159
+** output: *val = 1.4159 function return = '3'
+**
+** The counter *cnt is incremented each time. After counter exceeds
+** 16 (the number of significant digits in a 64-bit float) '0' is
+** always returned.
+*/
+static int getdigit(long double *val, int *cnt){
+ int digit;
+ long double d;
+ if( (*cnt)++ >= MAXDIG ) return '0';
+ digit = (int)*val;
+ d = digit;
+ digit += '0';
+ *val = (*val - d)*10.0;
+ return digit;
+}
+#endif
+
+/*
+** Setting the size of the BUFFER involves trade-offs. No %d or %f
+** conversion can have more than BUFSIZE characters. If the field
+** width is larger than BUFSIZE, it is silently shortened. On the
+** other hand, this routine consumes more stack space with larger
+** BUFSIZEs. If you have some threads for which you want to minimize
+** stack space, you should keep BUFSIZE small.
+*/
+#define BUFSIZE 100 /* Size of the output buffer */
+
+/*
+** The root program. All variations call this core.
+**
+** INPUTS:
+** func This is a pointer to a function taking three arguments
+** 1. A pointer to the list of characters to be output
+** (Note, this list is NOT null terminated.)
+** 2. An integer number of characters to be output.
+** (Note: This number might be zero.)
+** 3. A pointer to anything. Same as the "arg" parameter.
+**
+** arg This is the pointer to anything which will be passed as the
+** third argument to "func". Use it for whatever you like.
+**
+** fmt This is the format string, as in the usual print.
+**
+** ap This is a pointer to a list of arguments. Same as in
+** vfprint.
+**
+** OUTPUTS:
+** The return value is the total number of characters sent to
+** the function "func". Returns -1 on a error.
+**
+** Note that the order in which automatic variables are declared below
+** seems to make a big difference in determining how fast this beast
+** will run.
+*/
+static int vxprintf(func,arg,format,ap)
+ void (*func)(char*,int,void*);
+ void *arg;
+ const char *format;
+ va_list ap;
+{
+ register const char *fmt; /* The format string. */
+ register int c; /* Next character in the format string */
+ register char *bufpt; /* Pointer to the conversion buffer */
+ register int precision; /* Precision of the current field */
+ register int length; /* Length of the field */
+ register int idx; /* A general purpose loop counter */
+ int count; /* Total number of characters output */
+ int width; /* Width of the current field */
+ int flag_leftjustify; /* True if "-" flag is present */
+ int flag_plussign; /* True if "+" flag is present */
+ int flag_blanksign; /* True if " " flag is present */
+ int flag_alternateform; /* True if "#" flag is present */
+ int flag_zeropad; /* True if field width constant starts with zero */
+ int flag_long; /* True if "l" flag is present */
+ int flag_center; /* True if "=" flag is present */
+ unsigned long longvalue; /* Value for integer types */
+ long double realvalue; /* Value for real types */
+ info *infop; /* Pointer to the appropriate info structure */
+ char buf[BUFSIZE]; /* Conversion buffer */
+ char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
+ int errorflag = 0; /* True if an error is encountered */
+ enum e_type xtype; /* Conversion paradigm */
+ char *zMem; /* String to be freed */
+ static char spaces[] =
+ " ";
+#define SPACESIZE (sizeof(spaces)-1)
+#ifndef NOFLOATINGPOINT
+ int exp; /* exponent of real numbers */
+ long double rounder; /* Used for rounding floating point values */
+ int flag_dp; /* True if decimal point should be shown */
+ int flag_rtz; /* True if trailing zeros should be removed */
+ int flag_exp; /* True to force display of the exponent */
+ int nsd; /* Number of significant digits returned */
+#endif
+
+ fmt = format; /* Put in a register for speed */
+ count = length = 0;
+ bufpt = 0;
+ for(; (c=(*fmt))!=0; ++fmt){
+ if( c!='%' ){
+ register int amt;
+ bufpt = (char *)fmt;
+ amt = 1;
+ while( (c=(*++fmt))!='%' && c!=0 ) amt++;
+ (*func)(bufpt,amt,arg);
+ count += amt;
+ if( c==0 ) break;
+ }
+ if( (c=(*++fmt))==0 ){
+ errorflag = 1;
+ (*func)("%",1,arg);
+ count++;
+ break;
+ }
+ /* Find out what flags are present */
+ flag_leftjustify = flag_plussign = flag_blanksign =
+ flag_alternateform = flag_zeropad = flag_center = 0;
+ do{
+ switch( c ){
+ case '-': flag_leftjustify = 1; c = 0; break;
+ case '+': flag_plussign = 1; c = 0; break;
+ case ' ': flag_blanksign = 1; c = 0; break;
+ case '#': flag_alternateform = 1; c = 0; break;
+ case '0': flag_zeropad = 1; c = 0; break;
+ case '=': flag_center = 1; c = 0; break;
+ default: break;
+ }
+ }while( c==0 && (c=(*++fmt))!=0 );
+ if( flag_center ) flag_leftjustify = 0;
+ /* Get the field width */
+ width = 0;
+ if( c=='*' ){
+ width = va_arg(ap,int);
+ if( width<0 ){
+ flag_leftjustify = 1;
+ width = -width;
+ }
+ c = *++fmt;
+ }else{
+ while( isdigit(c) ){
+ width = width*10 + c - '0';
+ c = *++fmt;
+ }
+ }
+ if( width > BUFSIZE-10 ){
+ width = BUFSIZE-10;
+ }
+ /* Get the precision */
+ if( c=='.' ){
+ precision = 0;
+ c = *++fmt;
+ if( c=='*' ){
+ precision = va_arg(ap,int);
+#ifndef COMPATIBILITY
+ /* This is sensible, but SUN OS 4.1 doesn't do it. */
+ if( precision<0 ) precision = -precision;
+#endif
+ c = *++fmt;
+ }else{
+ while( isdigit(c) ){
+ precision = precision*10 + c - '0';
+ c = *++fmt;
+ }
+ }
+ /* Limit the precision to prevent overflowing buf[] during conversion */
+ if( precision>BUFSIZE-40 ) precision = BUFSIZE-40;
+ }else{
+ precision = -1;
+ }
+ /* Get the conversion type modifier */
+ if( c=='l' ){
+ flag_long = 1;
+ c = *++fmt;
+ }else{
+ flag_long = 0;
+ }
+ /* Fetch the info entry for the field */
+ infop = 0;
+ for(idx=0; idx<NINFO; idx++){
+ if( c==fmtinfo[idx].fmttype ){
+ infop = &fmtinfo[idx];
+ break;
+ }
+ }
+ /* No info entry found. It must be an error. */
+ if( infop==0 ){
+ xtype = ERROR;
+ }else{
+ xtype = infop->type;
+ }
+
+ /*
+ ** At this point, variables are initialized as follows:
+ **
+ ** flag_alternateform TRUE if a '#' is present.
+ ** flag_plussign TRUE if a '+' is present.
+ ** flag_leftjustify TRUE if a '-' is present or if the
+ ** field width was negative.
+ ** flag_zeropad TRUE if the width began with 0.
+ ** flag_long TRUE if the letter 'l' (ell) prefixed
+ ** the conversion character.
+ ** flag_blanksign TRUE if a ' ' is present.
+ ** width The specified field width. This is
+ ** always non-negative. Zero is the default.
+ ** precision The specified precision. The default
+ ** is -1.
+ ** xtype The class of the conversion.
+ ** infop Pointer to the appropriate info struct.
+ */
+ switch( xtype ){
+ case ORDINAL:
+ case RADIX:
+ if( flag_long ) longvalue = va_arg(ap,long);
+ else longvalue = va_arg(ap,int);
+#ifdef COMPATIBILITY
+ /* For the format %#x, the value zero is printed "0" not "0x0".
+ ** I think this is stupid. */
+ if( longvalue==0 ) flag_alternateform = 0;
+#else
+ /* More sensible: turn off the prefix for octal (to prevent "00"),
+ ** but leave the prefix for hex. */
+ if( longvalue==0 && infop->base==8 ) flag_alternateform = 0;
+#endif
+ if( infop->flag_signed ){
+ if( *(long*)&longvalue<0 ){
+ longvalue = -*(long*)&longvalue;
+ prefix = '-';
+ }else if( flag_plussign ) prefix = '+';
+ else if( flag_blanksign ) prefix = ' ';
+ else prefix = 0;
+ }else prefix = 0;
+ if( flag_zeropad && precision<width-(prefix!=0) ){
+ precision = width-(prefix!=0);
+ }
+ bufpt = &buf[BUFSIZE];
+ if( xtype==ORDINAL ){
+ long a,b;
+ a = longvalue%10;
+ b = longvalue%100;
+ bufpt -= 2;
+ if( a==0 || a>3 || (b>10 && b<14) ){
+ bufpt[0] = 't';
+ bufpt[1] = 'h';
+ }else if( a==1 ){
+ bufpt[0] = 's';
+ bufpt[1] = 't';
+ }else if( a==2 ){
+ bufpt[0] = 'n';
+ bufpt[1] = 'd';
+ }else if( a==3 ){
+ bufpt[0] = 'r';
+ bufpt[1] = 'd';
+ }
+ }
+ {
+ register char *cset; /* Use registers for speed */
+ register int base;
+ cset = infop->charset;
+ base = infop->base;
+ do{ /* Convert to ascii */
+ *(--bufpt) = cset[longvalue%base];
+ longvalue = longvalue/base;
+ }while( longvalue>0 );
+ }
+ length = (int)(&buf[BUFSIZE]-bufpt);
+ for(idx=precision-length; idx>0; idx--){
+ *(--bufpt) = '0'; /* Zero pad */
+ }
+ if( prefix ) *(--bufpt) = prefix; /* Add sign */
+ if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */
+ char *pre, x;
+ pre = infop->prefix;
+ if( *bufpt!=pre[0] ){
+ for(pre=infop->prefix; (x=(*pre))!=0; pre++) *(--bufpt) = x;
+ }
+ }
+ length = (int)(&buf[BUFSIZE]-bufpt);
+ break;
+ case FLOAT:
+ case EXP:
+ case GENERIC:
+ realvalue = va_arg(ap,double);
+#ifndef NOFLOATINGPOINT
+ if( precision<0 ) precision = 6; /* Set default precision */
+ if( precision>BUFSIZE-10 ) precision = BUFSIZE-10;
+ if( realvalue<0.0 ){
+ realvalue = -realvalue;
+ prefix = '-';
+ }else{
+ if( flag_plussign ) prefix = '+';
+ else if( flag_blanksign ) prefix = ' ';
+ else prefix = 0;
+ }
+ if( infop->type==GENERIC && precision>0 ) precision--;
+ rounder = 0.0;
+#ifdef COMPATIBILITY
+ /* Rounding works like BSD when the constant 0.4999 is used. Wierd! */
+ for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
+#else
+ /* It makes more sense to use 0.5 */
+ if( precision>MAXDIG-1 ) idx = MAXDIG-1;
+ else idx = precision;
+ for(rounder=0.5; idx>0; idx--, rounder*=0.1);
+#endif
+ if( infop->type==FLOAT ) realvalue += rounder;
+ /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
+ exp = 0;
+ if( realvalue>0.0 ){
+ int k = 0;
+ while( realvalue>=1e8 && k++<100 ){ realvalue *= 1e-8; exp+=8; }
+ while( realvalue>=10.0 && k++<100 ){ realvalue *= 0.1; exp++; }
+ while( realvalue<1e-8 && k++<100 ){ realvalue *= 1e8; exp-=8; }
+ while( realvalue<1.0 && k++<100 ){ realvalue *= 10.0; exp--; }
+ if( k>=100 ){
+ bufpt = "NaN";
+ length = 3;
+ break;
+ }
+ }
+ bufpt = buf;
+ /*
+ ** If the field type is GENERIC, then convert to either EXP
+ ** or FLOAT, as appropriate.
+ */
+ flag_exp = xtype==EXP;
+ if( xtype!=FLOAT ){
+ realvalue += rounder;
+ if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
+ }
+ if( xtype==GENERIC ){
+ flag_rtz = !flag_alternateform;
+ if( exp<-4 || exp>precision ){
+ xtype = EXP;
+ }else{
+ precision = precision - exp;
+ xtype = FLOAT;
+ }
+ }else{
+ flag_rtz = 0;
+ }
+ /*
+ ** The "exp+precision" test causes output to be of type EXP if
+ ** the precision is too large to fit in buf[].
+ */
+ nsd = 0;
+ if( xtype==FLOAT && exp+precision<BUFSIZE-30 ){
+ flag_dp = (precision>0 || flag_alternateform);
+ if( prefix ) *(bufpt++) = prefix; /* Sign */
+ if( exp<0 ) *(bufpt++) = '0'; /* Digits before "." */
+ else for(; exp>=0; exp--) *(bufpt++) = getdigit(&realvalue,&nsd);
+ if( flag_dp ) *(bufpt++) = '.'; /* The decimal point */
+ for(exp++; exp<0 && precision>0; precision--, exp++){
+ *(bufpt++) = '0';
+ }
+ while( (precision--)>0 ) *(bufpt++) = getdigit(&realvalue,&nsd);
+ *(bufpt--) = 0; /* Null terminate */
+ if( flag_rtz && flag_dp ){ /* Remove trailing zeros and "." */
+ while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0;
+ if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0;
+ }
+ bufpt++; /* point to next free slot */
+ }else{ /* EXP or GENERIC */
+ flag_dp = (precision>0 || flag_alternateform);
+ if( prefix ) *(bufpt++) = prefix; /* Sign */
+ *(bufpt++) = getdigit(&realvalue,&nsd); /* First digit */
+ if( flag_dp ) *(bufpt++) = '.'; /* Decimal point */
+ while( (precision--)>0 ) *(bufpt++) = getdigit(&realvalue,&nsd);
+ bufpt--; /* point to last digit */
+ if( flag_rtz && flag_dp ){ /* Remove tail zeros */
+ while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0;
+ if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0;
+ }
+ bufpt++; /* point to next free slot */
+ if( exp || flag_exp ){
+ *(bufpt++) = infop->charset[0];
+ if( exp<0 ){ *(bufpt++) = '-'; exp = -exp; } /* sign of exp */
+ else { *(bufpt++) = '+'; }
+ if( exp>=100 ){
+ *(bufpt++) = (exp/100)+'0'; /* 100's digit */
+ exp %= 100;
+ }
+ *(bufpt++) = exp/10+'0'; /* 10's digit */
+ *(bufpt++) = exp%10+'0'; /* 1's digit */
+ }
+ }
+ /* The converted number is in buf[] and zero terminated. Output it.
+ ** Note that the number is in the usual order, not reversed as with
+ ** integer conversions. */
+ length = (int)(bufpt-buf);
+ bufpt = buf;
+
+ /* Special case: Add leading zeros if the flag_zeropad flag is
+ ** set and we are not left justified */
+ if( flag_zeropad && !flag_leftjustify && length < width){
+ int i;
+ int nPad = width - length;
+ for(i=width; i>=nPad; i--){
+ bufpt[i] = bufpt[i-nPad];
+ }
+ i = prefix!=0;
+ while( nPad-- ) bufpt[i++] = '0';
+ length = width;
+ }
+#endif
+ break;
+ case SIZE:
+ *(va_arg(ap,int*)) = count;
+ length = width = 0;
+ break;
+ case PERCENT:
+ buf[0] = '%';
+ bufpt = buf;
+ length = 1;
+ break;
+ case CHARLIT:
+ case CHAR:
+ c = buf[0] = (xtype==CHAR ? va_arg(ap,int) : *++fmt);
+ if( precision>=0 ){
+ for(idx=1; idx<precision; idx++) buf[idx] = c;
+ length = precision;
+ }else{
+ length =1;
+ }
+ bufpt = buf;
+ break;
+ case STRING:
+ case MEM_STRING:
+ zMem = bufpt = va_arg(ap,char*);
+ if( bufpt==0 ) bufpt = "(null)";
+ length = strlen(bufpt);
+ if( precision>=0 && precision<length ) length = precision;
+ break;
+ case SEEIT:
+ {
+ int i;
+ int c;
+ char *arg = va_arg(ap,char*);
+ for(i=0; i<BUFSIZE-1 && (c = *arg++)!=0; i++){
+ if( c<0x20 || c>=0x7f ){
+ buf[i++] = '^';
+ buf[i] = (c&0x1f)+0x40;
+ }else{
+ buf[i] = c;
+ }
+ }
+ bufpt = buf;
+ length = i;
+ if( precision>=0 && precision<length ) length = precision;
+ }
+ break;
+ case ERROR:
+ buf[0] = '%';
+ buf[1] = c;
+ errorflag = 0;
+ idx = 1+(c!=0);
+ (*func)("%",idx,arg);
+ count += idx;
+ if( c==0 ) fmt--;
+ break;
+ }/* End switch over the format type */
+ /*
+ ** The text of the conversion is pointed to by "bufpt" and is
+ ** "length" characters long. The field width is "width". Do
+ ** the output.
+ */
+ if( !flag_leftjustify ){
+ register int nspace;
+ nspace = width-length;
+ if( nspace>0 ){
+ if( flag_center ){
+ nspace = nspace/2;
+ width -= nspace;
+ flag_leftjustify = 1;
+ }
+ count += nspace;
+ while( nspace>=SPACESIZE ){
+ (*func)(spaces,SPACESIZE,arg);
+ nspace -= SPACESIZE;
+ }
+ if( nspace>0 ) (*func)(spaces,nspace,arg);
+ }
+ }
+ if( length>0 ){
+ (*func)(bufpt,length,arg);
+ count += length;
+ }
+ if( xtype==MEM_STRING && zMem ){
+ free(zMem);
+ }
+ if( flag_leftjustify ){
+ register int nspace;
+ nspace = width-length;
+ if( nspace>0 ){
+ count += nspace;
+ while( nspace>=SPACESIZE ){
+ (*func)(spaces,SPACESIZE,arg);
+ nspace -= SPACESIZE;
+ }
+ if( nspace>0 ) (*func)(spaces,nspace,arg);
+ }
+ }
+ }/* End for loop over the format string */
+ return errorflag ? -1 : count;
+} /* End of function */
+
+/*
+** This non-standard function is still occasionally useful....
+*/
+int xprintf(
+ void (*func)(char*,int,void*),
+ void *arg,
+ const char *format,
+ ...
+){
+ va_list ap;
+ va_start(ap,format);
+ return vxprintf(func,arg,format,ap);
+}
+
+/*
+** Now for string-print, also as found in any standard library.
+** Add to this the snprint function which stops added characters
+** to the string at a given length.
+**
+** Note that snprint returns the length of the string as it would
+** be if there were no limit on the output.
+*/
+struct s_strargument { /* Describes the string being written to */
+ char *next; /* Next free slot in the string */
+ char *last; /* Last available slot in the string */
+};
+
+static void sout(txt,amt,arg)
+ char *txt;
+ int amt;
+ void *arg;
+{
+ register char *head;
+ register const char *t;
+ register int a;
+ register char *tail;
+ a = amt;
+ t = txt;
+ head = ((struct s_strargument*)arg)->next;
+ tail = ((struct s_strargument*)arg)->last;
+ if( tail ){
+ while( a-- >0 && head<tail ) *(head++) = *(t++);
+ }else{
+ while( a-- >0 ) *(head++) = *(t++);
+ }
+ *head = 0;
+ ((struct s_strargument*)arg)->next = head;
+}
+
+int sprintf(char *buf, const char *fmt, ...){
+ int rc;
+ va_list ap;
+ struct s_strargument arg;
+
+ va_start(ap,fmt);
+ arg.next = buf;
+ arg.last = 0;
+ *arg.next = 0;
+ rc = vxprintf(sout,&arg,fmt,ap);
+ va_end(ap);
+}
+int vsprintf(char *buf,const char *fmt,va_list ap){
+ struct s_strargument arg;
+ arg.next = buf;
+ arg.last = 0;
+ *buf = 0;
+ return vxprintf(sout,&arg,fmt,ap);
+}
+int snprintf(char *buf, size_t n, const char *fmt, ...){
+ int rc;
+ va_list ap;
+ struct s_strargument arg;
+
+ va_start(ap,fmt);
+ arg.next = buf;
+ arg.last = &arg.next[n-1];
+ *arg.next = 0;
+ rc = vxprintf(sout,&arg,fmt,ap);
+ va_end(ap);
+}
+int vsnprintf(char *buf, size_t n, const char *fmt, va_list ap){
+ struct s_strargument arg;
+ arg.next = buf;
+ arg.last = &buf[n-1];
+ *buf = 0;
+ return vxprintf(sout,&arg,fmt,ap);
+}
+
+/*
+** The following section of code handles the mprintf routine, that
+** writes to memory obtained from malloc().
+*/
+
+/* This structure is used to store state information about the
+** write in progress
+*/
+struct sgMprintf {
+ char *zBase; /* A base allocation */
+ char *zText; /* The string collected so far */
+ int nChar; /* Length of the string so far */
+ int nAlloc; /* Amount of space allocated in zText */
+};
+
+/* The xprintf callback function. */
+static void mout(zNewText,nNewChar,arg)
+ char *zNewText;
+ int nNewChar;
+ void *arg;
+{
+ struct sgMprintf *pM = (struct sgMprintf*)arg;
+ if( pM->nChar + nNewChar + 1 > pM->nAlloc ){
+ pM->nAlloc = pM->nChar + nNewChar*2 + 1;
+ if( pM->zText==pM->zBase ){
+ pM->zText = malloc(pM->nAlloc);
+ if( pM->zText && pM->nChar ) memcpy(pM->zText,pM->zBase,pM->nChar);
+ }else{
+ pM->zText = realloc(pM->zText, pM->nAlloc);
+ }
+ }
+ if( pM->zText ){
+ memcpy(&pM->zText[pM->nChar], zNewText, nNewChar);
+ pM->nChar += nNewChar;
+ pM->zText[pM->nChar] = 0;
+ }
+}
+
+/*
+** mprintf() works like printf(), but allocations memory to hold the
+** resulting string and returns a pointer to the allocated memory.
+**
+** We changed the name to TclMPrint() to conform with the Tcl private
+** routine naming conventions.
+*/
+char *mprintf(const char *zFormat, ...){
+ va_list ap;
+ struct sgMprintf sMprintf;
+ char *zNew;
+ char zBuf[200];
+
+ va_start(ap,zFormat);
+ sMprintf.nChar = 0;
+ sMprintf.nAlloc = sizeof(zBuf);
+ sMprintf.zText = zBuf;
+ sMprintf.zBase = zBuf;
+ vxprintf(mout,&sMprintf,zFormat,ap);
+ va_end(ap);
+ if( sMprintf.zText==sMprintf.zBase ){
+ zNew = malloc( sMprintf.nChar+1 );
+ if( zNew ) strcpy(zNew,zBuf);
+ }else{
+ zNew = realloc(sMprintf.zText,sMprintf.nChar+1);
+ }
+
+ return zNew;
+}
+
+/* This is the varargs version of mprintf.
+**
+** The name is changed to TclVMPrintf() to conform with Tcl naming
+** conventions.
+*/
+char *vmprintf(const char *zFormat,va_list ap){
+ struct sgMprintf sMprintf;
+ char zBuf[200];
+ sMprintf.nChar = 0;
+ sMprintf.zText = zBuf;
+ sMprintf.nAlloc = sizeof(zBuf);
+ sMprintf.zBase = zBuf;
+ vxprintf(mout,&sMprintf,zFormat,ap);
+ if( sMprintf.zText==sMprintf.zBase ){
+ sMprintf.zText = malloc( strlen(zBuf)+1 );
+ if( sMprintf.zText ) strcpy(sMprintf.zText,zBuf);
+ }else{
+ sMprintf.zText = realloc(sMprintf.zText,sMprintf.nChar+1);
+ }
+ return sMprintf.zText;
+}
+
+/*
+** The following section of code handles the standard fprintf routines
+** for pthreads.
+*/
+
+/* The xprintf callback function. */
+static void fout(zNewText,nNewChar,arg)
+ char *zNewText;
+ int nNewChar;
+ void *arg;
+{
+ fwrite(zNewText,1,nNewChar,(FILE*)arg);
+}
+
+/* The public interface routines */
+int fprintf(FILE *pOut, const char *zFormat, ...){
+ va_list ap;
+ int retc;
+
+ va_start(ap,zFormat);
+ retc = vxprintf(fout,pOut,zFormat,ap);
+ va_end(ap);
+ return retc;
+}
+int vfprintf(FILE *pOut, const char *zFormat, va_list ap){
+ return vxprintf(fout,pOut,zFormat,ap);
+}
+int printf(const char *zFormat, ...){
+ va_list ap;
+ int retc;
+
+ va_start(ap,zFormat);
+ retc = vxprintf(fout,stdout,zFormat,ap);
+ va_end(ap);
+ return retc;
+}
+int vprintf(const char *zFormat, va_list ap){
+ return vxprintf(fout,stdout,zFormat,ap);
+}
diff --git a/lib/libpthread/stdlib/GNUmakefile.inc b/lib/libpthread/stdlib/GNUmakefile.inc
new file mode 100755
index 00000000000..2f55ce8b217
--- /dev/null
+++ b/lib/libpthread/stdlib/GNUmakefile.inc
@@ -0,0 +1,7 @@
+# @(#)Makefile.inc 5.6 (Berkeley) 6/4/91
+
+# stdlib sources
+VPATH:= ${VPATH}:${srcdir}/stdlib
+
+SRCS:= abort.c exit.c strtod.c getopt.c rand.c random.c strtol.c strtoul.c \
+ system.c $(SRCS)
diff --git a/lib/libpthread/stdlib/Makefile.inc b/lib/libpthread/stdlib/Makefile.inc
new file mode 100644
index 00000000000..cc323d1d0e1
--- /dev/null
+++ b/lib/libpthread/stdlib/Makefile.inc
@@ -0,0 +1,10 @@
+# @(#)Makefile.inc 5.6 (Berkeley) 6/4/91
+
+# stdlib sources
+.PATH: ${srcdir}/${MACHINE}/stdlib ${srcdir}/stdlib
+
+SRCS+= exit.c strtod.c getopt.c rand.c random.c strtol.c strtoul.c
+
+# SRCS+=abort.c atexit.c atoi.c atof.c atol.c bsearch.c calloc.c div.c \
+# getenv.c heapsort.c labs.c ldiv.c malloc.c multibyte.c \
+# putenv.c qsort.c radixsort.c setenv.c system.c
diff --git a/lib/libpthread/stdlib/abort.c b/lib/libpthread/stdlib/abort.c
new file mode 100644
index 00000000000..e9892bc554c
--- /dev/null
+++ b/lib/libpthread/stdlib/abort.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1985 Regents of the University of California.
+ * 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, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)abort.c 5.11 (Berkeley) 2/23/91";*/
+static char *rcsid = "$Id: abort.c,v 1.1 1998/07/21 13:22:19 peter Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+
+void
+abort()
+{
+ sigset_t mask;
+
+ sigfillset(&mask);
+ /*
+ * don't block SIGABRT to give any handler a chance; we ignore
+ * any errors -- X3J11 doesn't allow abort to return anyway.
+ */
+ sigdelset(&mask, SIGABRT);
+ pthread_sigmask(SIG_SETMASK, &mask, NULL);
+ kill(getpid(), SIGABRT);
+
+ /*
+ * if SIGABRT ignored, or caught and the handler returns, do
+ * it again, only harder.
+ */
+ pthread_signal(SIGABRT, SIG_DFL);
+ pthread_sigmask(SIG_SETMASK, &mask, NULL);
+ kill(getpid(), SIGABRT);
+ exit(1);
+}
diff --git a/lib/libpthread/stdlib/atexit.h b/lib/libpthread/stdlib/atexit.h
new file mode 100644
index 00000000000..46675a2c9bf
--- /dev/null
+++ b/lib/libpthread/stdlib/atexit.h
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * 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, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ *
+ * from: @(#)atexit.h 5.1 (Berkeley) 5/15/90
+ * $Id: atexit.h,v 1.1 1998/07/21 13:22:19 peter Exp $
+ */
+
+/* must be at least 32 to guarantee ANSI conformance */
+#define ATEXIT_SIZE 32
+
+struct atexit {
+ struct atexit *next; /* next in list */
+ int ind; /* next index in this table */
+ void (*fns[ATEXIT_SIZE])(); /* the table itself */
+};
+
+struct atexit *__atexit; /* points to head of LIFO stack */
diff --git a/lib/libpthread/stdlib/exit.c b/lib/libpthread/stdlib/exit.c
new file mode 100644
index 00000000000..791e82748c5
--- /dev/null
+++ b/lib/libpthread/stdlib/exit.c
@@ -0,0 +1,89 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * 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, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)exit.c 5.4 (Berkeley) 2/23/91";*/
+static char *rcsid = "$Id: exit.c,v 1.1 1998/07/21 13:22:19 peter Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <pthread.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/cdefs.h>
+#include <pthread/posix.h>
+#include "atexit.h"
+
+void (*__cleanup)();
+
+/*
+ * Exit, flushing stdio buffers if necessary.
+ */
+void __NORETURN exit(int status)
+{
+ register struct atexit *p;
+ register int n;
+
+ for (p = __atexit; p; p = p->next)
+ for (n = p->ind; --n >= 0;)
+ (*p->fns[n])();
+ if (__cleanup)
+ (*__cleanup)();
+ _exit(status);
+
+ /* This is to shut up gcc, which complains about this function
+ * returning even if _exit() is declared noreturn. */
+ while (1);
+}
+
+
+/*
+ * Register a function to be performed at exit.
+ */
+int atexit(void (*fn)())
+{
+ static struct atexit __atexit0; /* one guaranteed table */
+ register struct atexit *p;
+
+ if ((p = __atexit) == NULL)
+ __atexit = p = &__atexit0;
+ else if (p->ind >= ATEXIT_SIZE) {
+ if ((p = malloc(sizeof(*p))) == NULL)
+ return (-1);
+ p->ind = 0;
+ p->next = __atexit;
+ __atexit = p;
+ }
+ p->fns[p->ind++] = fn;
+ return (0);
+}
diff --git a/lib/libpthread/stdlib/getopt.c b/lib/libpthread/stdlib/getopt.c
new file mode 100644
index 00000000000..88164ef34a1
--- /dev/null
+++ b/lib/libpthread/stdlib/getopt.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * 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, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getopt.c 4.13 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <config.h>
+
+/*
+ * get option letter from argument vector
+ */
+
+#ifndef LD_LINKS_STATIC_DATA
+/*
+ * Under the Solaris ld, some data sections are linked in regaurdless of
+ * whether or not the name has been resolved.
+ */
+int opterr = 1, /* if error message should be printed */
+ optind = 1, /* index into parent argv vector */
+ optopt = 0; /* character checked for validity */
+char * optarg = NULL; /* argument associated with option */
+
+#else
+
+extern int opterr, optind, optopt;
+extern char *optarg;
+
+#endif
+
+#define BADCH (int)'?'
+#define EMSG ""
+
+int
+getopt(nargc, nargv, ostr)
+ int nargc;
+ char * const *nargv;
+ const char *ostr;
+{
+ static char *place = EMSG; /* option letter processing */
+ register char *oli; /* option letter list index */
+ char *p;
+
+ if (!*place) { /* update scanning pointer */
+ if (optind >= nargc || *(place = nargv[optind]) != '-') {
+ place = EMSG;
+ return(EOF);
+ }
+ if (place[1] && *++place == '-') { /* found "--" */
+ ++optind;
+ place = EMSG;
+ return(EOF);
+ }
+ } /* option letter okay? */
+ if ((optopt = (int)*place++) == (int)':' ||
+ !(oli = strchr(ostr, optopt))) {
+ /*
+ * if the user didn't specify '-' as an option,
+ * assume it means EOF.
+ */
+ if (optopt == (int)'-')
+ return(EOF);
+ if (!*place)
+ ++optind;
+ if (opterr) {
+ if (!(p = strrchr(*nargv, '/')))
+ p = *nargv;
+ else
+ ++p;
+ (void)fprintf(stderr, "%s: illegal option -- %c\n",
+ p, optopt);
+ }
+ return(BADCH);
+ }
+ if (*++oli != ':') { /* don't need argument */
+ optarg = NULL;
+ if (!*place)
+ ++optind;
+ }
+ else { /* need an argument */
+ if (*place) /* no white space */
+ optarg = place;
+ else if (nargc <= ++optind) { /* no arg */
+ place = EMSG;
+ if (!(p = strrchr(*nargv, '/')))
+ p = *nargv;
+ else
+ ++p;
+ if (opterr)
+ (void)fprintf(stderr,
+ "%s: option requires an argument -- %c\n",
+ p, optopt);
+ return(BADCH);
+ }
+ else /* white space */
+ optarg = nargv[optind];
+ place = EMSG;
+ ++optind;
+ }
+ return(optopt); /* dump back option letter */
+}
diff --git a/lib/libpthread/stdlib/rand.c b/lib/libpthread/stdlib/rand.c
new file mode 100644
index 00000000000..9367dceed25
--- /dev/null
+++ b/lib/libpthread/stdlib/rand.c
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 1994 Chris Provenzano, proven@mit.edu
+ * 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, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rand.c 5.6 (Berkeley) 6/24/91";
+#endif /* LIBC_SCCS and not lint */
+
+#include <pthread.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
+static u_long next = 1;
+
+int rand_r(u_int * next_r)
+{
+ int ret;
+
+ (*next_r) = (*next_r) * 1103515245 + 12345;
+ ret = (*next_r) & RAND_MAX;
+ return(ret);
+}
+
+#undef rand
+int rand(void)
+{
+ return ((next = next * 1103515245 + 12345) & RAND_MAX);
+}
+
+#undef srand
+void srand(unsigned int seed)
+{
+ next = seed;
+}
diff --git a/lib/libpthread/stdlib/random.c b/lib/libpthread/stdlib/random.c
new file mode 100644
index 00000000000..8cba96e7534
--- /dev/null
+++ b/lib/libpthread/stdlib/random.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * Copyright (c) 1994 Chris Provenzano, proven@mit.edu
+ * 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, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)random.c 5.9 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+ * random.c:
+ *
+ * An improved random number generation package. In addition to the standard
+ * rand()/srand() like interface, this package also has a special state info
+ * interface. The initstate() routine is called with a seed, an array of
+ * bytes, and a count of how many bytes are being passed in; this array is
+ * then initialized to contain information for random number generation with
+ * that much state information. Good sizes for the amount of state
+ * information are 32, 64, 128, and 256 bytes. The state can be switched by
+ * calling the setstate() routine with the same array as was initiallized
+ * with initstate(). By default, the package runs with 128 bytes of state
+ * information and generates far better random numbers than a linear
+ * congruential generator. If the amount of state information is less than
+ * 32 bytes, a simple linear congruential R.N.G. is used.
+ *
+ * Internally, the state information is treated as an array of longs; the
+ * zeroeth element of the array is the type of R.N.G. being used (small
+ * integer); the remainder of the array is the state information for the
+ * R.N.G. Thus, 32 bytes of state information will give 7 longs worth of
+ * state information, which will allow a degree seven polynomial. (Note:
+ * the zeroeth word of state information also has some other information
+ * stored in it -- see setstate() for details).
+ *
+ * The random number generation technique is a linear feedback shift register
+ * approach, employing trinomials (since there are fewer terms to sum up that
+ * way). In this approach, the least significant bit of all the numbers in
+ * the state table will act as a linear feedback shift register, and will
+ * have period 2^deg - 1 (where deg is the degree of the polynomial being
+ * used, assuming that the polynomial is irreducible and primitive). The
+ * higher order bits will have longer periods, since their values are also
+ * influenced by pseudo-random carries out of the lower bits. The total
+ * period of the generator is approximately deg*(2**deg - 1); thus doubling
+ * the amount of state information has a vast influence on the period of the
+ * generator. Note: the deg*(2**deg - 1) is an approximation only good for
+ * large deg, when the period of the shift register is the dominant factor.
+ * With deg equal to seven, the period is actually much longer than the
+ * 7*(2**7 - 1) predicted by this formula.
+ */
+
+/*
+ * For each of the currently supported random number generators, we have a
+ * break value on the amount of state information (you need at least this
+ * many bytes of state info to support this random number generator), a degree
+ * for the polynomial (actually a trinomial) that the R.N.G. is based on, and
+ * the separation between the two lower order coefficients of the trinomial.
+ */
+#define TYPE_0 0 /* linear congruential */
+#define BREAK_0 8
+#define DEG_0 0
+#define SEP_0 0
+
+#define TYPE_1 1 /* x**7 + x**3 + 1 */
+#define BREAK_1 32
+#define DEG_1 7
+#define SEP_1 3
+
+#define TYPE_2 2 /* x**15 + x + 1 */
+#define BREAK_2 64
+#define DEG_2 15
+#define SEP_2 1
+
+#define TYPE_3 3 /* x**31 + x**3 + 1 */
+#define BREAK_3 128
+#define DEG_3 31
+#define SEP_3 3
+
+#define TYPE_4 4 /* x**63 + x + 1 */
+#define BREAK_4 256
+#define DEG_4 63
+#define SEP_4 1
+
+/*
+ * Array versions of the above information to make code run faster --
+ * relies on fact that TYPE_i == i.
+ */
+#define MAX_TYPES 5 /* max number of types above */
+
+static int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
+static int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
+
+/*
+ * Initially, everything is set up as if from:
+ *
+ * initstate(1, &randtbl, 128);
+ *
+ * Note that this initialization takes advantage of the fact that srandom()
+ * advances the front and rear pointers 10*rand_deg times, and hence the
+ * rear pointer which starts at 0 will also end up at zero; thus the zeroeth
+ * element of the state information, which contains info about the current
+ * position of the rear pointer is just
+ *
+ * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3.
+ */
+
+static long randtbl[DEG_3 + 1] = {
+ TYPE_3,
+ 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5,
+ 0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd,
+ 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88,
+ 0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc,
+ 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b,
+ 0x27fb47b9,
+};
+
+/*
+ * fptr and rptr are two pointers into the state info, a front and a rear
+ * pointer. These two pointers are always rand_sep places aparts, as they
+ * cycle cyclically through the state information. (Yes, this does mean we
+ * could get away with just one pointer, but the code for random() is more
+ * efficient this way). The pointers are left positioned as they would be
+ * from the call
+ *
+ * initstate(1, randtbl, 128);
+ *
+ * (The position of the rear pointer, rptr, is really 0 (as explained above
+ * in the initialization of randtbl) because the state table pointer is set
+ * to point to randtbl[1] (as explained below).
+ */
+static long *fptr = &randtbl[SEP_3 + 1];
+static long *rptr = &randtbl[1];
+
+/*
+ * The following things are the pointer to the state information table, the
+ * type of the current generator, the degree of the current polynomial being
+ * used, and the separation between the two pointers. Note that for efficiency
+ * of random(), we remember the first location of the state information, not
+ * the zeroeth. Hence it is valid to access state[-1], which is used to
+ * store the type of the R.N.G. Also, we remember the last location, since
+ * this is more efficient than indexing every time to find the address of
+ * the last element to see if the front and rear pointers have wrapped.
+ */
+static long *state = &randtbl[1];
+static int rand_type = TYPE_3;
+static int rand_deg = DEG_3;
+static int rand_sep = SEP_3;
+static long *end_ptr = &randtbl[DEG_3 + 1];
+
+/*
+ * State info won't be corrupted by multiple simultaneous calls,
+ * but srandom(), initstate(), and setstate() affect all threads
+ */
+static pthread_mutex_t random_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * random:
+ *
+ * If we are using the trivial TYPE_0 R.N.G., just do the old linear
+ * congruential bit. Otherwise, we do our fancy trinomial stuff, which is
+ * the same in all the other cases due to all the global variables that have
+ * been set up. The basic operation is to add the number at the rear pointer
+ * into the one at the front pointer. Then both pointers are advanced to
+ * the next location cyclically in the table. The value returned is the sum
+ * generated, reduced to 31 bits by throwing away the "least random" low bit.
+ *
+ * Note: the code takes advantage of the fact that both the front and
+ * rear pointers can't wrap on the same call by not testing the rear
+ * pointer if the front one has wrapped.
+ *
+ * Returns a 31-bit random number.
+ */
+static long random_basic()
+{
+ long i;
+
+ if (rand_type == TYPE_0)
+ i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff;
+ else {
+ *fptr += *rptr;
+ i = (*fptr >> 1) & 0x7fffffff; /* chucking least random bit */
+ if (++fptr >= end_ptr) {
+ fptr = state;
+ ++rptr;
+ } else if (++rptr >= end_ptr)
+ rptr = state;
+ }
+ return(i);
+}
+
+long random()
+{
+ long ret;
+
+ pthread_mutex_lock(&random_mutex);
+ ret = random_basic();
+ pthread_mutex_unlock(&random_mutex);
+ return(ret);
+}
+/*
+ * srandom:
+ *
+ * Initialize the random number generator based on the given seed. If the
+ * type is the trivial no-state-information type, just remember the seed.
+ * Otherwise, initializes state[] based on the given "seed" via a linear
+ * congruential generator. Then, the pointers are set to known locations
+ * that are exactly rand_sep places apart. Lastly, it cycles the state
+ * information a given number of times to get rid of any initial dependencies
+ * introduced by the L.C.R.N.G. Note that the initialization of randtbl[]
+ * for default usage relies on values produced by this routine.
+ */
+static void srandom_basic(u_int x)
+{
+ int i;
+
+ state[0] = x;
+ for (i = 1; i < rand_deg; i++)
+ state[i] = 1103515245 * state[i - 1] + 12345;
+ fptr = &state[rand_sep];
+ rptr = &state[0];
+
+ for (i = 0; i < 10 * rand_deg; i++)
+ (void)random_basic();
+}
+
+void srandom(u_int x)
+{
+ pthread_mutex_lock(&random_mutex);
+ srandom_basic(x);
+ pthread_mutex_unlock(&random_mutex);
+}
+
+/*
+ * initstate:
+ *
+ * Initialize the state information in the given array of n bytes for future
+ * random number generation. Based on the number of bytes we are given, and
+ * the break values for the different R.N.G.'s, we choose the best (largest)
+ * one we can and set things up for it. srandom() is then called to
+ * initialize the state information.
+ *
+ * Note that on return from srandom(), we set state[-1] to be the type
+ * multiplexed with the current value of the rear pointer; this is so
+ * successive calls to initstate() won't lose this information and will be
+ * able to restart with setstate().
+ *
+ * Note: the first thing we do is save the current state, if any, just like
+ * setstate() so that it doesn't matter when initstate is called.
+ *
+ * Returns a pointer to the old state.
+ */
+#ifdef initstate
+#undef initstate
+#endif
+char * initstate(u_int seed, char * arg_state, int n)
+{
+ register char *ostate = (char *)(&state[-1]);
+
+ pthread_mutex_lock(&random_mutex);
+
+ if (rand_type == TYPE_0)
+ state[-1] = rand_type;
+ else
+ state[-1] = MAX_TYPES * (rptr - state) + rand_type;
+ if (n < BREAK_0) {
+ (void)fprintf(stderr,
+ "random: not enough state (%d bytes); ignored.\n", n);
+ pthread_mutex_unlock(&random_mutex);
+ return(0);
+ }
+ if (n < BREAK_1) {
+ rand_type = TYPE_0;
+ rand_deg = DEG_0;
+ rand_sep = SEP_0;
+ } else if (n < BREAK_2) {
+ rand_type = TYPE_1;
+ rand_deg = DEG_1;
+ rand_sep = SEP_1;
+ } else if (n < BREAK_3) {
+ rand_type = TYPE_2;
+ rand_deg = DEG_2;
+ rand_sep = SEP_2;
+ } else if (n < BREAK_4) {
+ rand_type = TYPE_3;
+ rand_deg = DEG_3;
+ rand_sep = SEP_3;
+ } else {
+ rand_type = TYPE_4;
+ rand_deg = DEG_4;
+ rand_sep = SEP_4;
+ }
+ state = &(((long *)arg_state)[1]); /* first location */
+ end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */
+ srandom_basic(seed);
+ if (rand_type == TYPE_0)
+ state[-1] = rand_type;
+ else
+ state[-1] = MAX_TYPES*(rptr - state) + rand_type;
+ pthread_mutex_unlock(&random_mutex);
+ return(ostate);
+}
+
+/*
+ * setstate:
+ *
+ * Restore the state from the given state array.
+ *
+ * Note: it is important that we also remember the locations of the pointers
+ * in the current state information, and restore the locations of the pointers
+ * from the old state information. This is done by multiplexing the pointer
+ * location into the zeroeth word of the state information.
+ *
+ * Note that due to the order in which things are done, it is OK to call
+ * setstate() with the same state as the current state.
+ *
+ * Returns a pointer to the old state information.
+ */
+#ifdef setstate
+#undef setstate
+#endif
+char * setstate(char * arg_state)
+{
+ register long *new_state = (long *)arg_state;
+ register int type = new_state[0] % MAX_TYPES;
+ register int rear = new_state[0] / MAX_TYPES;
+ char *ostate = (char *)(&state[-1]);
+
+ pthread_mutex_lock(&random_mutex);
+
+ if (rand_type == TYPE_0)
+ state[-1] = rand_type;
+ else
+ state[-1] = MAX_TYPES * (rptr - state) + rand_type;
+ switch(type) {
+ case TYPE_0:
+ case TYPE_1:
+ case TYPE_2:
+ case TYPE_3:
+ case TYPE_4:
+ rand_type = type;
+ rand_deg = degrees[type];
+ rand_sep = seps[type];
+ break;
+ default:
+ (void)fprintf(stderr,
+ "random: state info corrupted; not changed.\n");
+ }
+ state = &new_state[1];
+ if (rand_type != TYPE_0) {
+ rptr = &state[rear];
+ fptr = &state[(rear + rand_sep) % rand_deg];
+ }
+ end_ptr = &state[rand_deg]; /* set end_ptr too */
+
+ pthread_mutex_unlock(&random_mutex);
+ return(ostate);
+}
+
diff --git a/lib/libpthread/stdlib/strtod.c b/lib/libpthread/stdlib/strtod.c
new file mode 100644
index 00000000000..173ca1e4bdf
--- /dev/null
+++ b/lib/libpthread/stdlib/strtod.c
@@ -0,0 +1,178 @@
+/*
+** An alternative implemtation of "strtod()" that is both
+** simplier, and thread-safe.
+*/
+#include <pthread.h>
+#include <ctype.h>
+#include <math.h>
+
+#ifdef TEST
+# define strtod NewStrtod
+#include <stdio.h>
+#endif
+
+static double scaler10[] = {
+ 1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90
+};
+static double scaler1[] = {
+ 1.0, 10.0, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9
+};
+static double pastpoint[] = {
+ 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8, 1e-9,
+ 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16, 1e-17, 1e-18, 1e-19,
+ 1e-20, 1e-21, 1e-22, 1e-23, 1e-24, 1e-25, 1e-26, 1e-27, 1e-28, 1e-29,
+ 1e-30, 1e-31, 1e-32, 1e-33, 1e-34, 1e-35, 1e-36, 1e-37, 1e-38, 1e-39,
+ 1e-40, 1e-41, 1e-42, 1e-43, 1e-44, 1e-45, 1e-46, 1e-47, 1e-48, 1e-49,
+ 1e-50, 1e-51, 1e-52, 1e-53, 1e-54, 1e-55, 1e-56, 1e-57, 1e-58, 1e-59,
+};
+
+#ifndef DBL_MAX
+#define DBL_MAX 1.7976931348623157e+308
+#endif
+
+double strtod(const char *zNum, char **pzEnd){
+ double rResult = 0.0;
+ int isNegative = 0;
+
+ while( isspace(*zNum) ){
+ zNum++;
+ }
+ if( *zNum=='-' ){
+ zNum++;
+ isNegative = 1;
+ }else if( *zNum=='+' ){
+ zNum++;
+ }
+ while( isdigit(*zNum) ){
+ rResult = rResult*10.0 + (*zNum - '0');
+ zNum++;
+ }
+ if( *zNum=='.' ){
+ int n = 0;
+ zNum++;
+ while( isdigit(*zNum) ){
+ if( n<sizeof(pastpoint)/sizeof(pastpoint[0]) ){
+ rResult += pastpoint[n] * (*zNum - '0');
+ n++;
+ }
+ zNum++;
+ }
+ }
+ if( *zNum=='e' || *zNum=='E' ){
+ int expVal = 0;
+ int isNegExp = 0;
+ const char *zExpStart = zNum;
+ zNum++;
+ if( *zNum=='-' ){
+ isNegExp = 1;
+ zNum++;
+ }else if( *zNum=='+' ){
+ zNum++;
+ }
+ if( !isdigit(*zNum) ){
+ zNum = zExpStart;
+ }else{
+ double scaler = 1.0;
+ while( isdigit(*zNum) ){
+ expVal = expVal*10 + *zNum - '0';
+ zNum++;
+ }
+ if( expVal >= 1000 ){
+ if( isNegExp ){
+ rResult = 0.0;
+ }else{
+ rResult = DBL_MAX;
+ }
+ goto done;
+ }
+ while( expVal >= 100 ){
+ scaler *= 1.0e100;
+ expVal -= 100;
+ }
+ scaler *= scaler10[expVal/10]*scaler1[expVal%10];
+ if( isNegExp ){
+ scaler = 1.0/scaler;
+ }
+ rResult *= scaler;
+ }
+
+ }
+
+done:
+ if( pzEnd ){
+ *pzEnd = (char *)zNum;
+ }
+ if( isNegative && rResult!=0.0 ){
+ rResult = -rResult;
+ }
+ return rResult;
+}
+
+double atof(const char *nptr)
+{
+ return (strtod(nptr, 0));
+}
+
+#ifdef TEST
+#undef strtod
+
+double strtod(const char*,char**);
+double NewStrtod(const char*,char**);
+
+int main(int argc, char **argv){
+ int nTest = 0;
+ int nFail = 0;
+ int nBigFail = 0;
+ char zBuf[1000];
+
+ while( fgets(zBuf,sizeof(zBuf),stdin) ){
+ double old, new;
+ char *zTailOld, *zTailNew;
+ int i;
+
+ for(i=0; zBuf[i] && zBuf[i]!='\n'; i++){}
+ zBuf[i] = 0;
+
+#if TEST==1
+ printf("Input line: [%s]\n",zBuf);
+ old = strtod(zBuf,&zTailOld);
+ printf("value=%g\n",old);
+ printf("Old: 0x%08x%08x tail=[%s]\n",
+ ((int*)&old)[1], ((int*)&old)[0], zTailOld);
+ new = NewStrtod(zBuf,&zTailNew);
+ printf("value=%g\n",new);
+ printf("New: 0x%08x%08x tail=[%s]\n\n",
+ ((int*)&new)[1], ((int*)&new)[0], zTailNew);
+#else
+ old = strtod(zBuf,&zTailOld);
+ new = NewStrtod(zBuf,&zTailNew);
+ nTest++;
+ if( strcmp(zTailOld,zTailNew)
+ || ((int*)&old)[0]!=((int*)&new)[0]
+ || ((int*)&old)[1]!=((int*)&new)[1]
+ ){
+ int olda, oldb, newa, newb;
+
+ nFail++;
+ olda = ((int*)&old)[1];
+ oldb = ((int*)&old)[0];
+ newa = ((int*)&new)[1];
+ newb = ((int*)&new)[0];
+
+ if( olda!=newa || abs(oldb-newb)>2 ){
+ nBigFail++;
+ printf("******* Big failure \n");
+ }
+ printf("Input = [%s]\n",zBuf);
+ printf("old: val=%g 0x%08x%08x tail=[%s]\n",
+ old, olda, oldb, zTailOld);
+ printf("new: val=%g 0x%08x%08x tail=[%s]\n\n",
+ new, newa, newb, zTailNew);
+ }
+#endif
+ }
+
+ printf("Out of %d tests, %d failures and %d big failurs\n",
+ nTest,nFail, nBigFail);
+}
+#endif
diff --git a/lib/libpthread/stdlib/strtol.c b/lib/libpthread/stdlib/strtol.c
new file mode 100644
index 00000000000..7bb0cb9db18
--- /dev/null
+++ b/lib/libpthread/stdlib/strtol.c
@@ -0,0 +1,131 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * 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, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)strtol.c 5.4 (Berkeley) 2/23/91";*/
+static char *rcsid = "$Id: strtol.c,v 1.1 1998/07/21 13:22:19 peter Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <pthread.h>
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+
+
+/*
+ * Convert a string to a long integer.
+ *
+ * Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+long
+strtol(nptr, endptr, base)
+ const char *nptr;
+ char **endptr;
+ register int base;
+{
+ register const char *s = nptr;
+ register unsigned long acc;
+ register int c;
+ register unsigned long cutoff;
+ register int neg = 0, any, cutlim;
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+
+ /*
+ * Compute the cutoff value between legal numbers and illegal
+ * numbers. That is the largest legal value, divided by the
+ * base. An input number that is greater than this value, if
+ * followed by a legal input character, is too big. One that
+ * is equal to this value may be valid or not; the limit
+ * between valid and invalid numbers is then based on the last
+ * digit. For instance, if the range for longs is
+ * [-2147483648..2147483647] and the input base is 10,
+ * cutoff will be set to 214748364 and cutlim to either
+ * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+ * a value > 214748364, or equal but the next digit is > 7 (or 8),
+ * the number is too big, and we will return a range error.
+ *
+ * Set any if any `digits' consumed; make it negative to indicate
+ * overflow.
+ */
+ cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
+ cutlim = cutoff % (unsigned long)base;
+ cutoff /= (unsigned long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? LONG_MIN : LONG_MAX;
+ errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *) (any ? s - 1 : nptr);
+ return (acc);
+}
diff --git a/lib/libpthread/stdlib/strtoul.c b/lib/libpthread/stdlib/strtoul.c
new file mode 100644
index 00000000000..f59a0b04cf8
--- /dev/null
+++ b/lib/libpthread/stdlib/strtoul.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 1990 Regents of the University of California.
+ * 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, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)strtoul.c 5.3 (Berkeley) 2/23/91";*/
+static char *rcsid = "$Id: strtoul.c,v 1.1 1998/07/21 13:22:19 peter Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <pthread.h>
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/*
+ * Convert a string to an unsigned long integer.
+ *
+ * Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+unsigned long
+strtoul(nptr, endptr, base)
+ const char *nptr;
+ char **endptr;
+ register int base;
+{
+ register const char *s = nptr;
+ register unsigned long acc;
+ register int c;
+ register unsigned long cutoff;
+ register int neg = 0, any, cutlim;
+
+ /*
+ * See strtol for comments as to the logic used.
+ */
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
+ cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = ULONG_MAX;
+ errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *) (any ? s - 1 : nptr);
+ return (acc);
+}
diff --git a/lib/libpthread/stdlib/system.c b/lib/libpthread/stdlib/system.c
new file mode 100644
index 00000000000..d43c5ce3d7c
--- /dev/null
+++ b/lib/libpthread/stdlib/system.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1988 The Regents of the University of California.
+ * 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, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)system.c 5.10 (Berkeley) 2/23/91";*/
+static char *rcsid = "$Id: system.c,v 1.1 1998/07/21 13:22:19 peter Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <pthread.h>
+#include <pthread/paths.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+
+extern char **environ;
+
+system(command)
+ const char *command;
+{
+ char *argp[] = {"sh", "-c", "*to be filled in*", NULL};
+ void (*intsave)(), (*quitsave)(), (*signal())();
+ sigset_t tmp_mask, old_mask;
+ int pstat;
+ pid_t pid;
+
+ if (!command) /* just checking... */
+ return(1);
+
+ argp[2] = (char *) command;
+ sigemptyset(&tmp_mask);
+ sigaddset(&tmp_mask, SIGCHLD);
+ pthread_sigmask(SIG_BLOCK, &tmp_mask, &old_mask);
+ switch(pid = fork()) {
+ case -1: /* error */
+ (void)pthread_sigmask(SIG_SETMASK, &old_mask, NULL);
+ return(-1);
+ case 0: /* child */
+ (void)pthread_sigmask(SIG_SETMASK, &old_mask, NULL);
+ execve(_PATH_BSHELL, argp, environ);
+ _exit(127);
+ }
+
+ intsave = pthread_signal(SIGINT, SIG_IGN);
+ quitsave = pthread_signal(SIGQUIT, SIG_IGN);
+ pid = waitpid(pid, (int *)&pstat, 0);
+ (void)pthread_sigmask(SIG_SETMASK, &old_mask, NULL);
+ (void)pthread_signal(SIGQUIT, quitsave);
+ (void)pthread_signal(SIGINT, intsave);
+ return(pid == -1 ? -1 : pstat);
+}
diff --git a/lib/libpthread/string/GNUmakefile.inc b/lib/libpthread/string/GNUmakefile.inc
new file mode 100755
index 00000000000..7b05ddfe248
--- /dev/null
+++ b/lib/libpthread/string/GNUmakefile.inc
@@ -0,0 +1,7 @@
+# from: @(#)Makefile.inc 5.21 (Berkeley) 5/24/91
+# $Id: GNUmakefile.inc,v 1.1 1998/07/21 13:22:19 peter Exp $
+
+# gen sources
+VPATH:= ${VPATH}:${srcdir}/string
+
+SRCS:= strtok.c $(SRCS)
diff --git a/lib/libpthread/string/Makefile.inc b/lib/libpthread/string/Makefile.inc
new file mode 100644
index 00000000000..0a3804975e0
--- /dev/null
+++ b/lib/libpthread/string/Makefile.inc
@@ -0,0 +1,8 @@
+# from: @(#)Makefile.inc 5.21 (Berkeley) 5/24/91
+# $Id: Makefile.inc,v 1.1 1998/07/21 13:22:19 peter Exp $
+
+# string sources
+.PATH: ${srcdir}/string
+
+SRCS+= strtok.c
+
diff --git a/lib/libpthread/string/strtok.c b/lib/libpthread/string/strtok.c
new file mode 100644
index 00000000000..e6c012aa71c
--- /dev/null
+++ b/lib/libpthread/string/strtok.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * 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, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)strtok.c 5.8 (Berkeley) 2/24/91";*/
+static char *rcsid = "$Id: strtok.c,v 1.1 1998/07/21 13:22:19 peter Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <pthread.h>
+#include <string.h>
+#include <stdlib.h>
+
+char *
+strtok(s, delim)
+ register char *s;
+ register const char *delim;
+{
+ static pthread_mutex_t strtok_mutex = PTHREAD_MUTEX_INITIALIZER;
+ static pthread_key_t strtok_key = -1;
+ char **lasts;
+
+ pthread_mutex_lock(&strtok_mutex);
+ if (strtok_key < 0) {
+ if (pthread_key_create(&strtok_key, free) < 0) {
+ pthread_mutex_unlock(&strtok_mutex);
+ return(NULL);
+ }
+ }
+ pthread_mutex_unlock(&strtok_mutex);
+ if ((lasts = pthread_getspecific(strtok_key)) == NULL) {
+ if ((lasts = (char **)malloc(sizeof(char *))) == NULL) {
+ return(NULL);
+ }
+ pthread_setspecific(strtok_key, lasts);
+ }
+
+ return(strtok_r(s, delim, lasts));
+}
+
+char *
+strtok_r(s, delim, lasts)
+ register char *s;
+ register const char *delim;
+ register char **lasts;
+{
+ register char *spanp;
+ register int c, sc;
+ char *tok;
+
+
+ if (s == NULL && (s = *lasts) == NULL)
+ return (NULL);
+
+ /*
+ * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
+ */
+cont:
+ c = *s++;
+ for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
+ if (c == sc)
+ goto cont;
+ }
+
+ if (c == 0) { /* no non-delimiter characters */
+ *lasts = NULL;
+ return (NULL);
+ }
+ tok = s - 1;
+
+ /*
+ * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
+ * Note that delim must have one NUL; we stop if we see that, too.
+ */
+ for (;;) {
+ c = *s++;
+ spanp = (char *)delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = 0;
+ *lasts = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
diff --git a/lib/libpthread/tests/Makefile b/lib/libpthread/tests/Makefile
new file mode 100644
index 00000000000..5ba9f9a3927
--- /dev/null
+++ b/lib/libpthread/tests/Makefile
@@ -0,0 +1,165 @@
+# 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.
+#
+
+CC = ../pgcc -notinstalled
+CPP = gcc -E
+srctop = /dr1/my/masters/mysql/mit-pthreads
+srcdir = /dr1/my/masters/mysql/mit-pthreads/tests
+VPATH = /dr1/my/masters/mysql/mit-pthreads/tests
+CDEBUGFLAGS = -g -O2 -Werror
+
+INCLUDES= -I../include -I.. -I$(srctop)/include
+CFLAGS = $(CDEBUGFLAGS) $(INCLUDES) $(ADDL_CFLAGS) -DSRCDIR=\"$(srcdir)\"
+LIBS = -lm -lgcc -L../obj/ -lpthread
+#LIBS = -static
+
+# 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
+
+all : $(TESTS) $(BENCHMARKS)
+
+check : $(TESTS)
+ set -e ; \
+ for i in $(TESTS) ; do \
+ echo Running test $$i ... ; \
+ ./$$i ; \
+ done
+
+# More flags
+ADDITIONALFLAGS = -DPTHREAD_INITIAL_PORT
+################################################################################
+#
+
+clean:
+ rm -f *.o $(TESTS) $(BENCHMARKS) a.out core maketmp makeout
+
+depend:
+ sed '/\#\#\# Dependencies/q' < Makefile > maketmp
+ (for i in $(CSRC);do $(CPP) -M $$i;done) >> maketmp
+ cp maketmp Makefile
+
+install:
+
+realclean: clean
+ rm -f Makefile
+
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+
+Makefile: Makefile.in
+ (cd .. ; sh config.status)
+
+test_create : test_create.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_create test_create.o $(LIBS)
+
+test_pthread_join : test_pthread_join.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_pthread_join test_pthread_join.o $(LIBS)
+
+test_switch : test_switch.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_switch test_switch.o $(LIBS)
+
+test_sleep : test_sleep.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_sleep test_sleep.o $(LIBS)
+
+test_readdir : test_readdir.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_readdir test_readdir.o $(LIBS)
+
+test_fork : test_fork.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_fork test_fork.o $(LIBS)
+
+test_execve : test_execve.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_execve test_execve.o $(LIBS)
+
+test_preemption : test_preemption.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_preemption test_preemption.o $(LIBS)
+
+test_preemption_float : test_preemption_float.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_preemption_float test_preemption_float.o $(LIBS)
+
+test_stdio_1 : test_stdio_1.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_stdio_1 test_stdio_1.o $(LIBS)
+
+test_sock_1 : test_sock_1.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_sock_1 test_sock_1.o $(LIBS)
+
+test_sock_2 : test_sock_2a test_sock_2.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_sock_2 test_sock_2.o $(LIBS)
+
+test_sock_2a : test_sock_2a.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_sock_2a test_sock_2a.o $(LIBS)
+
+test_pthread_mutex : test_pthread_mutex.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_pthread_mutex test_pthread_mutex.o $(LIBS)
+
+test_pthread_cond_timedwait : test_pthread_cond_timedwait.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_pthread_cond_timedwait test_pthread_cond_timedwait.o $(LIBS)
+
+test_netdb : test_netdb.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_netdb test_netdb.o $(LIBS)
+
+test_select : test_select.o ../obj/libpthread.a
+ $(CC) $(CFLAGS) -o test_select test_select.o $(LIBS)
+
+test_pw : test_pw.o ../obj/libpthread.a
+ $(CC) $(CFLAGS) -o test_pw test_pw.o $(LIBS)
+
+test_cwd : test_cwd.o ../obj/libpthread.a
+ $(CC) $(CFLAGS) -o test_cwd test_cwd.o $(LIBS)
+
+p_bench_read : p_bench_read.o ../libpthread.a
+ $(CC) $(CFLAGS) -o p_bench_read p_bench_read.o $(LIBS)
+
+p_bench_semaphore : p_bench_semaphore.o ../libpthread.a
+ $(CC) $(CFLAGS) -o p_bench_semaphore p_bench_semaphore.o $(LIBS)
+
+p_bench_mutex : p_bench_mutex.o ../libpthread.a
+ $(CC) $(CFLAGS) -o p_bench_mutex p_bench_mutex.o $(LIBS)
+
+p_bench_yield : p_bench_yield.o ../libpthread.a
+ $(CC) $(CFLAGS) -o p_bench_yield p_bench_yield.o $(LIBS)
+
+p_bench_getpid : p_bench_getpid.o ../libpthread.a
+ $(CC) $(CFLAGS) -o p_bench_getpid p_bench_getpid.o $(LIBS)
+
+p_bench_pthread_create : p_bench_pthread_create.o ../libpthread.a
+ $(CC) $(CFLAGS) -o p_bench_pthread_create p_bench_pthread_create.o $(LIBS)
+
+test_create.o : test_create.c
+test_pthread_join.o : test_pthread_join.c
+test_switch.o : test_switch.c
+test_sleep.o : test_sleep.c
+test_readdir.o : test_readdir.c
+test_fork.o : test_fork.c
+test_execve.o : test_execve.c
+test_preemption.o : test_preemption.c
+test_preemption_float.o : test_preemption_float.c
+test_sock_1.o : test_sock_1.c
+test_sock_2.o : test_sock_2.c
+test_sock_3.o : test_sock_3.c
+test_stdio_1.o : test_stdio_1.c
+test_pthread_mutex.o : test_pthread_mutex.c
+test_pthread_cond_timedwait.o : test_pthread_cond_timedwait.c
+p_bench_read.o : p_bench_read.c
+p_bench_semaphore.o : p_bench_semaphore.c
+p_bench_mutex.o : p_bench_mutex.c
+p_bench_yield.o : p_bench_yield.c
+p_bench_getpid.o : p_bench_getpid.c
+p_bench_pthread_create.o : p_bench_pthread_create.c
+
+################################################################################
+### Do not remove the following line. It is for depend #########################
+### Dependencies:
diff --git a/lib/libpthread/tests/Makefile.in b/lib/libpthread/tests/Makefile.in
new file mode 100644
index 00000000000..6e01b6bffc3
--- /dev/null
+++ b/lib/libpthread/tests/Makefile.in
@@ -0,0 +1,164 @@
+# === 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.
+#
+
+CC = ../pgcc -notinstalled
+CPP = @CPP@
+srctop = @srctop@
+srcdir = @srctop@/tests
+VPATH = @srctop@/tests
+CDEBUGFLAGS = @CFLAGS@
+
+INCLUDES= -I../include -I.. -I$(srctop)/include
+CFLAGS = $(CDEBUGFLAGS) $(INCLUDES) $(ADDL_CFLAGS) -DSRCDIR=\"$(srcdir)\"
+LIBS = -lm -lgcc -L../obj/ -lpthread
+#LIBS = -static
+
+# 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
+
+all : $(TESTS) $(BENCHMARKS)
+
+check : $(TESTS)
+ set -e ; \
+ for i in $(TESTS) ; do \
+ echo Running test $$i ... ; \
+ ./$$i ; \
+ done
+
+# More flags
+ADDITIONALFLAGS = -DPTHREAD_INITIAL_PORT
+################################################################################
+#
+
+clean:
+ rm -f *.o $(TESTS) $(BENCHMARKS) a.out core maketmp makeout
+
+depend:
+ sed '/\#\#\# Dependencies/q' < Makefile > maketmp
+ (for i in $(CSRC);do $(CPP) -M $$i;done) >> maketmp
+ cp maketmp Makefile
+
+install:
+
+realclean: clean
+ rm -f Makefile
+
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+
+Makefile: Makefile.in
+ (cd .. ; sh config.status)
+
+test_create : test_create.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_create test_create.o $(LIBS)
+
+test_pthread_join : test_pthread_join.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_pthread_join test_pthread_join.o $(LIBS)
+
+test_switch : test_switch.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_switch test_switch.o $(LIBS)
+
+test_sleep : test_sleep.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_sleep test_sleep.o $(LIBS)
+
+test_readdir : test_readdir.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_readdir test_readdir.o $(LIBS)
+
+test_fork : test_fork.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_fork test_fork.o $(LIBS)
+
+test_execve : test_execve.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_execve test_execve.o $(LIBS)
+
+test_preemption : test_preemption.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_preemption test_preemption.o $(LIBS)
+
+test_preemption_float : test_preemption_float.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_preemption_float test_preemption_float.o $(LIBS)
+
+test_stdio_1 : test_stdio_1.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_stdio_1 test_stdio_1.o $(LIBS)
+
+test_sock_1 : test_sock_1.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_sock_1 test_sock_1.o $(LIBS)
+
+test_sock_2 : test_sock_2a test_sock_2.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_sock_2 test_sock_2.o $(LIBS)
+
+test_sock_2a : test_sock_2a.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_sock_2a test_sock_2a.o $(LIBS)
+
+test_pthread_mutex : test_pthread_mutex.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_pthread_mutex test_pthread_mutex.o $(LIBS)
+
+test_pthread_cond_timedwait : test_pthread_cond_timedwait.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_pthread_cond_timedwait test_pthread_cond_timedwait.o $(LIBS)
+
+test_netdb : test_netdb.o ../libpthread.a
+ $(CC) $(CFLAGS) -o test_netdb test_netdb.o $(LIBS)
+
+test_select : test_select.o ../obj/libpthread.a
+ $(CC) $(CFLAGS) -o test_select test_select.o $(LIBS)
+
+test_pw : test_pw.o ../obj/libpthread.a
+ $(CC) $(CFLAGS) -o test_pw test_pw.o $(LIBS)
+
+test_cwd : test_cwd.o ../obj/libpthread.a
+ $(CC) $(CFLAGS) -o test_cwd test_cwd.o $(LIBS)
+
+p_bench_read : p_bench_read.o ../libpthread.a
+ $(CC) $(CFLAGS) -o p_bench_read p_bench_read.o $(LIBS)
+
+p_bench_semaphore : p_bench_semaphore.o ../libpthread.a
+ $(CC) $(CFLAGS) -o p_bench_semaphore p_bench_semaphore.o $(LIBS)
+
+p_bench_mutex : p_bench_mutex.o ../libpthread.a
+ $(CC) $(CFLAGS) -o p_bench_mutex p_bench_mutex.o $(LIBS)
+
+p_bench_yield : p_bench_yield.o ../libpthread.a
+ $(CC) $(CFLAGS) -o p_bench_yield p_bench_yield.o $(LIBS)
+
+p_bench_getpid : p_bench_getpid.o ../libpthread.a
+ $(CC) $(CFLAGS) -o p_bench_getpid p_bench_getpid.o $(LIBS)
+
+p_bench_pthread_create : p_bench_pthread_create.o ../libpthread.a
+ $(CC) $(CFLAGS) -o p_bench_pthread_create p_bench_pthread_create.o $(LIBS)
+
+test_create.o : test_create.c
+test_pthread_join.o : test_pthread_join.c
+test_switch.o : test_switch.c
+test_sleep.o : test_sleep.c
+test_readdir.o : test_readdir.c
+test_fork.o : test_fork.c
+test_execve.o : test_execve.c
+test_preemption.o : test_preemption.c
+test_preemption_float.o : test_preemption_float.c
+test_sock_1.o : test_sock_1.c
+test_sock_2.o : test_sock_2.c
+test_sock_3.o : test_sock_3.c
+test_stdio_1.o : test_stdio_1.c
+test_pthread_mutex.o : test_pthread_mutex.c
+test_pthread_cond_timedwait.o : test_pthread_cond_timedwait.c
+p_bench_read.o : p_bench_read.c
+p_bench_semaphore.o : p_bench_semaphore.c
+p_bench_mutex.o : p_bench_mutex.c
+p_bench_yield.o : p_bench_yield.c
+p_bench_getpid.o : p_bench_getpid.c
+p_bench_pthread_create.o : p_bench_pthread_create.c
+
+################################################################################
+### Do not remove the following line. It is for depend #########################
+### Dependencies:
diff --git a/lib/libpthread/tests/README b/lib/libpthread/tests/README
new file mode 100755
index 00000000000..bb4a3e7ce01
--- /dev/null
+++ b/lib/libpthread/tests/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/libpthread/tests/bench_fcntl.c b/lib/libpthread/tests/bench_fcntl.c
new file mode 100644
index 00000000000..046046adda4
--- /dev/null
+++ b/lib/libpthread/tests/bench_fcntl.c
@@ -0,0 +1,82 @@
+/* ==== 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>
+
+#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;
+ 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/libpthread/tests/bench_pipe.c b/lib/libpthread/tests/bench_pipe.c
new file mode 100644
index 00000000000..8555cf37f67
--- /dev/null
+++ b/lib/libpthread/tests/bench_pipe.c
@@ -0,0 +1,115 @@
+/* ==== 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>
+
+#define OK 0
+#define NOTOK -1
+
+/* ==========================================================================
+ * 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/libpthread/tests/bench_read.c b/lib/libpthread/tests/bench_read.c
new file mode 100644
index 00000000000..28c8469e270
--- /dev/null
+++ b/lib/libpthread/tests/bench_read.c
@@ -0,0 +1,88 @@
+/* ==== 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>
+
+#define OK 0
+#define NOTOK -1
+/* ==========================================================================
+ * 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/libpthread/tests/p_bench_getpid.c b/lib/libpthread/tests/p_bench_getpid.c
new file mode 100644
index 00000000000..d972d075c1d
--- /dev/null
+++ b/lib/libpthread/tests/p_bench_getpid.c
@@ -0,0 +1,78 @@
+/* ==== p_bench_getpid.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 <unistd.h>
+#include <stdio.h>
+
+#define OK 0
+#define NOTOK -1
+
+/* ==========================================================================
+ * usage();
+ */
+void usage(void)
+{
+ printf("p_bench_getpid [-d?] [-c count]\n");
+ errno = 0;
+}
+
+main(int argc, char **argv)
+{
+ struct timeval starttime, endtime;
+ pthread_mutex_t lock;
+ pid_t process_id;
+ 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);
+ }
+ }
+
+ 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 %d usecs.\n", count,
+ (endtime.tv_sec - starttime.tv_sec) * 1000000 +
+ (endtime.tv_usec - starttime.tv_usec));
+
+ return 0;
+}
diff --git a/lib/libpthread/tests/p_bench_mutex.c b/lib/libpthread/tests/p_bench_mutex.c
new file mode 100644
index 00000000000..e3179f08072
--- /dev/null
+++ b/lib/libpthread/tests/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>
+
+#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;
+ pthread_mutex_t lock;
+ 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);
+ }
+ }
+
+ 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 %d usecs.\n", count,
+ (endtime.tv_sec - starttime.tv_sec) * 1000000 +
+ (endtime.tv_usec - starttime.tv_usec));
+
+ return 0;
+}
diff --git a/lib/libpthread/tests/p_bench_pthread_create.c b/lib/libpthread/tests/p_bench_pthread_create.c
new file mode 100644
index 00000000000..b31b680c665
--- /dev/null
+++ b/lib/libpthread/tests/p_bench_pthread_create.c
@@ -0,0 +1,92 @@
+/* ==== p_bench_pthread_create.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.
+ */
+
+#define PTHREAD_KERNEL
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+
+extern pthread_attr_t pthread_attr_default;
+
+/* ==========================================================================
+ * new_thread();
+ */
+void * new_thread(void * arg)
+{
+ PANIC();
+}
+
+/* ==========================================================================
+ * usage();
+ */
+void usage(void)
+{
+ printf("p_bench_getpid [-d?] [-c count]\n");
+ errno = 0;
+}
+
+main(int argc, char **argv)
+{
+ struct timeval starttime, endtime;
+ pthread_mutex_t lock;
+ pthread_t thread_id;
+ int count = 10000;
+ int debug = 0;
+ int i;
+
+ char word[256];
+
+ /* Getopt variables. */
+ extern int optind, opterr;
+ extern char *optarg;
+
+ pthread_init();
+ /* Shut timer off */
+ machdep_unset_thread_timer(NULL);
+ pthread_attr_default.stackaddr_attr = &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, & pthread_attr_default, new_thread, NULL)) {
+ printf("Bad pthread create routine\n");
+ exit(1);
+ }
+ }
+ if (gettimeofday(&endtime, NULL)) {
+ perror ("gettimeofday");
+ return 1;
+ }
+
+ printf("%d getpid calls took %d usecs.\n", count,
+ (endtime.tv_sec - starttime.tv_sec) * 1000000 +
+ (endtime.tv_usec - starttime.tv_usec));
+
+ return 0;
+}
diff --git a/lib/libpthread/tests/p_bench_read.c b/lib/libpthread/tests/p_bench_read.c
new file mode 100644
index 00000000000..52a6aca7706
--- /dev/null
+++ b/lib/libpthread/tests/p_bench_read.c
@@ -0,0 +1,103 @@
+/* ==== 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>
+
+#define OK 0
+#define NOTOK -1
+
+/* ==========================================================================
+ * usage();
+ */
+void usage(void)
+{
+ printf("p_bench_read [-d?] [-c count] [-s size] [-f file]\n");
+ errno = 0;
+}
+
+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;
+
+ pthread_init();
+
+ 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 %d usecs.\n", count, infile,
+ (endtime.tv_sec - starttime.tv_sec) * 1000000 +
+ (endtime.tv_usec - starttime.tv_usec));
+
+ return 0;
+}
diff --git a/lib/libpthread/tests/p_bench_semaphore.c b/lib/libpthread/tests/p_bench_semaphore.c
new file mode 100644
index 00000000000..b3bce340b95
--- /dev/null
+++ b/lib/libpthread/tests/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/libpthread/tests/p_bench_yield.c b/lib/libpthread/tests/p_bench_yield.c
new file mode 100644
index 00000000000..bb6d86be09e
--- /dev/null
+++ b/lib/libpthread/tests/p_bench_yield.c
@@ -0,0 +1,123 @@
+/* ==== 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>
+
+#define OK 0
+#define NOTOK -1
+
+/* ==========================================================================
+ * 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);
+}
+
+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;
+
+ pthread_init();
+
+ 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);
+ if (optimization > 0) {
+ pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
+ }
+ if (optimization > 1) {
+ pthread_attr_setfloatstate(&attr, PTHREAD_NOFLOAT);
+ }
+
+ 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 %d usecs.\n", count,
+ (endtime.tv_sec - starttime.tv_sec) * 1000000 +
+ (endtime.tv_usec - starttime.tv_usec));
+
+ return 0;
+}
diff --git a/lib/libpthread/tests/test_create.c b/lib/libpthread/tests/test_create.c
new file mode 100644
index 00000000000..2d82db07c5f
--- /dev/null
+++ b/lib/libpthread/tests/test_create.c
@@ -0,0 +1,35 @@
+/* ==== 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.
+ */
+
+#define PTHREAD_KERNEL
+#include <pthread.h>
+#include <stdio.h>
+
+void* new_thread(void* arg)
+{
+ int i;
+
+ printf("New thread was passed arg address %x\n", arg);
+ printf("New thread stack at %x\n", &i);
+ return(NULL);
+ PANIC();
+}
+
+main()
+{
+ pthread_t thread;
+ int i;
+
+ printf("Original thread stack at %x\n", &i);
+ if (pthread_create(&thread, NULL, new_thread, (void *)0xdeadbeef)) {
+ printf("Error: creating new thread\n");
+ }
+ pthread_exit(NULL);
+ PANIC();
+}
diff --git a/lib/libpthread/tests/test_cwd.c b/lib/libpthread/tests/test_cwd.c
new file mode 100644
index 00000000000..979c173d5fc
--- /dev/null
+++ b/lib/libpthread/tests/test_cwd.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+main(int argc, char **argv)
+{
+ char wd[1024], *getcwd(), *getwd();
+
+ pthread_init();
+ printf("getcwd => %s\n", getcwd(wd, 1024));
+ printf("getwd => %s\n", getwd(wd));
+ exit(0);
+}
diff --git a/lib/libpthread/tests/test_execve.c b/lib/libpthread/tests/test_execve.c
new file mode 100644
index 00000000000..f7988457df9
--- /dev/null
+++ b/lib/libpthread/tests/test_execve.c
@@ -0,0 +1,57 @@
+/* ==== 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.
+ */
+
+#define PTHREAD_KERNEL
+#include <pthread.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.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";
+
+main()
+{
+ pthread_t thread;
+ int fd;
+
+ pthread_init();
+
+ printf("This is the first message\n");
+ if (isatty(1)) {
+ if ((fd = open(ttyname(1), O_RDWR)) < OK) {
+ printf("Error: opening tty\n");
+ exit(1);
+ }
+ } else {
+ printf("Error: stdout not a tty\n");
+ exit(1);
+ }
+
+ 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));
+ machdep_sys_write(1, should_fail, strlen(should_fail));
+
+ if (execve(argv[0], argv, environ) < OK) {
+ printf("Error: execve\n");
+ exit(1);
+ }
+ PANIC();
+}
diff --git a/lib/libpthread/tests/test_fcntl.c b/lib/libpthread/tests/test_fcntl.c
new file mode 100644
index 00000000000..60bc77ce464
--- /dev/null
+++ b/lib/libpthread/tests/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/libpthread/tests/test_fork.c b/lib/libpthread/tests/test_fork.c
new file mode 100644
index 00000000000..4c2125e678a
--- /dev/null
+++ b/lib/libpthread/tests/test_fork.c
@@ -0,0 +1,60 @@
+/* ==== 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.
+ */
+
+#define PTHREAD_KERNEL
+#include <pthread.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+main()
+{
+ pthread_t thread;
+ int flags, pid;
+
+ pthread_init();
+
+ if (((flags = machdep_sys_fcntl(1, F_GETFL, NULL)) >= OK) &&
+ (flags & __FD_NONBLOCK | O_NDELAY)) {
+ machdep_sys_fcntl(1, F_SETFL, flags & (~__FD_NONBLOCK | O_NDELAY));
+ }
+ printf("parent process %d\n", getpid());
+
+ switch(pid = fork()) {
+ case OK:
+ exit(OK);
+ break;
+ case NOTOK:
+ printf("fork() FAILED\n");
+ exit(2);
+ break;
+ default:
+ if ((flags = machdep_sys_fcntl(1, F_GETFL, NULL)) >= OK) {
+ if (flags & (__FD_NONBLOCK | O_NDELAY)) {
+ printf("fd flags not set to BLOCKING ERROR\n");
+ printf("test_fork FAILED\n");
+ exit(1);
+ break;
+ }
+ printf("The stdout fd was set to BLOCKING\n");
+ printf("child process %d\n", pid);
+ flags = machdep_sys_fcntl(1, F_GETFL, NULL);
+ if (flags & (__FD_NONBLOCK | O_NDELAY)) {
+ printf("The stdout fd was reset to O_NDELAY\n");
+ } else {
+ printf("Error: the stdout fd was not reset\n");
+ printf("test_fork FAILED\n");
+ exit(1);
+ }
+ }
+ break;
+ }
+
+ printf("test_fork PASSED\n");
+ pthread_exit(NULL);
+}
diff --git a/lib/libpthread/tests/test_netdb.c b/lib/libpthread/tests/test_netdb.c
new file mode 100644
index 00000000000..a944579237f
--- /dev/null
+++ b/lib/libpthread/tests/test_netdb.c
@@ -0,0 +1,110 @@
+/* ==== 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.
+ */
+
+#define PTHREAD_KERNEL /* Needed for OK and NOTOK defines */
+#include <pthread.h>
+#include <string.h>
+#include <stdio.h>
+#include <netdb.h>
+#include <errno.h>
+
+int debug = 0;
+
+static int test_serv()
+{
+ struct servent *serv;
+ char answer[1024];
+
+ if (serv = getservbyname("telnet", "tcp"))
+ printf("getservbyname -> port %d\n", ntohs(serv->s_port));
+ else
+ printf("getservbyname -> NULL (bad)\n");
+
+ if (serv = getservbyname_r("telnet", "tcp", serv, answer, 1024))
+ 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")) {
+ 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)) {
+ 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")) {
+ return(OK);
+ }
+ return(NOTOK);
+}
+
+/* ==========================================================================
+ * usage();
+ */
+void usage(void)
+{
+ printf("test_netdb [-d?]\n");
+ errno = 0;
+}
+
+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/libpthread/tests/test_pause.c b/lib/libpthread/tests/test_pause.c
new file mode 100644
index 00000000000..46c5080e43e
--- /dev/null
+++ b/lib/libpthread/tests/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/libpthread/tests/test_preemption.c b/lib/libpthread/tests/test_preemption.c
new file mode 100644
index 00000000000..9181c127fe4
--- /dev/null
+++ b/lib/libpthread/tests/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);
+}
+
+main()
+{
+ pthread_t thread;
+ int error;
+
+ 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/libpthread/tests/test_preemption_float.c b/lib/libpthread/tests/test_preemption_float.c
new file mode 100644
index 00000000000..e12192044c6
--- /dev/null
+++ b/lib/libpthread/tests/test_preemption_float.c
@@ -0,0 +1,98 @@
+/* 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 () {
+ int i;
+ pthread_t thread[2];
+ pthread_attr_t attr;
+ int *x, *y;
+
+ pthread_init ();
+ 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/libpthread/tests/test_pthread_cond_timedwait.c b/lib/libpthread/tests/test_pthread_cond_timedwait.c
new file mode 100644
index 00000000000..fe21408f11e
--- /dev/null
+++ b/lib/libpthread/tests/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>
+
+#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);
+}
+
+main()
+{
+ struct timespec abstime = { 0, 0 };
+ struct timeval curtime;
+ pthread_t thread;
+ int error;
+
+ pthread_init();
+ 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/libpthread/tests/test_pthread_join.c b/lib/libpthread/tests/test_pthread_join.c
new file mode 100644
index 00000000000..fd2ec6a78b2
--- /dev/null
+++ b/lib/libpthread/tests/test_pthread_join.c
@@ -0,0 +1,78 @@
+/* ==== 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.
+ */
+
+#define PTHREAD_KERNEL
+#include <pthread.h>
+#include <stdio.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 %x\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 %x\n", &i);
+ return(new_buf);
+ PANIC();
+}
+
+main()
+{
+ char buf[256], *status;
+ pthread_t thread;
+ int debug = 1;
+ int i = 0;
+
+ pthread_init();
+
+ printf("Original thread stack at %x\n", &i);
+ if (pthread_create(&thread, NULL, new_thread_1, (void *)buf) == OK) {
+ if (pthread_join(thread, (void **)(&status)) == OK) {
+ 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) == OK){
+ pthread_yield();
+ if (pthread_join(thread, (void **)(&status)) == OK) {
+ 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/libpthread/tests/test_pthread_mutex.c b/lib/libpthread/tests/test_pthread_mutex.c
new file mode 100644
index 00000000000..2fb0574f5cb
--- /dev/null
+++ b/lib/libpthread/tests/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>
+
+#define OK 0
+#define NOTOK -1
+
+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);
+ pthread_mutexattr_settype(&mutex_debug_attr, PTHREAD_MUTEXTYPE_DEBUG);
+
+ 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);
+}
+
+main()
+{
+ pthread_init();
+
+ 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/libpthread/tests/test_pw.c b/lib/libpthread/tests/test_pw.c
new file mode 100644
index 00000000000..0ef6d428180
--- /dev/null
+++ b/lib/libpthread/tests/test_pw.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <pwd.h>
+
+main()
+{
+ struct passwd *pw;
+
+ pthread_init();
+ pw = getpwuid(getuid());
+ if (!pw) {
+ printf("getpwuid(%d) died!\n", getuid());
+ exit(1);
+ }
+ printf("getpwuid(%d) => %lx\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/libpthread/tests/test_readdir.c b/lib/libpthread/tests/test_readdir.c
new file mode 100644
index 00000000000..6de1841bdbc
--- /dev/null
+++ b/lib/libpthread/tests/test_readdir.c
@@ -0,0 +1,42 @@
+/* ==== 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>
+
+main()
+{
+ struct dirent * file;
+ DIR * dot_dir;
+ int i, found = 0;
+
+ pthread_init();
+
+ if (dot_dir = opendir(".")) {
+ while (file = readdir(dot_dir)) {
+ if (!strcmp("test_readdir", file->d_name)) {
+ 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/libpthread/tests/test_select.c b/lib/libpthread/tests/test_select.c
new file mode 100644
index 00000000000..0401d77a666
--- /dev/null
+++ b/lib/libpthread/tests/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/libpthread/tests/test_setjmp.c b/lib/libpthread/tests/test_setjmp.c
new file mode 100644
index 00000000000..ea24ecd63bc
--- /dev/null
+++ b/lib/libpthread/tests/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/libpthread/tests/test_sleep.c b/lib/libpthread/tests/test_sleep.c
new file mode 100644
index 00000000000..f228d08a2ca
--- /dev/null
+++ b/lib/libpthread/tests/test_sleep.c
@@ -0,0 +1,46 @@
+/* ==== 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>
+
+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);
+ }
+}
+
+main()
+{
+ pthread_t thread;
+ int count = 2;
+ long i;
+
+ pthread_init();
+
+ printf("Going to sleep\n");
+ sleep(10);
+ printf("Done sleeping\n");
+
+ for(i = 0; i < count; i++) {
+ if (pthread_create(&thread, NULL, new_thread, (void *) i)) {
+ printf("error creating new thread %d\n", i);
+ }
+ }
+ pthread_exit(NULL);
+ fprintf(stderr, "pthread_exit returned\n");
+ exit(1);
+}
diff --git a/lib/libpthread/tests/test_sock_1.c b/lib/libpthread/tests/test_sock_1.c
new file mode 100644
index 00000000000..e23755a67dc
--- /dev/null
+++ b/lib/libpthread/tests/test_sock_1.c
@@ -0,0 +1,204 @@
+/* ==== 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;
+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);
+}
+
+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) {
+ printf("Error: sock_accept:accept()\n");
+ 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);
+}
+
+main()
+{
+ pthread_t thread;
+ int i;
+
+ pthread_init();
+ 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 (pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) {
+ printf("Error: main:pthread_attr_setschedpolicy()\n");
+ exit(1);
+ }
+ 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 %lx going to sleep\n", pthread_self());
+ sleep(10);
+ printf("done sleeping\n");
+ return 0;
+}
diff --git a/lib/libpthread/tests/test_sock_2.c b/lib/libpthread/tests/test_sock_2.c
new file mode 100644
index 00000000000..5ec82fd7499
--- /dev/null
+++ b/lib/libpthread/tests/test_sock_2.c
@@ -0,0 +1,116 @@
+/* ==== 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_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) {
+ 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) {
+ printf("Error: sock_accept:accept()\n");
+ 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) {
+ printf("Error: sock_accept:accept()\n");
+ exit(1);
+ }
+
+ /* Setup a write thread */
+ if (pthread_create(&thread, NULL, sock_write, &fd)) {
+ printf("Error: sock_accept:pthread_create(sock_write)\n");
+ exit(1);
+ }
+ if ((tmp = read(fd, buf, 1024)) <= 0) {
+ tmp = read(fd, buf, 1024);
+ printf("Error: sock_accept:read() == %d\n", tmp);
+ exit(1);
+ }
+ printf("%s\n", buf);
+ close(fd);
+}
+
+main()
+{
+ pthread_t thread;
+ int i;
+
+ switch(fork()) {
+ case -1:
+ printf("Error: main:fork()\n");
+ 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)) {
+ printf("Error: main:pthread_create(sock_accept)\n");
+ exit(1);
+ }
+ pthread_exit(NULL);
+}
diff --git a/lib/libpthread/tests/test_sock_2a.c b/lib/libpthread/tests/test_sock_2a.c
new file mode 100644
index 00000000000..9f767b7c675
--- /dev/null
+++ b/lib/libpthread/tests/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) {
+ 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 ((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 */
+
+ 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);
+}
+
+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)) {
+ printf("Error: main:pthread_create(sock_connect)\n");
+ 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/libpthread/tests/test_stdio_1.c b/lib/libpthread/tests/test_stdio_1.c
new file mode 100644
index 00000000000..648343a2c9d
--- /dev/null
+++ b/lib/libpthread/tests/test_stdio_1.c
@@ -0,0 +1,124 @@
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+char * base_name = "test_stdio_1.c";
+char * dir_name = SRCDIR;
+char * fullname;
+
+#define OK 0
+#define NOTOK -1
+
+/* 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.2lf", i, d);
+
+ if (strcmp(buf, str)) {
+ printf("ERROR: sscanf()/sprintf() didn't parse unparse correctly\n");
+ return(NOTOK);
+ }
+ return(OK);
+}
+
+main()
+{
+
+ printf("test_stdio_1 START\n");
+
+ if (fullname = malloc (strlen (dir_name) + strlen (base_name) + 2)) {
+ 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/libpthread/tests/test_switch.c b/lib/libpthread/tests/test_switch.c
new file mode 100644
index 00000000000..4c184158fb8
--- /dev/null
+++ b/lib/libpthread/tests/test_switch.c
@@ -0,0 +1,97 @@
+/* ==== 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>
+
+#define OK 0
+#define NOTOK -1
+
+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);
+}
+
+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 %d\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 (10);
+ for (i = 0; i < count; i++)
+ if (x[i] == 0) {
+ fprintf (stderr, "thread %d never ran\n", i);
+ return 1;
+ }
+ printf ("\n%s PASSED\n", argv[0]);
+ return 0;
+#endif
+}