[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit

Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/ap/build/uClibc/test/pthread/Makefile b/ap/build/uClibc/test/pthread/Makefile
new file mode 100644
index 0000000..d6f00d6
--- /dev/null
+++ b/ap/build/uClibc/test/pthread/Makefile
@@ -0,0 +1,7 @@
+# uClibc pthread tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+top_builddir=../../
+include ../Rules.mak
+-include Makefile.in
+include ../Test.mak
diff --git a/ap/build/uClibc/test/pthread/Makefile.in b/ap/build/uClibc/test/pthread/Makefile.in
new file mode 100644
index 0000000..c50748d
--- /dev/null
+++ b/ap/build/uClibc/test/pthread/Makefile.in
@@ -0,0 +1,8 @@
+# uClibc pthread tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+TESTS_DISABLED += cancellation-points
+
+EXTRA_LDFLAGS := -lpthread
+
+LDFLAGS_cancellation-points := -lrt
diff --git a/ap/build/uClibc/test/pthread/cancellation-points.c b/ap/build/uClibc/test/pthread/cancellation-points.c
new file mode 100644
index 0000000..5453060
--- /dev/null
+++ b/ap/build/uClibc/test/pthread/cancellation-points.c
@@ -0,0 +1,286 @@
+/*
+ * Make sure functions marked as cancellation points actually are.
+ * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_09.html#tag_02_09_05
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <features.h>
+#include <sys/ipc.h>
+#include <sys/mman.h>
+#include <sys/msg.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <mqueue.h>
+#include <poll.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <time.h>
+#include <unistd.h>
+
+/* take care of optional things ... */
+#define STUB(func, args) static void func args { sleep(0); }
+#if defined(__UCLIBC_AIO__)
+# include <aio.h>
+#else
+STUB(aio_suspend, (void *p, int n, const void *p2))
+#endif
+#if defined(__UCLIBC_STROPTS__)
+# include <stropts.h>
+#else
+STUB(getmsg, (int f, void *p, void *p2, void *p3))
+STUB(getpmsg, (int f, void *p, void *p2, void *p3, void *p4))
+STUB(putmsg, (int f, void *p, void *p2, void *p3))
+STUB(putpmsg, (int f, void *p, void *p2, void *p3, void *p4))
+#endif
+#if defined(__UCLIBC__)
+STUB(clock_nanosleep, (int i, int f, const void *p, void *p2))
+#endif
+
+int cnt;
+bool ready;
+
+void cancel_timeout(int sig)
+{
+	ready = false;
+}
+void cancel_thread_cleanup(void *arg)
+{
+	ready = false;
+}
+
+/* some funcs need some help as they wont take NULL args ... */
+const struct timespec zero_sec = { .tv_sec = 0, .tv_nsec = 0 };
+
+sem_t sem;
+void help_sem_setup(void)
+{
+	if (sem_init(&sem, 0, 1) == -1) {
+		perror("sem_init() failed");
+		exit(-1);
+	}
+}
+
+pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+pthread_mutex_t mutex;
+void help_pthread_setup(void)
+{
+	pthread_mutex_init(&mutex, NULL);
+	pthread_mutex_lock(&mutex);
+}
+
+/* the pthread function that will call the cancellable function over and over */
+#define _MAKE_CANCEL_THREAD_FUNC_EX(func, sysfunc, args, setup) \
+void *cancel_thread_##func(void *arg) \
+{ \
+	if (pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL)) { \
+		perror("unable to set cancel type to deferred; something is seriously broken"); \
+		exit(-1); \
+	} \
+	pthread_cleanup_push(cancel_thread_cleanup, NULL); \
+	setup; \
+	ready = true; \
+	while (ready) \
+		sysfunc args; \
+	pthread_cleanup_pop(1); \
+	return NULL; \
+}
+#define MAKE_CANCEL_THREAD_FUNC_RE(func, sysfunc, args) _MAKE_CANCEL_THREAD_FUNC_EX(func, sysfunc, args, (void)0)
+#define MAKE_CANCEL_THREAD_FUNC_EX(func, args, setup)   _MAKE_CANCEL_THREAD_FUNC_EX(func, func, args, setup)
+#define MAKE_CANCEL_THREAD_FUNC(func, args)             _MAKE_CANCEL_THREAD_FUNC_EX(func, func, args, (void)0)
+
+MAKE_CANCEL_THREAD_FUNC(accept, (-1, NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC(aio_suspend, (NULL, 0, &zero_sec))
+MAKE_CANCEL_THREAD_FUNC(clock_nanosleep, (0, 0, NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC(close, (-1))
+MAKE_CANCEL_THREAD_FUNC(connect, (-1, NULL, 0))
+MAKE_CANCEL_THREAD_FUNC(creat, ("", 0))
+MAKE_CANCEL_THREAD_FUNC(fcntl, (0, F_SETLKW, NULL))
+MAKE_CANCEL_THREAD_FUNC(fdatasync, (-1))
+MAKE_CANCEL_THREAD_FUNC(fsync, (0))
+MAKE_CANCEL_THREAD_FUNC(getmsg, (-1, NULL, NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC(getpmsg, (-1, NULL, NULL, NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC(lockf, (-1, F_TEST, 0))
+MAKE_CANCEL_THREAD_FUNC(mq_receive, (0, NULL, 0, NULL))
+MAKE_CANCEL_THREAD_FUNC(mq_send, (0, NULL, 0, 0))
+MAKE_CANCEL_THREAD_FUNC(mq_timedreceive, (0, NULL, 0, NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC(mq_timedsend, (0, NULL, 0, 0, NULL))
+MAKE_CANCEL_THREAD_FUNC(msgrcv, (-1, NULL, 0, 0, 0))
+MAKE_CANCEL_THREAD_FUNC(msgsnd, (-1, NULL, 0, 0))
+MAKE_CANCEL_THREAD_FUNC(msync, (NULL, 0, 0))
+MAKE_CANCEL_THREAD_FUNC(nanosleep, (NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC(open, ("", 0))
+MAKE_CANCEL_THREAD_FUNC(pause, ())
+MAKE_CANCEL_THREAD_FUNC(poll, (NULL, 0, 0))
+MAKE_CANCEL_THREAD_FUNC(pread, (-1, NULL, 0, 0))
+MAKE_CANCEL_THREAD_FUNC(pselect, (0, NULL, NULL, NULL, NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC_EX(pthread_cond_timedwait, (&cond, &mutex, &zero_sec), help_pthread_setup())
+MAKE_CANCEL_THREAD_FUNC_EX(pthread_cond_wait, (&cond, &mutex), help_pthread_setup())
+/*MAKE_CANCEL_THREAD_FUNC_EX(pthread_join, (0, NULL))*/
+MAKE_CANCEL_THREAD_FUNC(pthread_testcancel, ())
+MAKE_CANCEL_THREAD_FUNC(putmsg, (-1, NULL, NULL, 0))
+MAKE_CANCEL_THREAD_FUNC(putpmsg, (-1, NULL, NULL, 0, 0))
+MAKE_CANCEL_THREAD_FUNC(pwrite, (-1, NULL, 0, 0))
+MAKE_CANCEL_THREAD_FUNC(read, (-1, NULL, 0))
+MAKE_CANCEL_THREAD_FUNC(readv, (-1, NULL, 0))
+MAKE_CANCEL_THREAD_FUNC(recv, (-1, NULL, 0, 0))
+MAKE_CANCEL_THREAD_FUNC(recvfrom, (-1, NULL, 0, 0, NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC(recvmsg, (-1, NULL, 0))
+MAKE_CANCEL_THREAD_FUNC(select, (0, NULL, NULL, NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC_EX(sem_timedwait, (&sem, &zero_sec), help_sem_setup())
+MAKE_CANCEL_THREAD_FUNC_EX(sem_wait, (&sem), help_sem_setup())
+MAKE_CANCEL_THREAD_FUNC(send, (-1, NULL, 0, 0))
+MAKE_CANCEL_THREAD_FUNC(sendmsg, (-1, NULL, 0))
+MAKE_CANCEL_THREAD_FUNC(sendto, (-1, NULL, 0, 0, NULL, 0))
+#ifdef __UCLIBC_SUSV4_LEGACY__
+MAKE_CANCEL_THREAD_FUNC(sigpause, (0))
+#endif
+MAKE_CANCEL_THREAD_FUNC(sigsuspend, (NULL))
+MAKE_CANCEL_THREAD_FUNC(sigtimedwait, (NULL, NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC(sigwait, (NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC(sigwaitinfo, (NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC(sleep, (0))
+MAKE_CANCEL_THREAD_FUNC(system, (""))
+MAKE_CANCEL_THREAD_FUNC(tcdrain, (-1))
+#ifdef __UCLIBC_SUSV3_LEGACY__
+MAKE_CANCEL_THREAD_FUNC(usleep, (0))
+#endif
+MAKE_CANCEL_THREAD_FUNC(wait, (NULL))
+MAKE_CANCEL_THREAD_FUNC(waitid, (0, 0, NULL, 0))
+MAKE_CANCEL_THREAD_FUNC(waitpid, (-1, NULL, 0))
+MAKE_CANCEL_THREAD_FUNC(write, (-1, NULL, 0))
+MAKE_CANCEL_THREAD_FUNC(writev, (-1, NULL, 0))
+
+/* test a few variations that should not cancel ... */
+MAKE_CANCEL_THREAD_FUNC_RE(fcntl_another, fcntl, (0, F_GETFD))
+
+/* main test that creates thread, cancels it, etc... */
+int _test_func(const char *func_name, void *(*func)(void*), const int should_cancel)
+{
+	int ret;
+	pthread_t cancel_thread_id;
+
+	++cnt;
+
+	printf("testing %-30s ", func_name);
+
+	printf(".");
+	if (signal(SIGALRM, cancel_timeout) == SIG_ERR) {
+		perror("unable to bind SIGALRM");
+		exit(-1);
+	}
+
+	printf(".");
+	ready = false;
+	pthread_create(&cancel_thread_id, NULL, func, NULL);
+
+	printf(".");
+	while (!ready)
+		sched_yield();
+
+	printf(".");
+	if (pthread_cancel(cancel_thread_id)) {
+		perror("unable to cancel thread");
+		exit(-1);
+	}
+
+	printf(".");
+	alarm(5);
+	while (ready)
+		sched_yield();
+
+	printf(".");
+	ret = (!!!alarm(0) == should_cancel);
+
+	if (ret)
+		printf(" failed ;(\n");
+	else
+		printf(" OK!\n");
+
+	return ret;
+}
+#define TEST_FUNC(f)    _test_func(#f, cancel_thread_##f, 1)
+#define TEST_FUNC_RE(f) _test_func(#f, cancel_thread_##f, 0)
+
+int main(int argc, char *argv[])
+{
+	int ret = 0;
+	setbuf(stdout, NULL);
+	cnt = 0;
+
+	ret += TEST_FUNC(accept);
+	ret += TEST_FUNC(aio_suspend);
+	ret += TEST_FUNC(clock_nanosleep);
+	ret += TEST_FUNC(close);
+	ret += TEST_FUNC(connect);
+	ret += TEST_FUNC(creat);
+	ret += TEST_FUNC(fcntl);
+	ret += TEST_FUNC(fdatasync);
+	ret += TEST_FUNC(fsync);
+	ret += TEST_FUNC(getmsg);
+	ret += TEST_FUNC(getpmsg);
+	ret += TEST_FUNC(lockf);
+	ret += TEST_FUNC(mq_receive);
+	ret += TEST_FUNC(mq_send);
+	ret += TEST_FUNC(mq_timedreceive);
+	ret += TEST_FUNC(mq_timedsend);
+	ret += TEST_FUNC(msgrcv);
+	ret += TEST_FUNC(msgsnd);
+	ret += TEST_FUNC(msync);
+	ret += TEST_FUNC(nanosleep);
+	ret += TEST_FUNC(open);
+	ret += TEST_FUNC(pause);
+	ret += TEST_FUNC(poll);
+	ret += TEST_FUNC(pread);
+	ret += TEST_FUNC(pselect);
+	ret += TEST_FUNC(pthread_cond_timedwait);
+	ret += TEST_FUNC(pthread_cond_wait);
+	/*ret += TEST_FUNC(pthread_join);*/
+	ret += TEST_FUNC(pthread_testcancel);
+	ret += TEST_FUNC(putmsg);
+	ret += TEST_FUNC(putpmsg);
+	ret += TEST_FUNC(pwrite);
+	ret += TEST_FUNC(read);
+	ret += TEST_FUNC(readv);
+	ret += TEST_FUNC(recv);
+	ret += TEST_FUNC(recvfrom);
+	ret += TEST_FUNC(recvmsg);
+	ret += TEST_FUNC(select);
+	ret += TEST_FUNC(sem_timedwait);
+	ret += TEST_FUNC(sem_wait);
+	ret += TEST_FUNC(send);
+	ret += TEST_FUNC(sendmsg);
+	ret += TEST_FUNC(sendto);
+	ret += TEST_FUNC(sigpause);
+	ret += TEST_FUNC(sigsuspend);
+	ret += TEST_FUNC(sigtimedwait);
+	ret += TEST_FUNC(sigwait);
+	ret += TEST_FUNC(sigwaitinfo);
+	ret += TEST_FUNC(sleep);
+	ret += TEST_FUNC(system);
+	ret += TEST_FUNC(tcdrain);
+#ifdef __UCLIBC_SUSV3_LEGACY__
+	ret += TEST_FUNC(usleep);
+#endif
+	ret += TEST_FUNC(wait);
+	ret += TEST_FUNC(waitid);
+	ret += TEST_FUNC(waitpid);
+	ret += TEST_FUNC(write);
+	ret += TEST_FUNC(writev);
+
+	ret += TEST_FUNC_RE(fcntl_another);
+
+	if (ret)
+		printf("!!! %i / %i tests failed\n", ret, cnt);
+
+	return ret;
+}
diff --git a/ap/build/uClibc/test/pthread/ex1.c b/ap/build/uClibc/test/pthread/ex1.c
new file mode 100644
index 0000000..4d9de03
--- /dev/null
+++ b/ap/build/uClibc/test/pthread/ex1.c
@@ -0,0 +1,35 @@
+/* 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;
+	printf("Starting process %s\n", (char *)arg);
+	for (i = 0; i < 10000; i++)
+		write(1, (char *) arg, 1);
+	return NULL;
+}
+
+#define sucfail(r) (r != 0 ? "failed" : "succeeded")
+int main(void)
+{
+	int pret, ret = 0;
+	pthread_t th_a, th_b;
+	void *retval;
+
+	ret += (pret = pthread_create(&th_a, NULL, process, (void *)"a"));
+	printf("create a %s %d\n", sucfail(pret), pret);
+	ret += (pret = pthread_create(&th_b, NULL, process, (void *)"b"));
+	printf("create b %s %d\n", sucfail(pret), pret);
+	ret += (pret = pthread_join(th_a, &retval));
+	printf("join a %s %d\n", sucfail(pret), pret);
+	ret += (pret = pthread_join(th_b, &retval));
+	printf("join b %s %d\n", sucfail(pret), pret);
+	return ret;
+}
diff --git a/ap/build/uClibc/test/pthread/ex2.c b/ap/build/uClibc/test/pthread/ex2.c
new file mode 100644
index 0000000..98bd4b3
--- /dev/null
+++ b/ap/build/uClibc/test/pthread/ex2.c
@@ -0,0 +1,113 @@
+/* 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/ap/build/uClibc/test/pthread/ex3.c b/ap/build/uClibc/test/pthread/ex3.c
new file mode 100644
index 0000000..8ef7797
--- /dev/null
+++ b/ap/build/uClibc/test/pthread/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)
+{
+  unsigned long i;
+  unsigned long pid;
+
+  /* create a number to search for */
+  pid = getpid();
+  printf("Searching for the number = %ld...\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 *)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)
+{
+  unsigned long num = (unsigned long) arg;
+  unsigned long 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/ap/build/uClibc/test/pthread/ex4.c b/ap/build/uClibc/test/pthread/ex4.c
new file mode 100644
index 0000000..cf4cf1d
--- /dev/null
+++ b/ap/build/uClibc/test/pthread/ex4.c
@@ -0,0 +1,107 @@
+/* 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
+
+static 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);
+  exit(0);
+}
diff --git a/ap/build/uClibc/test/pthread/ex5.c b/ap/build/uClibc/test/pthread/ex5.c
new file mode 100644
index 0000000..7a293eb
--- /dev/null
+++ b/ap/build/uClibc/test/pthread/ex5.c
@@ -0,0 +1,102 @@
+/* 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/ap/build/uClibc/test/pthread/ex6.c b/ap/build/uClibc/test/pthread/ex6.c
new file mode 100644
index 0000000..ffb6287
--- /dev/null
+++ b/ap/build/uClibc/test/pthread/ex6.c
@@ -0,0 +1,44 @@
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <time.h>
+
+static void *
+test_thread (void *v_param)
+{
+  return NULL;
+}
+
+int
+main (void)
+{
+  unsigned long count;
+  struct timespec ts;
+  ts.tv_sec = 0;
+  ts.tv_nsec = 10 * 1000;
+
+  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); */
+      pthread_join (thread, NULL);
+      nanosleep (&ts, NULL);
+    }
+  return 0;
+}
diff --git a/ap/build/uClibc/test/pthread/ex7.c b/ap/build/uClibc/test/pthread/ex7.c
new file mode 100644
index 0000000..8eeb9a2
--- /dev/null
+++ b/ap/build/uClibc/test/pthread/ex7.c
@@ -0,0 +1,106 @@
+/* ex7
+ *
+ * Test case that illustrates a timed wait on a condition variable.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <time.h>
+
+/* Our event variable using a condition variable contruct. */
+typedef struct {
+    pthread_mutex_t	mutex;
+    pthread_cond_t	cond;
+    int			flag;
+} event_t;
+
+
+/* Global event to signal main thread the timeout of the child thread. */
+event_t main_event;
+
+
+static void *
+test_thread (void *ms_param)
+{
+    unsigned long status = 0;
+    event_t foo;
+    struct timespec timeout;
+    struct timeval  now;
+    long ms = (long) ms_param;
+
+    /* initialize cond var */
+    pthread_cond_init(&foo.cond, NULL);
+    pthread_mutex_init(&foo.mutex, NULL);
+    foo.flag = 0;
+
+    /* set the time out value */
+    printf("waiting %ld ms ...\n", ms);
+    gettimeofday(&now, NULL);
+    timeout.tv_sec  = now.tv_sec + ms/1000 + (now.tv_usec + (ms%1000)*1000)/1000000;
+    timeout.tv_nsec = ((now.tv_usec + (ms%1000)*1000) % 1000000) * 1000;
+
+    /* Just use this to test the time out. The cond var is never signaled. */
+    pthread_mutex_lock(&foo.mutex);
+    while (foo.flag == 0 && status != ETIMEDOUT) {
+	status = pthread_cond_timedwait(&foo.cond, &foo.mutex, &timeout);
+    }
+    pthread_mutex_unlock(&foo.mutex);
+
+    /* post the main event */
+    pthread_mutex_lock(&main_event.mutex);
+    main_event.flag = 1;
+    pthread_cond_signal(&main_event.cond);
+    pthread_mutex_unlock(&main_event.mutex);
+
+    /* that's it, bye */
+    return (void*) status;
+}
+
+int
+main (void)
+{
+  unsigned long count;
+  struct timespec ts;
+  ts.tv_sec = 0;
+  ts.tv_nsec = 10 * 1000;
+
+  setvbuf (stdout, NULL, _IONBF, 0);
+
+  /* initialize main event cond var */
+  pthread_cond_init(&main_event.cond, NULL);
+  pthread_mutex_init(&main_event.mutex, NULL);
+  main_event.flag = 0;
+
+  for (count = 0; count < 20; ++count)
+  {
+      pthread_t thread;
+      int status;
+
+      /* pass down the milli-second timeout in the void* param */
+      status = pthread_create (&thread, NULL, test_thread, (void*) (count*100));
+      if (status != 0) {
+	  printf ("status = %d, count = %lu: %s\n", status, count,
+		  strerror (errno));
+	  return 1;
+      }
+      else {
+
+	  /* wait for the event posted by the child thread */
+	  pthread_mutex_lock(&main_event.mutex);
+	  while (main_event.flag == 0) {
+	      pthread_cond_wait(&main_event.cond, &main_event.mutex);
+	  }
+	  main_event.flag = 0;
+	  pthread_mutex_unlock(&main_event.mutex);
+
+	  printf ("count = %lu\n", count);
+      }
+
+      nanosleep (&ts, NULL);
+  }
+
+  return 0;
+}
diff --git a/ap/build/uClibc/test/pthread/tst-too-many-cleanups.c b/ap/build/uClibc/test/pthread/tst-too-many-cleanups.c
new file mode 100644
index 0000000..7828c50
--- /dev/null
+++ b/ap/build/uClibc/test/pthread/tst-too-many-cleanups.c
@@ -0,0 +1,104 @@
+/*
+ * This illustrates the bug where the cleanup function
+ * of a thread may be called too many times.
+ *
+ * main thread:
+ *  - grab mutex
+ *  - spawn thread1
+ *  - go to sleep
+ * thread1:
+ *  - register cleanup handler via pthread_cleanup_push()
+ *  - try to grab mutex and sleep
+ * main:
+ *  - kill thread1
+ *  - go to sleep
+ * thread1 cleanup handler:
+ *  - try to grab mutex and sleep
+ * main:
+ *  - kill thread1
+ *  - go to sleep
+ * thread1 cleanup handler:
+ *  - wrongly called again
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <assert.h>
+#include <unistd.h>
+
+#define warn(fmt, args...) fprintf(stderr, "[%p] " fmt, (void*)pthread_self(), ## args)
+#define warnf(fmt, args...) warn("%s:%i: " fmt, __FUNCTION__, __LINE__, ## args)
+
+int ok_to_kill_thread;
+
+static void thread_killed(void *arg);
+
+static void *KillMeThread(void *thread_par)
+{
+	pthread_t pthread_id;
+
+	warnf("Starting child thread\n");
+
+	pthread_id = pthread_self();
+	pthread_cleanup_push(thread_killed, (void *)pthread_id);
+
+	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+
+	/* main code */
+	warnf("please kill me now\n");
+	while (1) {
+		ok_to_kill_thread = 1;
+		sleep(1);
+	}
+
+	pthread_cleanup_pop(0);
+
+	return 0;
+}
+
+static void thread_killed(void *arg)
+{
+	static int num_times_called = 0;
+
+	warnf("killing %p [cnt=%i]\n", arg, ++num_times_called);
+	assert(num_times_called == 1);
+
+	/* pick any cancellation endpoint, sleep() will do just fine */
+	while (1) {
+		warnf("sleeping in cancellation endpoint ...\n");
+		sleep(1);
+	}
+
+	warnf("done cleaning up\n");
+}
+
+int main(int argc, char *argv[])
+{
+	int count = 3;
+	pthread_t app_pthread_id;
+
+	/* need to tweak this test a bit to play nice with signals and LT */
+	return 0;
+
+	ok_to_kill_thread = 0;
+
+	pthread_create(&app_pthread_id, NULL, KillMeThread, NULL);
+
+	warnf("waiting for thread to prepare itself\n");
+	while (!ok_to_kill_thread)
+		sleep(1);
+
+	while (count--) {
+		warnf("killing thread\n");
+		pthread_cancel(app_pthread_id);
+		sleep(3);
+	}
+
+	return 0;
+}