summaryrefslogtreecommitdiff
path: root/linuxthreads/Examples
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2004-12-22 20:10:10 +0000
committerUlrich Drepper <drepper@redhat.com>2004-12-22 20:10:10 +0000
commita334319f6530564d22e775935d9c91663623a1b4 (patch)
treeb5877475619e4c938e98757d518bb1e9cbead751 /linuxthreads/Examples
parent0ecb606cb6cf65de1d9fc8a919bceb4be476c602 (diff)
(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
Diffstat (limited to 'linuxthreads/Examples')
-rw-r--r--linuxthreads/Examples/Makefile15
-rw-r--r--linuxthreads/Examples/ex1.c42
-rw-r--r--linuxthreads/Examples/ex10.c108
-rw-r--r--linuxthreads/Examples/ex11.c154
-rw-r--r--linuxthreads/Examples/ex12.c47
-rw-r--r--linuxthreads/Examples/ex13.c112
-rw-r--r--linuxthreads/Examples/ex14.c133
-rw-r--r--linuxthreads/Examples/ex15.c58
-rw-r--r--linuxthreads/Examples/ex16.c26
-rw-r--r--linuxthreads/Examples/ex17.c112
-rw-r--r--linuxthreads/Examples/ex18.c113
-rw-r--r--linuxthreads/Examples/ex2.c124
-rw-r--r--linuxthreads/Examples/ex3.c152
-rw-r--r--linuxthreads/Examples/ex4.c115
-rw-r--r--linuxthreads/Examples/ex5.c114
-rw-r--r--linuxthreads/Examples/ex6.c46
-rw-r--r--linuxthreads/Examples/ex7.c45
-rw-r--r--linuxthreads/Examples/ex8.c101
-rw-r--r--linuxthreads/Examples/ex9.c98
-rw-r--r--linuxthreads/Examples/tststatic.c1
20 files changed, 1716 insertions, 0 deletions
diff --git a/linuxthreads/Examples/Makefile b/linuxthreads/Examples/Makefile
new file mode 100644
index 0000000000..c68b3676a4
--- /dev/null
+++ b/linuxthreads/Examples/Makefile
@@ -0,0 +1,15 @@
+CC=gcc
+CFLAGS=-g -O -Wall -I.. -D_REENTRANT
+LIBPTHREAD=../libpthread.a
+
+PROGS=ex1 ex2 ex3 ex4 ex5 proxy
+
+all: $(PROGS)
+
+.c:
+ $(CC) $(CFLAGS) -o $* $*.c $(LIBPTHREAD)
+
+$(PROGS):
+
+clean:
+ rm -f $(PROGS)
diff --git a/linuxthreads/Examples/ex1.c b/linuxthreads/Examples/ex1.c
new file mode 100644
index 0000000000..29138cf761
--- /dev/null
+++ b/linuxthreads/Examples/ex1.c
@@ -0,0 +1,42 @@
+/* Creates two threads, one printing 10000 "a"s, the other printing
+ 10000 "b"s.
+ Illustrates: thread creation, thread joining. */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "pthread.h"
+
+static void *
+process (void *arg)
+{
+ int i;
+ fprintf (stderr, "Starting process %s\n", (char *) arg);
+ for (i = 0; i < 10000; i++)
+ {
+ write (1, (char *) arg, 1);
+ }
+ return NULL;
+}
+
+int
+main (void)
+{
+ int retcode;
+ pthread_t th_a, th_b;
+ void *retval;
+
+ retcode = pthread_create (&th_a, NULL, process, (void *) "a");
+ if (retcode != 0)
+ fprintf (stderr, "create a failed %d\n", retcode);
+ retcode = pthread_create (&th_b, NULL, process, (void *) "b");
+ if (retcode != 0)
+ fprintf (stderr, "create b failed %d\n", retcode);
+ retcode = pthread_join (th_a, &retval);
+ if (retcode != 0)
+ fprintf (stderr, "join a failed %d\n", retcode);
+ retcode = pthread_join (th_b, &retval);
+ if (retcode != 0)
+ fprintf (stderr, "join b failed %d\n", retcode);
+ return 0;
+}
diff --git a/linuxthreads/Examples/ex10.c b/linuxthreads/Examples/ex10.c
new file mode 100644
index 0000000000..f3ad517283
--- /dev/null
+++ b/linuxthreads/Examples/ex10.c
@@ -0,0 +1,108 @@
+/* Tests for pthread_mutex_timedlock function.
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+ Contributed by Kaz Kylheku <kaz@ashi.footprints.net>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <errno.h>
+#include <error.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <time.h>
+
+#define NUM_THREADS 10
+#define NUM_ITERS 50
+#define TIMEOUT_NS 100000000L
+
+static void *thread (void *) __attribute__ ((__noreturn__));
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+int
+main (void)
+{
+ pthread_t th;
+ int i;
+
+ for (i = 0; i < NUM_THREADS; i++)
+ {
+ if (pthread_create (&th, NULL, thread, NULL) != 0)
+ error (EXIT_FAILURE, 0, "cannot create thread");
+ }
+
+ (void) thread (NULL);
+ /* notreached */
+ return 0;
+}
+
+
+static void *
+thread (void *arg)
+{
+ int i;
+ pthread_t self = pthread_self ();
+ static int linecount; /* protected by flockfile(stdout) */
+
+ for (i = 0; i < NUM_ITERS; i++)
+ {
+ struct timespec ts;
+
+ for (;;)
+ {
+ int err;
+
+ clock_gettime (CLOCK_REALTIME, &ts);
+
+ ts.tv_nsec += TIMEOUT_NS;
+
+ if (ts.tv_nsec >= 1000000000L) {
+ ts.tv_sec++;
+ ts.tv_nsec -= 1000000000L;
+ }
+
+ switch ((err = pthread_mutex_timedlock (&mutex, &ts)))
+ {
+ case 0:
+ flockfile (stdout);
+ printf ("%04d: thread %lu got mutex\n", ++linecount,
+ (unsigned long) self);
+ funlockfile (stdout);
+ break;
+ case ETIMEDOUT:
+ flockfile (stdout);
+ printf ("%04d: thread %lu timed out on mutex\n", ++linecount,
+ (unsigned long) self);
+ funlockfile (stdout);
+ continue;
+ default:
+ error (EXIT_FAILURE, err, "pthread_mutex_timedlock failure");
+ }
+ break;
+ }
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = TIMEOUT_NS;
+ nanosleep (&ts, NULL);
+
+ flockfile (stdout);
+ printf ("%04d: thread %lu releasing mutex\n", ++linecount,
+ (unsigned long) self);
+ funlockfile (stdout);
+ pthread_mutex_unlock (&mutex);
+ }
+
+ pthread_exit (NULL);
+}
diff --git a/linuxthreads/Examples/ex11.c b/linuxthreads/Examples/ex11.c
new file mode 100644
index 0000000000..abb5b5385a
--- /dev/null
+++ b/linuxthreads/Examples/ex11.c
@@ -0,0 +1,154 @@
+/* Test program for timedout read/write lock functions.
+ Copyright (C) 2000 Free Software Foundation, Inc.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <errno.h>
+#include <error.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+
+#define NWRITERS 15
+#define WRITETRIES 10
+#define NREADERS 15
+#define READTRIES 15
+
+#define TIMEOUT 1000000
+#define DELAY 1000000
+
+static pthread_rwlock_t lock = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP;
+
+
+static void *
+writer_thread (void *nr)
+{
+ struct timespec ts;
+ struct timespec delay;
+ int n;
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = TIMEOUT;
+
+ delay.tv_sec = 0;
+ delay.tv_nsec = DELAY;
+
+ for (n = 0; n < WRITETRIES; ++n)
+ {
+ do
+ {
+ clock_gettime (CLOCK_REALTIME, &ts);
+
+ ts.tv_nsec += 2 * TIMEOUT;
+
+ printf ("writer thread %ld tries again\n", (long int) nr);
+ }
+ //while (pthread_rwlock_wrlock (&lock), 0);
+ while (pthread_rwlock_timedwrlock (&lock, &ts) == ETIMEDOUT);
+
+ printf ("writer thread %ld succeeded\n", (long int) nr);
+
+ nanosleep (&delay, NULL);
+
+ pthread_rwlock_unlock (&lock);
+
+ printf ("writer thread %ld released\n", (long int) nr);
+ }
+
+ return NULL;
+}
+
+
+static void *
+reader_thread (void *nr)
+{
+ struct timespec ts;
+ struct timespec delay;
+ int n;
+
+ delay.tv_sec = 0;
+ delay.tv_nsec = DELAY;
+
+ for (n = 0; n < READTRIES; ++n)
+ {
+ do
+ {
+ clock_gettime (CLOCK_REALTIME, &ts);
+
+ ts.tv_nsec += TIMEOUT;
+
+ printf ("reader thread %ld tries again\n", (long int) nr);
+ }
+ //while (pthread_rwlock_rdlock (&lock), 0);
+ while (pthread_rwlock_timedrdlock (&lock, &ts) == ETIMEDOUT);
+
+ printf ("reader thread %ld succeeded\n", (long int) nr);
+
+ nanosleep (&delay, NULL);
+
+ pthread_rwlock_unlock (&lock);
+
+ printf ("reader thread %ld released\n", (long int) nr);
+ }
+
+ return NULL;
+}
+
+
+int
+main (void)
+{
+ pthread_t thwr[NWRITERS];
+ pthread_t thrd[NREADERS];
+ int n;
+ void *res;
+
+ /* Make standard error the same as standard output. */
+ dup2 (1, 2);
+
+ /* Make sure we see all message, even those on stdout. */
+ setvbuf (stdout, NULL, _IONBF, 0);
+
+ for (n = 0; n < NWRITERS; ++n)
+ {
+ int err = pthread_create (&thwr[n], NULL, writer_thread,
+ (void *) (long int) n);
+
+ if (err != 0)
+ error (EXIT_FAILURE, err, "cannot create writer thread");
+ }
+
+ for (n = 0; n < NREADERS; ++n)
+ {
+ int err = pthread_create (&thrd[n], NULL, reader_thread,
+ (void *) (long int) n);
+
+ if (err != 0)
+ error (EXIT_FAILURE, err, "cannot create reader thread");
+ }
+
+ /* Wait for all the threads. */
+ for (n = 0; n < NWRITERS; ++n)
+ pthread_join (thwr[n], &res);
+ for (n = 0; n < NREADERS; ++n)
+ pthread_join (thrd[n], &res);
+
+ return 0;
+}
diff --git a/linuxthreads/Examples/ex12.c b/linuxthreads/Examples/ex12.c
new file mode 100644
index 0000000000..e986fec97f
--- /dev/null
+++ b/linuxthreads/Examples/ex12.c
@@ -0,0 +1,47 @@
+/* Variant of ex6, but this time we use pthread_exit (). */
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+
+static void *
+__attribute__ ((noreturn))
+test_thread (void *v_param)
+{
+ pthread_exit (NULL);
+}
+
+int
+main (void)
+{
+ unsigned long count;
+
+ setvbuf (stdout, NULL, _IONBF, 0);
+
+ for (count = 0; count < 2000; ++count)
+ {
+ pthread_t thread;
+ int status;
+
+ status = pthread_create (&thread, NULL, test_thread, NULL);
+ if (status != 0)
+ {
+ printf ("status = %d, count = %lu: %s\n", status, count,
+ strerror (errno));
+ return 1;
+ }
+ else
+ {
+ printf ("count = %lu\n", count);
+ }
+ /* pthread_detach (thread); */
+ if (pthread_join (thread, NULL) != 0)
+ {
+ printf ("join failed, count %lu\n", count);
+ return 2;
+ }
+ usleep (10);
+ }
+ return 0;
+}
diff --git a/linuxthreads/Examples/ex13.c b/linuxthreads/Examples/ex13.c
new file mode 100644
index 0000000000..14add6c773
--- /dev/null
+++ b/linuxthreads/Examples/ex13.c
@@ -0,0 +1,112 @@
+/* Test for Pthreads/mutexes.
+ Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Kurt Garloff <garloff@suse.de>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void *thread_start (void *ptr) __attribute__ ((__noreturn__));
+
+
+struct thr_ctrl
+{
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ int retval;
+};
+
+static void
+dump_mut (pthread_mutex_t * mut)
+{
+ size_t i;
+ for (i = 0; i < sizeof (*mut); i++)
+ printf (" %02x", *((unsigned char *) mut + i));
+ printf ("\n");
+};
+
+/* Helper, the opposite of pthread_cond_wait (cond, mut). */
+static void
+pthr_cond_signal_mutex (pthread_cond_t * cond, pthread_mutex_t * mut)
+{
+ int err;
+ err = pthread_mutex_lock (mut);
+ if (err)
+ printf ("mutex_lock : %s\n", strerror (err));
+ err = pthread_cond_signal (cond);
+ if (err)
+ printf ("cond_signal : %s\n", strerror (err));
+ err = pthread_mutex_unlock (mut);
+ if (err)
+ printf ("mutex_unlock: %s\n", strerror (err));
+}
+
+static void *
+thread_start (void *ptr)
+{
+ struct thr_ctrl *tc = ptr;
+ /* Do initialization. */
+ /* ... */
+ /* Signal that we are ready. */
+ pthr_cond_signal_mutex (&tc->cond, &tc->mutex);
+ sleep (2);
+ pthr_cond_signal_mutex (&tc->cond, &tc->mutex);
+ tc->retval = 0;
+ pthread_exit (&tc->retval);
+}
+
+int
+main (void)
+{
+ struct thr_ctrl threadctrl;
+ pthread_t thread;
+ int err;
+ void *res = &threadctrl.retval;
+ pthread_mutexattr_t mutattr;
+ pthread_mutexattr_init (&mutattr);
+ pthread_mutex_init (&threadctrl.mutex, &mutattr);
+ pthread_cond_init (&threadctrl.cond, NULL);
+ err = pthread_mutex_lock (&threadctrl.mutex);
+ if (err)
+ printf ("mutex_lock : %s\n", strerror (err));
+ dump_mut (&threadctrl.mutex);
+ pthread_create (&thread, NULL, thread_start, &threadctrl);
+ /* Wait until it's ready. */
+ err = pthread_cond_wait (&threadctrl.cond, &threadctrl.mutex);
+ if (err)
+ printf ("cond_wait : %s\n", strerror (err));
+ /* Now, we should have acquired the mutex again! */
+ dump_mut (&threadctrl.mutex);
+ sleep (1);
+ dump_mut (&threadctrl.mutex);
+ err = pthread_cond_wait (&threadctrl.cond, &threadctrl.mutex);
+ if (err)
+ {
+ printf ("cond_wait : %s\n", strerror (err));
+ printf ("ERROR\n");
+ abort ();
+ };
+ dump_mut (&threadctrl.mutex);
+ pthread_join (thread, &res);
+ printf ("OK\n");
+ return 0;
+}
diff --git a/linuxthreads/Examples/ex14.c b/linuxthreads/Examples/ex14.c
new file mode 100644
index 0000000000..406e03f346
--- /dev/null
+++ b/linuxthreads/Examples/ex14.c
@@ -0,0 +1,133 @@
+/* Test of POSIX barriers. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define NTHREADS 20
+
+#define ROUNDS 20
+
+static pthread_barrier_t barriers[NTHREADS];
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+static int counters[NTHREADS];
+static int serial[NTHREADS];
+
+static void *
+worker (void *arg)
+{
+ void *result = NULL;
+ int nr = (long int) arg;
+ int i;
+
+ for (i = 0; i < ROUNDS; ++i)
+ {
+ int j;
+ int retval;
+
+ if (nr == 0)
+ {
+ memset (counters, '\0', sizeof (counters));
+ memset (serial, '\0', sizeof (serial));
+ }
+
+ retval = pthread_barrier_wait (&barriers[NTHREADS - 1]);
+ if (retval != 0 && retval != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("thread %d failed to wait for all the others\n", nr);
+ result = (void *) 1;
+ }
+
+ for (j = nr; j < NTHREADS; ++j)
+ {
+ /* Increment the counter for this round. */
+ pthread_mutex_lock (&lock);
+ ++counters[j];
+ pthread_mutex_unlock (&lock);
+
+ /* Wait for the rest. */
+ retval = pthread_barrier_wait (&barriers[j]);
+
+ /* Test the result. */
+ if (nr == 0 && counters[j] != j + 1)
+ {
+ printf ("barrier in round %d released but count is %d\n",
+ j, counters[j]);
+ result = (void *) 1;
+ }
+
+ if (retval != 0)
+ {
+ if (retval != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("thread %d in round %d has nonzero return value != PTHREAD_BARRIER_SERIAL_THREAD\n",
+ nr, j);
+ result = (void *) 1;
+ }
+ else
+ {
+ pthread_mutex_lock (&lock);
+ ++serial[j];
+ pthread_mutex_unlock (&lock);
+ }
+ }
+
+ /* Wait for the rest again. */
+ retval = pthread_barrier_wait (&barriers[j]);
+
+ /* Now we can check whether exactly one thread was serializing. */
+ if (nr == 0 && serial[j] != 1)
+ {
+ printf ("not exactly one serial thread in round %d\n", j);
+ result = (void *) 1;
+ }
+ }
+ }
+
+ return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 60
+static int
+do_test (void)
+{
+ pthread_t threads[NTHREADS];
+ int i;
+ void *res;
+ int result = 0;
+
+ /* Initialized the barrier variables. */
+ for (i = 0; i < NTHREADS; ++i)
+ if (pthread_barrier_init (&barriers[i], NULL, i + 1) != 0)
+ {
+ printf ("Failed to initialize barrier %d\n", i);
+ exit (1);
+ }
+
+ /* Start the threads. */
+ for (i = 0; i < NTHREADS; ++i)
+ if (pthread_create (&threads[i], NULL, worker, (void *) (long int) i) != 0)
+ {
+ printf ("Failed to start thread %d\n", i);
+ exit (1);
+ }
+
+ /* And wait for them. */
+ for (i = 0; i < NTHREADS; ++i)
+ if (pthread_join (threads[i], &res) != 0 || res != NULL)
+ {
+ printf ("thread %d returned a failure\n", i);
+ result = 1;
+ }
+
+ if (result == 0)
+ puts ("all OK");
+
+ return result;
+}
+
+#include "../test-skeleton.c"
diff --git a/linuxthreads/Examples/ex15.c b/linuxthreads/Examples/ex15.c
new file mode 100644
index 0000000000..e953b231d7
--- /dev/null
+++ b/linuxthreads/Examples/ex15.c
@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <pthread.h>
+#include <unistd.h>
+
+static void *worker (void *dummy) __attribute__ ((__noreturn__));
+
+static void *
+worker (void *dummy)
+{
+ exit (26);
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 10
+static int
+do_test (void)
+{
+ pthread_t th;
+ pid_t pid;
+ int status;
+
+ switch ((pid = fork ()))
+ {
+ case -1:
+ puts ("Could not fork");
+ exit (1);
+ case 0:
+ if (pthread_create(&th, NULL, worker, NULL) != 0)
+ {
+ puts ("Failed to start thread");
+ exit (1);
+ }
+ for (;;);
+ exit (1);
+ default:
+ break;
+ }
+
+ if (waitpid (pid, &status, 0) != pid)
+ {
+ puts ("waitpid failed");
+ exit (1);
+ }
+
+ if (!WIFEXITED (status) || WEXITSTATUS (status) != 26)
+ {
+ printf ("Wrong exit code %d\n", status);
+ exit (1);
+ }
+
+ puts ("All OK");
+ return 0;
+}
+
+#include "../../test-skeleton.c"
diff --git a/linuxthreads/Examples/ex16.c b/linuxthreads/Examples/ex16.c
new file mode 100644
index 0000000000..6509ae4515
--- /dev/null
+++ b/linuxthreads/Examples/ex16.c
@@ -0,0 +1,26 @@
+/* Tst case by Jakub Jelinek <jakub@redhat.com>. */
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+
+static void *
+task (void *p)
+{
+ sleep (30);
+ return NULL;
+}
+
+int
+main (void)
+{
+ pthread_t t;
+ int status;
+
+ status = pthread_create (&t, NULL, task, NULL);
+ if (status)
+ exit (status);
+
+ status = pthread_detach (t);
+ pthread_kill_other_threads_np ();
+ return status;
+}
diff --git a/linuxthreads/Examples/ex17.c b/linuxthreads/Examples/ex17.c
new file mode 100644
index 0000000000..1bc09a5bda
--- /dev/null
+++ b/linuxthreads/Examples/ex17.c
@@ -0,0 +1,112 @@
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/mman.h>
+
+static pthread_mutex_t synch = PTHREAD_MUTEX_INITIALIZER;
+
+static void *
+test_thread (void *v_param)
+{
+ pthread_mutex_lock (&synch);
+ return NULL;
+}
+
+#define STACKSIZE 0x100000
+
+int
+main (void)
+{
+ pthread_t thread;
+ pthread_attr_t attr;
+ int status;
+ void *stack, *stack2;
+ size_t stacksize;
+
+ pthread_attr_init (&attr);
+ stack = mmap (NULL, STACKSIZE,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+ if (stack == MAP_FAILED)
+ {
+ perror ("mmap failed");
+ return 1;
+ }
+
+ status = pthread_attr_setstack (&attr, stack, STACKSIZE);
+ if (status != 0)
+ {
+ printf ("pthread_attr_setstack failed: %s\n", strerror (status));
+ return 1;
+ }
+
+ status = pthread_attr_getstack (&attr, &stack2, &stacksize);
+ if (status != 0)
+ {
+ printf ("pthread_attr_getstack failed: %s\n", strerror (status));
+ return 1;
+ }
+
+ if (stack2 != stack || stacksize != STACKSIZE)
+ {
+ printf ("first pthread_attr_getstack returned different stack (%p,%zx)\n"
+ "than was set by setstack (%p,%x)\n",
+ stack2, stacksize, stack, STACKSIZE);
+ return 2;
+ }
+
+ status = pthread_mutex_lock (&synch);
+ if (status != 0)
+ {
+ printf ("cannot get lock: %s\n", strerror (status));
+ return 1;
+ }
+
+ status = pthread_create (&thread, &attr, test_thread, NULL);
+ if (status != 0)
+ {
+ printf ("pthread_create failed: %s\n", strerror (status));
+ return 1;
+ }
+
+ status = pthread_getattr_np (thread, &attr);
+ if (status != 0)
+ {
+ printf ("pthread_getattr_np failed: %s\n", strerror (status));
+ return 1;
+ }
+
+ status = pthread_attr_getstack (&attr, &stack2, &stacksize);
+ if (status != 0)
+ {
+ printf ("pthread_attr_getstack failed: %s\n", strerror (status));
+ return 1;
+ }
+
+ if (stack2 != stack || stacksize != STACKSIZE)
+ {
+ printf ("second pthread_attr_getstack returned different stack (%p,%zx)\n"
+ "than was set by setstack (%p,%x)\n",
+ stack2, stacksize, stack, STACKSIZE);
+ return 3;
+ }
+
+ status = pthread_mutex_unlock (&synch);
+ if (status != 0)
+ {
+ printf ("cannot release lock: %s\n", strerror (status));
+ return 1;
+ }
+
+ /* pthread_detach (thread); */
+ if (pthread_join (thread, NULL) != 0)
+ {
+ printf ("join failed\n");
+ return 1;
+ }
+ return 0;
+}
diff --git a/linuxthreads/Examples/ex18.c b/linuxthreads/Examples/ex18.c
new file mode 100644
index 0000000000..283396bede
--- /dev/null
+++ b/linuxthreads/Examples/ex18.c
@@ -0,0 +1,113 @@
+/*
+ * Beat up the pthread_key_create and pthread_key_delete
+ * functions.
+ */
+
+#if 0
+#define CHATTY
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+
+const int beatup_iterations = 10000;
+const int num_threads = 30;
+const int max_keys = 500;
+
+struct key_list {
+ struct key_list *next;
+ pthread_key_t key;
+};
+
+struct key_list *key_list;
+pthread_mutex_t key_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * Create a new key and put it at the tail of a linked list.
+ * If the linked list grows to a certain length, delete a key from the
+ * head of * the list.
+ */
+
+static void
+beat_up(void)
+{
+ struct key_list *new = malloc(sizeof *new);
+ struct key_list **iter, *old_key = 0;
+ int key_count = 0;
+
+ if (new == 0) {
+ fprintf(stderr, "malloc failed\n");
+ abort();
+ }
+
+ new->next = 0;
+
+ if (pthread_key_create(&new->key, 0) != 0) {
+ fprintf(stderr, "pthread_key_create failed\n");
+ abort();
+ }
+
+ if (pthread_getspecific(new->key) != 0) {
+ fprintf(stderr, "new pthread_key_t resolves to non-null value\n");
+ abort();
+ }
+
+ pthread_setspecific(new->key, (void *) 1);
+
+#ifdef CHATTY
+ printf("created key\n");
+#endif
+
+ pthread_mutex_lock(&key_lock);
+
+ for (iter = &key_list; *iter != 0; iter = &(*iter)->next)
+ key_count++;
+
+ *iter = new;
+
+ if (key_count > max_keys) {
+ old_key = key_list;
+ key_list = key_list->next;
+ }
+
+ pthread_mutex_unlock(&key_lock);
+
+ if (old_key != 0) {
+#ifdef CHATTY
+ printf("deleting key\n");
+#endif
+ pthread_key_delete(old_key->key);
+ }
+}
+
+static void *
+thread(void *arg)
+{
+ int i;
+ for (i = 0; i < beatup_iterations; i++)
+ beat_up();
+ return 0;
+}
+
+int
+main(void)
+{
+ int i;
+ pthread_attr_t detached_thread;
+
+ pthread_attr_init(&detached_thread);
+ pthread_attr_setdetachstate(&detached_thread, PTHREAD_CREATE_DETACHED);
+
+ for (i = 0; i < num_threads; i++) {
+ pthread_t thread_id;
+ while (pthread_create(&thread_id, &detached_thread, thread, 0) == EAGAIN) {
+ /* let some threads die, so system can breathe. :) */
+ sleep(1);
+ }
+ }
+
+ pthread_exit(0);
+}
diff --git a/linuxthreads/Examples/ex2.c b/linuxthreads/Examples/ex2.c
new file mode 100644
index 0000000000..f2556a4206
--- /dev/null
+++ b/linuxthreads/Examples/ex2.c
@@ -0,0 +1,124 @@
+/* The classic producer-consumer example.
+ Illustrates mutexes and conditions.
+ All integers between 0 and 9999 should be printed exactly twice,
+ once to the right of the arrow and once to the left. */
+
+#include <stdio.h>
+#include "pthread.h"
+
+#define BUFFER_SIZE 16
+
+/* Circular buffer of integers. */
+
+struct prodcons
+{
+ int buffer[BUFFER_SIZE]; /* the actual data */
+ pthread_mutex_t lock; /* mutex ensuring exclusive access to buffer */
+ int readpos, writepos; /* positions for reading and writing */
+ pthread_cond_t notempty; /* signaled when buffer is not empty */
+ pthread_cond_t notfull; /* signaled when buffer is not full */
+};
+
+/* Initialize a buffer */
+static void
+init (struct prodcons *b)
+{
+ pthread_mutex_init (&b->lock, NULL);
+ pthread_cond_init (&b->notempty, NULL);
+ pthread_cond_init (&b->notfull, NULL);
+ b->readpos = 0;
+ b->writepos = 0;
+}
+
+/* Store an integer in the buffer */
+static void
+put (struct prodcons *b, int data)
+{
+ pthread_mutex_lock (&b->lock);
+ /* Wait until buffer is not full */
+ while ((b->writepos + 1) % BUFFER_SIZE == b->readpos)
+ {
+ pthread_cond_wait (&b->notfull, &b->lock);
+ /* pthread_cond_wait reacquired b->lock before returning */
+ }
+ /* Write the data and advance write pointer */
+ b->buffer[b->writepos] = data;
+ b->writepos++;
+ if (b->writepos >= BUFFER_SIZE)
+ b->writepos = 0;
+ /* Signal that the buffer is now not empty */
+ pthread_cond_signal (&b->notempty);
+ pthread_mutex_unlock (&b->lock);
+}
+
+/* Read and remove an integer from the buffer */
+static int
+get (struct prodcons *b)
+{
+ int data;
+ pthread_mutex_lock (&b->lock);
+ /* Wait until buffer is not empty */
+ while (b->writepos == b->readpos)
+ {
+ pthread_cond_wait (&b->notempty, &b->lock);
+ }
+ /* Read the data and advance read pointer */
+ data = b->buffer[b->readpos];
+ b->readpos++;
+ if (b->readpos >= BUFFER_SIZE)
+ b->readpos = 0;
+ /* Signal that the buffer is now not full */
+ pthread_cond_signal (&b->notfull);
+ pthread_mutex_unlock (&b->lock);
+ return data;
+}
+
+/* A test program: one thread inserts integers from 1 to 10000,
+ the other reads them and prints them. */
+
+#define OVER (-1)
+
+struct prodcons buffer;
+
+static void *
+producer (void *data)
+{
+ int n;
+ for (n = 0; n < 10000; n++)
+ {
+ printf ("%d --->\n", n);
+ put (&buffer, n);
+ }
+ put (&buffer, OVER);
+ return NULL;
+}
+
+static void *
+consumer (void *data)
+{
+ int d;
+ while (1)
+ {
+ d = get (&buffer);
+ if (d == OVER)
+ break;
+ printf ("---> %d\n", d);
+ }
+ return NULL;
+}
+
+int
+main (void)
+{
+ pthread_t th_a, th_b;
+ void *retval;
+
+ init (&buffer);
+ /* Create the threads */
+ pthread_create (&th_a, NULL, producer, 0);
+ pthread_create (&th_b, NULL, consumer, 0);
+ /* Wait until producer and consumer finish. */
+ pthread_join (th_a, &retval);
+ pthread_join (th_b, &retval);
+ return 0;
+}
diff --git a/linuxthreads/Examples/ex3.c b/linuxthreads/Examples/ex3.c
new file mode 100644
index 0000000000..b80b323a33
--- /dev/null
+++ b/linuxthreads/Examples/ex3.c
@@ -0,0 +1,152 @@
+/* Multi-thread searching.
+ Illustrates: thread cancellation, cleanup handlers. */
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <pthread.h>
+
+/* Defines the number of searching threads */
+#define NUM_THREADS 5
+
+/* Function prototypes */
+void *search(void *);
+void print_it(void *);
+
+/* Global variables */
+pthread_t threads[NUM_THREADS];
+pthread_mutex_t lock;
+int tries;
+volatile int started;
+
+int main(int argc, char ** argv)
+{
+ int i;
+ int pid;
+
+ /* create a number to search for */
+ pid = getpid();
+ printf("Searching for the number = %d...\n", pid);
+
+ /* Initialize the mutex lock */
+ pthread_mutex_init(&lock, NULL);
+
+ /* Create the searching threads */
+ for (started=0; started<NUM_THREADS; started++)
+ pthread_create(&threads[started], NULL, search, (void *) (long int) pid);
+
+ /* Wait for (join) all the searching threads */
+ for (i=0; i<NUM_THREADS; i++)
+ pthread_join(threads[i], NULL);
+
+ printf("It took %d tries to find the number.\n", tries);
+
+ /* Exit the program */
+ return 0;
+}
+
+/* This is the cleanup function that is called
+ when the threads are cancelled */
+
+void print_it(void *arg)
+{
+ int *try = (int *) arg;
+ pthread_t tid;
+
+ /* Get the calling thread's ID */
+ tid = pthread_self();
+
+ /* Print where the thread was in its search when it was cancelled */
+ printf("Thread %lx was canceled on its %d try.\n", tid, *try);
+}
+
+/* This is the search routine that is executed in each thread */
+
+void *search(void *arg)
+{
+ int num = (long int) arg;
+ int i, j, ntries;
+ pthread_t tid;
+
+ /* get the calling thread ID */
+ tid = pthread_self();
+
+ /* use the thread ID to set the seed for the random number generator */
+ /* Since srand and rand are not thread-safe, serialize with lock */
+
+ /* Try to lock the mutex lock --
+ if locked, check to see if the thread has been cancelled
+ if not locked then continue */
+ while (pthread_mutex_trylock(&lock) == EBUSY)
+ pthread_testcancel();
+
+ srand((int)tid);
+ i = rand() & 0xFFFFFF;
+ pthread_mutex_unlock(&lock);
+ ntries = 0;
+
+ /* Set the cancellation parameters --
+ - Enable thread cancellation
+ - Defer the action of the cancellation */
+
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+ pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
+
+ while (started < NUM_THREADS)
+ sched_yield ();
+
+ /* Push the cleanup routine (print_it) onto the thread
+ cleanup stack. This routine will be called when the
+ thread is cancelled. Also note that the pthread_cleanup_push
+ call must have a matching pthread_cleanup_pop call. The
+ push and pop calls MUST be at the same lexical level
+ within the code */
+
+ /* Pass address of `ntries' since the current value of `ntries' is not
+ the one we want to use in the cleanup function */
+
+ pthread_cleanup_push(print_it, (void *)&ntries);
+
+ /* Loop forever */
+ while (1) {
+ i = (i + 1) & 0xFFFFFF;
+ ntries++;
+
+ /* Does the random number match the target number? */
+ if (num == i) {
+ /* Try to lock the mutex lock --
+ if locked, check to see if the thread has been cancelled
+ if not locked then continue */
+ while (pthread_mutex_trylock(&lock) == EBUSY)
+ pthread_testcancel();
+
+ /* Set the global variable for the number of tries */
+ tries = ntries;
+ printf("Thread %lx found the number!\n", tid);
+
+ /* Cancel all the other threads */
+ for (j=0; j<NUM_THREADS; j++)
+ if (threads[j] != tid) pthread_cancel(threads[j]);
+
+ /* Break out of the while loop */
+ break;
+ }
+
+ /* Every 100 tries check to see if the thread has been cancelled. */
+ if (ntries % 100 == 0) {
+ pthread_testcancel();
+ }
+ }
+
+ /* The only way we can get here is when the thread breaks out
+ of the while loop. In this case the thread that makes it here
+ has found the number we are looking for and does not need to run
+ the thread cleanup function. This is why the pthread_cleanup_pop
+ function is called with a 0 argument; this will pop the cleanup
+ function off the stack without executing it */
+
+ pthread_cleanup_pop(0);
+ return((void *)0);
+}
diff --git a/linuxthreads/Examples/ex4.c b/linuxthreads/Examples/ex4.c
new file mode 100644
index 0000000000..5c8b929e22
--- /dev/null
+++ b/linuxthreads/Examples/ex4.c
@@ -0,0 +1,115 @@
+/* Making a library function that uses static variables thread-safe.
+ Illustrates: thread-specific data, pthread_once(). */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+
+/* This is a typical example of a library function that uses
+ static variables to accumulate results between calls.
+ Here, it just returns the concatenation of all string arguments
+ that were given to it. */
+
+#if 0
+
+char *
+str_accumulate (char *s)
+{
+ static char accu[1024] = { 0 };
+ strcat (accu, s);
+ return accu;
+}
+
+#endif
+
+/* Of course, this cannot be used in a multi-threaded program
+ because all threads store "accu" at the same location.
+ So, we'll use thread-specific data to have a different "accu"
+ for each thread. */
+
+/* Key identifying the thread-specific data */
+static pthread_key_t str_key;
+/* "Once" variable ensuring that the key for str_alloc will be allocated
+ exactly once. */
+static pthread_once_t str_alloc_key_once = PTHREAD_ONCE_INIT;
+
+/* Forward functions */
+static void str_alloc_key (void);
+static void str_alloc_destroy_accu (void *accu);
+
+/* Thread-safe version of str_accumulate */
+
+static char *
+str_accumulate (const char *s)
+{
+ char *accu;
+
+ /* Make sure the key is allocated */
+ pthread_once (&str_alloc_key_once, str_alloc_key);
+ /* Get the thread-specific data associated with the key */
+ accu = (char *) pthread_getspecific (str_key);
+ /* It's initially NULL, meaning that we must allocate the buffer first. */
+ if (accu == NULL)
+ {
+ accu = malloc (1024);
+ if (accu == NULL)
+ return NULL;
+ accu[0] = 0;
+ /* Store the buffer pointer in the thread-specific data. */
+ pthread_setspecific (str_key, (void *) accu);
+ printf ("Thread %lx: allocating buffer at %p\n", pthread_self (), accu);
+ }
+ /* Now we can use accu just as in the non thread-safe code. */
+ strcat (accu, s);
+ return accu;
+}
+
+/* Function to allocate the key for str_alloc thread-specific data. */
+
+static void
+str_alloc_key (void)
+{
+ pthread_key_create (&str_key, str_alloc_destroy_accu);
+ printf ("Thread %lx: allocated key %d\n", pthread_self (), str_key);
+}
+
+/* Function to free the buffer when the thread exits. */
+/* Called only when the thread-specific data is not NULL. */
+
+static void
+str_alloc_destroy_accu (void *accu)
+{
+ printf ("Thread %lx: freeing buffer at %p\n", pthread_self (), accu);
+ free (accu);
+}
+
+/* Test program */
+
+static void *
+process (void *arg)
+{
+ char *res;
+ res = str_accumulate ("Result of ");
+ res = str_accumulate ((char *) arg);
+ res = str_accumulate (" thread");
+ printf ("Thread %lx: \"%s\"\n", pthread_self (), res);
+ return NULL;
+}
+
+int
+main (int argc, char **argv)
+{
+ char *res;
+ pthread_t th1, th2;
+
+ res = str_accumulate ("Result of ");
+ pthread_create (&th1, NULL, process, (void *) "first");
+ pthread_create (&th2, NULL, process, (void *) "second");
+ res = str_accumulate ("initial thread");
+ printf ("Thread %lx: \"%s\"\n", pthread_self (), res);
+ pthread_join (th1, NULL);
+ pthread_join (th2, NULL);
+ return 0;
+}
diff --git a/linuxthreads/Examples/ex5.c b/linuxthreads/Examples/ex5.c
new file mode 100644
index 0000000000..d39d487603
--- /dev/null
+++ b/linuxthreads/Examples/ex5.c
@@ -0,0 +1,114 @@
+/* The classic producer-consumer example, implemented with semaphores.
+ All integers between 0 and 9999 should be printed exactly twice,
+ once to the right of the arrow and once to the left. */
+
+#include <stdio.h>
+#include "pthread.h"
+#include "semaphore.h"
+
+#define BUFFER_SIZE 16
+
+/* Circular buffer of integers. */
+
+struct prodcons
+{
+ int buffer[BUFFER_SIZE]; /* the actual data */
+ int readpos, writepos; /* positions for reading and writing */
+ sem_t sem_read; /* number of elements available for reading */
+ sem_t sem_write; /* number of locations available for writing */
+};
+
+/* Initialize a buffer */
+
+static void
+init (struct prodcons *b)
+{
+ sem_init (&b->sem_write, 0, BUFFER_SIZE - 1);
+ sem_init (&b->sem_read, 0, 0);
+ b->readpos = 0;
+ b->writepos = 0;
+}
+
+/* Store an integer in the buffer */
+
+static void
+put (struct prodcons *b, int data)
+{
+ /* Wait until buffer is not full */
+ sem_wait (&b->sem_write);
+ /* Write the data and advance write pointer */
+ b->buffer[b->writepos] = data;
+ b->writepos++;
+ if (b->writepos >= BUFFER_SIZE)
+ b->writepos = 0;
+ /* Signal that the buffer contains one more element for reading */
+ sem_post (&b->sem_read);
+}
+
+/* Read and remove an integer from the buffer */
+
+static int
+get (struct prodcons *b)
+{
+ int data;
+ /* Wait until buffer is not empty */
+ sem_wait (&b->sem_read);
+ /* Read the data and advance read pointer */
+ data = b->buffer[b->readpos];
+ b->readpos++;
+ if (b->readpos >= BUFFER_SIZE)
+ b->readpos = 0;
+ /* Signal that the buffer has now one more location for writing */
+ sem_post (&b->sem_write);
+ return data;
+}
+
+/* A test program: one thread inserts integers from 1 to 10000,
+ the other reads them and prints them. */
+
+#define OVER (-1)
+
+struct prodcons buffer;
+
+static void *
+producer (void *data)
+{
+ int n;
+ for (n = 0; n < 10000; n++)
+ {
+ printf ("%d --->\n", n);
+ put (&buffer, n);
+ }
+ put (&buffer, OVER);
+ return NULL;
+}
+
+static void *
+consumer (void *data)
+{
+ int d;
+ while (1)
+ {
+ d = get (&buffer);
+ if (d == OVER)
+ break;
+ printf ("---> %d\n", d);
+ }
+ return NULL;
+}
+
+int
+main (void)
+{
+ pthread_t th_a, th_b;
+ void *retval;
+
+ init (&buffer);
+ /* Create the threads */
+ pthread_create (&th_a, NULL, producer, 0);
+ pthread_create (&th_b, NULL, consumer, 0);
+ /* Wait until producer and consumer finish. */
+ pthread_join (th_a, &retval);
+ pthread_join (th_b, &retval);
+ return 0;
+}
diff --git a/linuxthreads/Examples/ex6.c b/linuxthreads/Examples/ex6.c
new file mode 100644
index 0000000000..9a0266828b
--- /dev/null
+++ b/linuxthreads/Examples/ex6.c
@@ -0,0 +1,46 @@
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+
+static void *
+test_thread (void *v_param)
+{
+ return NULL;
+}
+
+int
+main (void)
+{
+ unsigned long count;
+
+ setvbuf (stdout, NULL, _IONBF, 0);
+
+ for (count = 0; count < 2000; ++count)
+ {
+ pthread_t thread;
+ int status;
+
+ status = pthread_create (&thread, NULL, test_thread, NULL);
+ if (status != 0)
+ {
+ printf ("status = %d, count = %lu: %s\n", status, count,
+ strerror (errno));
+ return 1;
+ }
+ else
+ {
+ printf ("count = %lu\n", count);
+ }
+ /* pthread_detach (thread); */
+ int err = pthread_join (thread, NULL);
+ if (err != 0)
+ {
+ printf ("join failed (%s), count %lu\n", strerror (err), count);
+ return 2;
+ }
+ usleep (10);
+ }
+ return 0;
+}
diff --git a/linuxthreads/Examples/ex7.c b/linuxthreads/Examples/ex7.c
new file mode 100644
index 0000000000..d9db33c5cd
--- /dev/null
+++ b/linuxthreads/Examples/ex7.c
@@ -0,0 +1,45 @@
+/* This is a test of the special shutdown that occurs
+ when all threads, including the main one, call
+ pthread_exit(). It demonstrates that atexit
+ handlers are properly called, and that the
+ output is properly flushed even when stdout is
+ redirected to a file, and therefore fully buffered. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#define NTHREADS 20 /* number of threads */
+
+static void *
+thread (void *arg)
+{
+ printf ("thread terminating\n");
+ return 0;
+}
+
+static void
+cleanup (void)
+{
+ printf ("atexit handler called\n");
+}
+
+int
+main (void)
+{
+ int i;
+
+ atexit (cleanup);
+
+ for (i = 0; i < NTHREADS; i++)
+ {
+ pthread_t id;
+ if (pthread_create (&id, 0, thread, 0) != 0)
+ {
+ fprintf (stderr, "pthread_create failed\n");
+ abort ();
+ }
+ }
+
+ pthread_exit (0);
+}
diff --git a/linuxthreads/Examples/ex8.c b/linuxthreads/Examples/ex8.c
new file mode 100644
index 0000000000..bda81b9c61
--- /dev/null
+++ b/linuxthreads/Examples/ex8.c
@@ -0,0 +1,101 @@
+/* Tests for fork in multi-threaded environment.
+ Copyright (C) 2000 Free Software Foundation, Inc.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <errno.h>
+#include <error.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+enum
+{
+ PREPARE_BIT = 1,
+ PARENT_BIT = 2,
+ CHILD_BIT = 4
+};
+
+static int var;
+
+static void
+prepare (void)
+{
+ var |= PREPARE_BIT;
+}
+
+static void
+parent (void)
+{
+ var |= PARENT_BIT;
+}
+
+static void
+child (void)
+{
+ var |= CHILD_BIT;
+}
+
+
+static void *thread (void *arg);
+
+
+int
+main (void)
+{
+ pthread_t th;
+ void *res;
+
+ pthread_atfork (prepare, parent, child);
+
+ if (pthread_create (&th, NULL, thread, NULL) != 0)
+ error (EXIT_FAILURE, 0, "cannot create thread");
+
+ pthread_join (th, &res);
+
+ return (int) (long int) res;
+}
+
+
+static void *
+thread (void *arg)
+{
+ int status;
+ pid_t pid;
+
+ pid = fork ();
+ if (pid == 0)
+ {
+ /* We check whether the `prepare' and `child' function ran. */
+ exit (var != (PREPARE_BIT | CHILD_BIT));
+ }
+ else if (pid == (pid_t) -1)
+ error (EXIT_FAILURE, errno, "cannot fork");
+
+ if (waitpid (pid, &status, 0) != pid)
+ error (EXIT_FAILURE, errno, "wrong child");
+
+ if (WTERMSIG (status) != 0)
+ error (EXIT_FAILURE, 0, "Child terminated incorrectly");
+ status = WEXITSTATUS (status);
+
+ if (status == 0)
+ status = var != (PREPARE_BIT | PARENT_BIT);
+
+ return (void *) (long int) status;
+}
diff --git a/linuxthreads/Examples/ex9.c b/linuxthreads/Examples/ex9.c
new file mode 100644
index 0000000000..3c8b8142e1
--- /dev/null
+++ b/linuxthreads/Examples/ex9.c
@@ -0,0 +1,98 @@
+/* Tests for pthread_barrier_* functions.
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+ Contributed by Kaz Kylheku <kaz@ashi.footprints.net>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <errno.h>
+#include <error.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#define NUM_THREADS 10
+#define NUM_ITERS 500
+
+static void *thread (void *) __attribute__ ((__noreturn__));
+static pthread_barrier_t barrier;
+
+int
+main (void)
+{
+ pthread_t thread_list[NUM_THREADS];
+ int i;
+
+ if (pthread_barrier_init (&barrier, NULL, NUM_THREADS + 1) != 0)
+ error (EXIT_FAILURE, 0, "cannot initialize barrier");
+
+ for (i = 0; i < NUM_THREADS; i++)
+ {
+ if (pthread_create (&thread_list[i], NULL, thread, NULL) != 0)
+ error (EXIT_FAILURE, 0, "cannot create thread");
+ }
+
+ (void) thread (NULL);
+
+ for (i = 0; i < NUM_THREADS; i++)
+ {
+ pthread_join(thread_list[i], NULL);
+ }
+
+ return 0;
+}
+
+
+static void *
+thread (void *arg)
+{
+ int i;
+ pthread_t self = pthread_self ();
+ static pthread_t last_serial_thread;
+ static int linecount; /* protected by flockfile(stdout) */
+
+ for (i = 0; i < NUM_ITERS; i++)
+ {
+ switch (pthread_barrier_wait (&barrier))
+ {
+ case 0:
+ flockfile (stdout);
+ printf ("%04d: non-serial thread %lu\n", ++linecount,
+ (unsigned long) self);
+ funlockfile (stdout);
+ break;
+ case PTHREAD_BARRIER_SERIAL_THREAD:
+ flockfile (stdout);
+ printf ("%04d: serial thread %lu\n", ++linecount,
+ (unsigned long) self);
+ funlockfile (stdout);
+ last_serial_thread = self;
+ break;
+ default:
+ /* Huh? */
+ error (EXIT_FAILURE, 0, "unexpected return value from barrier wait");
+ }
+ }
+
+ if (pthread_equal (self, last_serial_thread))
+ {
+ flockfile (stdout);
+ printf ("%04d: last serial thread %lu terminating process\n",
+ ++linecount, (unsigned long) self);
+ funlockfile (stdout);
+ }
+
+ pthread_exit(NULL);
+}
diff --git a/linuxthreads/Examples/tststatic.c b/linuxthreads/Examples/tststatic.c
new file mode 100644
index 0000000000..421011a3c4
--- /dev/null
+++ b/linuxthreads/Examples/tststatic.c
@@ -0,0 +1 @@
+#include "ex1.c"