summaryrefslogtreecommitdiff
path: root/apps/examples/ostest
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-03-20 18:18:19 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-03-20 18:18:19 +0000
commiteafaeb9398216dacb92de69683ccdda6007efb1d (patch)
treee513e4fd791670d9b74d33821682d4059ed73098 /apps/examples/ostest
parentf68c474e8ae9cfa5c9124a6eb92ec06fe2bf40a1 (diff)
downloadnuttx-eafaeb9398216dacb92de69683ccdda6007efb1d.tar.gz
nuttx-eafaeb9398216dacb92de69683ccdda6007efb1d.tar.bz2
nuttx-eafaeb9398216dacb92de69683ccdda6007efb1d.zip
Move nuttx/examples to apps/examples
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3405 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'apps/examples/ostest')
-rw-r--r--apps/examples/ostest/Makefile130
-rw-r--r--apps/examples/ostest/barrier.c200
-rw-r--r--apps/examples/ostest/cancel.c333
-rw-r--r--apps/examples/ostest/cond.c294
-rw-r--r--apps/examples/ostest/dev_null.c92
-rw-r--r--apps/examples/ostest/main.c523
-rw-r--r--apps/examples/ostest/mqueue.c394
-rw-r--r--apps/examples/ostest/mutex.c142
-rw-r--r--apps/examples/ostest/ostest.h162
-rw-r--r--apps/examples/ostest/posixtimer.c268
-rw-r--r--apps/examples/ostest/prioinherit.c541
-rw-r--r--apps/examples/ostest/rmutex.c166
-rw-r--r--apps/examples/ostest/roundrobin.c232
-rw-r--r--apps/examples/ostest/sem.c246
-rw-r--r--apps/examples/ostest/sighand.c279
-rw-r--r--apps/examples/ostest/timedmqueue.c393
-rw-r--r--apps/examples/ostest/timedwait.c201
17 files changed, 4596 insertions, 0 deletions
diff --git a/apps/examples/ostest/Makefile b/apps/examples/ostest/Makefile
new file mode 100644
index 000000000..0e50db434
--- /dev/null
+++ b/apps/examples/ostest/Makefile
@@ -0,0 +1,130 @@
+############################################################################
+# apps/examples/ostest/Makefile
+#
+# Copyright (C) 2007-2011 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+#
+# 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. Neither the name NuttX 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 COPYRIGHT HOLDERS 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
+# COPYRIGHT OWNER 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 $(TOPDIR)/.config
+-include $(TOPDIR)/Make.defs
+include $(APPDIR)/Make.defs
+
+# NuttX OS Test
+
+ASRCS =
+CSRCS = main.c dev_null.c
+
+ifneq ($(CONFIG_DISABLE_PTHREAD),y)
+CSRCS += cancel.c cond.c mutex.c sem.c barrier.c
+ifneq ($(CONFIG_RR_INTERVAL),0)
+CSRCS += roundrobin.c
+endif # CONFIG_RR_INTERVAL
+ifeq ($(CONFIG_MUTEX_TYPES),y)
+CSRCS += rmutex.c
+endif # CONFIG_MUTEX_TYPES
+endif # CONFIG_DISABLE_PTHREAD
+
+ifneq ($(CONFIG_DISABLE_SIGNALS),y)
+CSRCS += sighand.c
+ifneq ($(CONFIG_DISABLE_PTHREAD),y)
+ifneq ($(CONFIG_DISABLE_CLOCK),y)
+CSRCS += timedwait.c
+endif # CONFIG_DISABLE_CLOCK
+endif # CONFIG_DISABLE_PTHREAD
+endif # CONFIG_DISABLE_SIGNALS
+
+ifneq ($(CONFIG_DISABLE_MQUEUE),y)
+ifneq ($(CONFIG_DISABLE_PTHREAD),y)
+CSRCS += mqueue.c
+ifneq ($(CONFIG_DISABLE_CLOCK),y)
+CSRCS += timedmqueue.c
+endif # CONFIG_DISABLE_CLOCK
+endif # CONFIG_DISABLE_PTHREAD
+endif # CONFIG_DISABLE_MQUEUE
+
+ifneq ($(CONFIG_DISABLE_POSIX_TIMERS),y)
+CSRCS += posixtimer.c
+endif
+
+ifneq ($(CONFIG_DISABLE_SIGNALS),y)
+ifneq ($(CONFIG_DISABLE_PTHREAD),y)
+ifeq ($(CONFIG_PRIORITY_INHERITANCE),y)
+CSRCS += prioinherit.c
+endif # CONFIG_PRIORITY_INHERITANCE
+endif # CONFIG_DISABLE_PTHREAD
+endif # CONFIG_DISABLE_SIGNALS
+
+AOBJS = $(ASRCS:.S=$(OBJEXT))
+COBJS = $(CSRCS:.c=$(OBJEXT))
+
+SRCS = $(ASRCS) $(CSRCS)
+OBJS = $(AOBJS) $(COBJS)
+
+BIN = ../../libapps$(LIBEXT)
+
+ROOTDEPPATH = --dep-path .
+
+# Common build
+
+VPATH =
+
+all: .built
+.PHONY: .built clean depend disclean
+
+$(AOBJS): %$(OBJEXT): %.S
+ $(call ASSEMBLE, $<, $@)
+
+$(COBJS): %$(OBJEXT): %.c
+ $(call COMPILE, $<, $@)
+
+$(BIN): $(OBJS)
+ @( for obj in $(OBJS) ; do \
+ $(call ARCHIVE, $@, $${obj}); \
+ done ; )
+ @touch .built
+
+.built: $(BIN)
+
+.depend: Makefile $(SRCS)
+ @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep
+ @touch $@
+
+# Register application
+depend: .depend
+
+clean:
+ @rm -f $(BIN) *.o *~ .*.swp .built
+ $(call CLEAN)
+
+distclean: clean
+ @rm -f Make.dep .depend
+
+-include Make.dep
diff --git a/apps/examples/ostest/barrier.c b/apps/examples/ostest/barrier.c
new file mode 100644
index 000000000..c88e1bed1
--- /dev/null
+++ b/apps/examples/ostest/barrier.c
@@ -0,0 +1,200 @@
+/****************************************************************************
+ * examples/ostest/barrier.c
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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. Neither the name NuttX 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#include "ostest.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+#define HALF_SECOND 500000L
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static pthread_barrier_t barrier;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: barrier_func
+ ****************************************************************************/
+
+static void *barrier_func(void *parameter)
+{
+ int id = (int)parameter;
+ int status;
+
+ printf("barrier_func: Thread %d started\n", id);
+#ifndef CONFIG_DISABLE_SIGNALS
+ usleep(HALF_SECOND);
+#endif
+
+ /* Wait at the barrier until all threads are synchronized. */
+
+ printf("barrier_func: Thread %d calling pthread_barrier_wait()\n",
+ id);
+ status = pthread_barrier_wait(&barrier);
+ if (status == 0)
+ {
+ printf("barrier_func: Thread %d, back with "
+ "status=0 (I am not special)\n",
+ id, status);
+ }
+ else if (status == PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf("barrier_func: Thread %d, back with "
+ "status=PTHREAD_BARRIER_SERIAL_THREAD (I AM SPECIAL)\n",
+ id, status);
+ }
+ else
+ {
+ printf("barrier_func: ERROR thread %d could not get semaphore value\n",
+ id);
+ }
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ usleep(HALF_SECOND);
+#endif
+ printf("barrier_func: Thread %d done\n", id);
+ return NULL;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: barrier_test
+ ****************************************************************************/
+
+void barrier_test(void)
+{
+ pthread_t barrier_thread[CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS];
+ pthread_addr_t result;
+ pthread_attr_t attr;
+ pthread_barrierattr_t barrierattr;
+ int status;
+ int i;
+
+ printf("barrier_test: Initializing barrier\n");
+
+ status = pthread_barrierattr_init(&barrierattr);
+ if (status != OK)
+ {
+ printf("barrier_test: pthread_barrierattr_init failed, status=%d\n",
+ status);
+ }
+
+ status = pthread_barrier_init(&barrier, &barrierattr,
+ CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS);
+ if (status != OK)
+ {
+ printf("barrier_test: pthread_barrierattr_init failed, status=%d\n",
+ status);
+ }
+
+ /* Create the barrier */
+
+ status = pthread_barrierattr_init(&barrierattr);
+
+ /* Start CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS thread instances */
+
+ status = pthread_attr_init(&attr);
+ if (status != OK)
+ {
+ printf("barrier_test: pthread_attr_init failed, status=%d\n",
+ status);
+ }
+
+ for (i = 0; i < CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS; i++)
+ {
+ status = pthread_create(&barrier_thread[i], &attr, barrier_func,
+ (pthread_addr_t)i);
+ if (status != 0)
+ {
+ printf("barrier_test: Error in thread %d create, status=%d\n",
+ i, status);
+ }
+ else
+ {
+ printf("barrier_test: Thread %d created\n", i);
+ }
+ }
+
+ /* Wait for all thread instances to complete */
+
+ for (i = 0; i < CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS; i++)
+ {
+ status = pthread_join(barrier_thread[i], &result);
+ if (status != 0)
+ {
+ printf("barrier_test: Error in thread %d join, status=%d\n",
+ i, status);
+ }
+ else
+ {
+ printf("barrier_test: Thread %d completed with result=%p\n",
+ i, result);
+ }
+ }
+
+ /* Destroy the barrier */
+
+ status = pthread_barrier_destroy(&barrier);
+ if (status != OK)
+ {
+ printf("barrier_test: pthread_barrier_destroy failed, status=%d\n",
+ status);
+ }
+
+ status = pthread_barrierattr_destroy(&barrierattr);
+ if (status != OK)
+ {
+ printf("barrier_test: pthread_barrierattr_destroy failed, status=%d\n",
+ status);
+ }
+}
diff --git a/apps/examples/ostest/cancel.c b/apps/examples/ostest/cancel.c
new file mode 100644
index 000000000..bf2d03615
--- /dev/null
+++ b/apps/examples/ostest/cancel.c
@@ -0,0 +1,333 @@
+/***********************************************************************
+ * examples/ostest/cancel.c
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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. Neither the name NuttX 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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 <stdio.h>
+#include <time.h>
+#include <pthread.h>
+#include <errno.h>
+#include "ostest.h"
+
+static pthread_mutex_t mutex;
+static pthread_cond_t cond;
+
+static void *thread_waiter(void *parameter)
+{
+ int status;
+
+ /* Take the mutex */
+
+ printf("thread_waiter: Taking mutex\n");
+ status = pthread_mutex_lock(&mutex);
+ if (status != 0)
+ {
+ printf("thread_waiter: ERROR pthread_mutex_lock failed, status=%d\n", status);
+ }
+
+ printf("thread_waiter: Starting wait for condition\n");
+
+ /* Are we a non-cancelable thread? Yes, set the non-cancelable state */
+
+ if (!parameter)
+ {
+ printf("thread_waiter: Setting non-cancelable\n");
+ status = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+ if (status != 0)
+ {
+ printf("thread_waiter: ERROR pthread_setcancelstate failed, status=%d\n", status);
+ }
+ }
+
+ /* The wait -- we will never awaken from this. */
+
+ status = pthread_cond_wait(&cond, &mutex);
+ if (status != 0)
+ {
+ printf("thread_waiter: ERROR pthread_cond_wait failed, status=%d\n", status);
+ }
+
+ /* Release the mutex */
+
+ printf("thread_waiter: Releasing mutex\n");
+ status = pthread_mutex_unlock(&mutex);
+ if (status != 0)
+ {
+ printf("thread_waiter: ERROR pthread_mutex_unlock failed, status=%d\n", status);
+ }
+
+ /* Set the cancelable state */
+
+ printf("thread_waiter: Setting cancelable\n");
+ status = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+ if (status != 0)
+ {
+ printf("thread_waiter: ERROR pthread_setcancelstate failed, status=%d\n", status);
+ }
+
+ printf("thread_waiter: Exit with status 0x12345678\n");
+ pthread_exit((pthread_addr_t)0x12345678);
+ return NULL;
+}
+
+static void start_thread(pthread_t *waiter, int cancelable)
+{
+ pthread_attr_t attr;
+ int status;
+
+ /* Initialize the mutex */
+
+ printf("start_thread: Initializing mutex\n");
+ status = pthread_mutex_init(&mutex, NULL);
+ if (status != 0)
+ {
+ printf("start_thread: ERROR pthread_mutex_init failed, status=%d\n", status);
+ }
+
+ /* Initialize the condition variable */
+
+ printf("start_thread: Initializing cond\n");
+ status = pthread_cond_init(&cond, NULL);
+ if (status != 0)
+ {
+ printf("start_thread: ERROR pthread_cond_init failed, status=%d\n", status);
+ }
+
+ /* Set up attributes */
+
+ status = pthread_attr_init(&attr);
+ if (status != 0)
+ {
+ printf("start_thread: pthread_attr_init failed, status=%d\n", status);
+ }
+
+ status = pthread_attr_setstacksize(&attr, STACKSIZE);
+ if (status != 0)
+ {
+ printf("start_thread: pthread_attr_setstacksize failed, status=%d\n", status);
+ }
+
+ /* Start the waiter thread */
+
+ printf("start_thread: Starting thread\n");
+ status = pthread_create(waiter, &attr, thread_waiter, (pthread_addr_t)cancelable);
+ if (status != 0)
+ {
+ printf("start_thread: ERROR pthread_create failed, status=%d\n", status);
+ }
+
+ /* Make sure that the waiter thread gets a chance to run */
+
+ printf("start_thread: Yielding\n");
+ pthread_yield();
+}
+
+static void restart_thread(pthread_t *waiter, int cancelable)
+{
+ int status;
+
+ /* Destroy the condition variable */
+
+ printf("restart_thread: Destroying cond\n");
+ status = pthread_cond_destroy(&cond);
+ if (status != 0)
+ {
+ printf("restart_thread: ERROR pthread_cond_destroy failed, status=%d\n", status);
+ }
+
+ /* Destroy the mutex */
+
+ printf("restart_thread: Destroying mutex\n");
+ status = pthread_cond_destroy(&cond);
+ if (status != 0)
+ {
+ printf("restart_thread: ERROR pthread_mutex_destroy failed, status=%d\n", status);
+ }
+
+ /* Then restart the thread */
+
+ printf("restart_thread: Re-starting thread\n");
+ start_thread(waiter, cancelable);
+}
+
+void cancel_test(void)
+{
+ pthread_t waiter;
+ void *result;
+ int status;
+
+ /* Test 1: Normal Cancel *********************************************/
+ /* Start the waiter thread */
+
+ printf("cancel_test: Test 1: Normal Cancelation\n");
+ printf("cancel_test: Starting thread\n");
+ start_thread(&waiter, 1);
+
+ /* Then cancel it. It should be in the pthread_cond_wait now */
+
+ printf("cancel_test: Canceling thread\n");
+ status = pthread_cancel(waiter);
+ if (status != 0)
+ {
+ printf("cancel_test: ERROR pthread_cancel failed, status=%d\n", status);
+ }
+
+ /* Then join to the thread to pick up the result (if we don't do
+ * we will have a memory leak!)
+ */
+
+ printf("cancel_test: Joining\n");
+ status = pthread_join(waiter, &result);
+ if (status != 0)
+ {
+ printf("cancel_test: ERROR pthread_join failed, status=%d\n", status);
+ }
+ else
+ {
+ printf("cancel_test: waiter exited with result=%p\n", result);
+ if (result != PTHREAD_CANCELED)
+ {
+ printf("cancel_test: ERROR expected result=%p\n", PTHREAD_CANCELED);
+ }
+ else
+ {
+ printf("cancel_test: PASS thread terminated with PTHREAD_CANCELED\n");
+ }
+ }
+
+ /* Test 2: Cancel Detached Thread ************************************/
+
+ printf("cancel_test: Test 2: Cancelation of detached thread\n");
+ printf("cancel_test: Re-starting thread\n");
+ restart_thread(&waiter, 1);
+
+ /* Detach the thread */
+
+ status = pthread_detach(waiter);
+ if (status != 0)
+ {
+ printf("cancel_test: ERROR pthread_detach, status=%d\n", status);
+ }
+
+ /* Then cancel it. It should be in the pthread_cond_wait now */
+
+ printf("cancel_test: Canceling thread\n");
+ status = pthread_cancel(waiter);
+ if (status != 0)
+ {
+ printf("cancel_test: ERROR pthread_cancel failed, status=%d\n", status);
+ }
+
+ /* Join should now fail */
+
+ printf("cancel_test: Joining\n");
+ status = pthread_join(waiter, &result);
+ if (status == 0)
+ {
+ printf("cancel_test: ERROR pthread_join succeeded\n");
+ }
+ else if (status != ESRCH)
+ {
+ printf("cancel_test: ERROR pthread_join failed but with wrong status=%d\n", status);
+ }
+ else
+ {
+ printf("cancel_test: PASS pthread_join failed with status=ESRCH\n");
+ }
+
+ /* Test 3: Non-cancelable threads ************************************/
+
+ printf("cancel_test: Test 3: Non-cancelable threads\n");
+ printf("cancel_test: Re-starting thread (non-cancelable)\n");
+ restart_thread(&waiter, 0);
+
+ /* Then cancel it. It should be in the pthread_cond_wait now. The
+ * behavior here is non-standard: when the thread is at a cancelation
+ * point, it should be cancelable, even when cancelation is disable.
+ *
+ * The cancelation should succeed, because the cancelation is pending.
+ */
+
+ printf("cancel_test: Canceling thread\n");
+ status = pthread_cancel(waiter);
+ if (status != 0)
+ {
+ printf("cancel_test: ERROR pthread_cancel failed, status=%d\n", status);
+ }
+
+ /* Signal the thread. It should wake up and restore the cancelable state.
+ * When the cancelable state is re-enabled, the thread should be canceled.
+ */
+
+ status = pthread_mutex_lock(&mutex);
+ if (status != 0)
+ {
+ printf("cancel_test: ERROR pthread_mutex_lock failed, status=%d\n", status);
+ }
+
+ status = pthread_cond_signal(&cond);
+ if (status != 0)
+ {
+ printf("cancel_test: ERROR pthread_cond_signal failed, status=%d\n", status);
+ }
+
+ status = pthread_mutex_unlock(&mutex);
+ if (status != 0)
+ {
+ printf("cancel_test: ERROR pthread_mutex_unlock failed, status=%d\n", status);
+ }
+
+ /* Then join to the thread to pick up the result (if we don't do
+ * we will have a memory leak!)
+ */
+
+ printf("cancel_test: Joining\n");
+ status = pthread_join(waiter, &result);
+ if (status != 0)
+ {
+ printf("cancel_test: ERROR pthread_join failed, status=%d\n", status);
+ }
+ else
+ {
+ printf("cancel_test: waiter exited with result=%p\n", result);
+ if (result != PTHREAD_CANCELED)
+ {
+ printf("cancel_test: ERROR expected result=%p\n", PTHREAD_CANCELED);
+ }
+ else
+ {
+ printf("cancel_test: PASS thread terminated with PTHREAD_CANCELED\n");
+ }
+ }
+
+}
diff --git a/apps/examples/ostest/cond.c b/apps/examples/ostest/cond.c
new file mode 100644
index 000000000..11191b7d5
--- /dev/null
+++ b/apps/examples/ostest/cond.c
@@ -0,0 +1,294 @@
+/***********************************************************************
+ * cond.c
+ *
+ * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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. Neither the name NuttX 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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 <stdio.h>
+#include <pthread.h>
+#include <unistd.h>
+#include "ostest.h"
+
+#ifndef NULL
+# define NULL (void*)0
+#endif
+
+static volatile enum { RUNNING, MUTEX_WAIT, COND_WAIT} waiter_state;
+
+static pthread_mutex_t mutex;
+static pthread_cond_t cond;
+static volatile int data_available = 0;
+static int waiter_nloops = 0;
+static int waiter_waits = 0;
+static int waiter_nerrors = 0;
+static int signaler_nloops = 0;
+static int signaler_already = 0;
+static int signaler_state = 0;
+static int signaler_nerrors = 0;
+
+static void *thread_waiter(void *parameter)
+{
+ int status;
+
+ printf("waiter_thread: Started\n");
+
+ for(;;)
+ {
+ /* Take the mutex */
+
+ waiter_state = MUTEX_WAIT;
+ status = pthread_mutex_lock(&mutex);
+ waiter_state = RUNNING;
+
+ if (status != 0)
+ {
+ printf("waiter_thread: ERROR pthread_mutex_lock failed, status=%d\n", status);
+ waiter_nerrors++;
+ }
+
+ /* Check if data is available -- if data is not available then
+ * wait for it
+ */
+
+ if (!data_available)
+ {
+ /* We are higher priority than the signaler thread so the
+ * only time that the signaler thread will have a chance to run is when
+ * we are waiting for the condition variable. In this case, pthread_cond_wait
+ * will automatically release the mutex for the signaler (then re-acquire
+ * the mutex before returning.
+ */
+
+ waiter_state = COND_WAIT;
+ status = pthread_cond_wait(&cond, &mutex);
+ waiter_state = RUNNING;
+
+ if (status != 0)
+ {
+ printf("waiter_thread: ERROR pthread_cond_wait failed, status=%d\n", status);
+ waiter_nerrors++;
+ }
+ waiter_waits++;
+ }
+
+ /* Now data should be available */
+
+ if (!data_available)
+ {
+ printf("waiter_thread: ERROR data not available after wait\n");
+ waiter_nerrors++;
+ }
+
+ /* Clear data available */
+
+ data_available = 0;
+
+ /* Release the mutex */
+
+ status = pthread_mutex_unlock(&mutex);
+ if (status != 0)
+ {
+ printf("waiter_thread: ERROR waiter: pthread_mutex_unlock failed, status=%d\n", status);
+ waiter_nerrors++;
+ }
+
+ waiter_nloops++;
+ }
+ return NULL;
+}
+
+static void *thread_signaler(void *parameter)
+{
+ int status;
+ int i;
+
+ printf("thread_signaler: Started\n");
+ for (i = 0; i < 32; i++)
+ {
+ /* Take the mutex. The waiter is higher priority and should
+ * run until it waits for the condition. So, at this point
+ * signaler should be waiting for the condition.
+ */
+
+ status = pthread_mutex_lock(&mutex);
+ if (status != 0)
+ {
+ printf("thread_signaler: ERROR pthread_mutex_lock failed, status=%d\n", status);
+ signaler_nerrors++;
+ }
+
+ /* Verify the state */
+
+ if (waiter_state != COND_WAIT)
+ {
+ printf("thread_signaler: ERROR waiter state = %d != COND_WAITING\n", waiter_state);
+ signaler_state++;
+ }
+
+ if (data_available)
+ {
+ printf("thread_signaler: ERROR data already available, waiter_state=%d\n", waiter_state);
+ signaler_already++;
+ }
+
+ /* Set data available and signal the waiter */
+
+ data_available = 1;
+ status = pthread_cond_signal(&cond);
+ if (status != 0)
+ {
+ printf("thread_signaler: ERROR pthread_cond_signal failed, status=%d\n", status);
+ signaler_nerrors++;
+ }
+
+ /* Release the mutex */
+
+ status = pthread_mutex_unlock(&mutex);
+ if (status != 0)
+ {
+ printf("thread_signaler: ERROR pthread_mutex_unlock failed, status=%d\n", status);
+ signaler_nerrors++;
+ }
+
+ signaler_nloops++;
+ }
+
+ printf("thread_signaler: Terminating\n");
+ pthread_exit(NULL);
+ return NULL; /* Non-reachable -- needed for some compilers */
+}
+
+void cond_test(void)
+{
+ pthread_t waiter;
+ pthread_t signaler;
+ pthread_attr_t attr;
+#ifdef SDCC
+ pthread_addr_t result;
+#endif
+ struct sched_param sparam;
+ int prio_min;
+ int prio_max;
+ int prio_mid;
+ int status;
+
+ /* Initialize the mutex */
+
+ printf("cond_test: Initializing mutex\n");
+ status = pthread_mutex_init(&mutex, NULL);
+ if (status != 0)
+ {
+ printf("cond_test: ERROR pthread_mutex_init failed, status=%d\n", status);
+ }
+
+ /* Initialize the condition variable */
+
+ printf("cond_test: Initializing cond\n");
+ status = pthread_cond_init(&cond, NULL);
+ if (status != 0)
+ {
+ printf("cond_test: ERROR pthread_condinit failed, status=%d\n", status);
+ }
+
+ /* Start the waiter thread at higher priority */
+
+ printf("cond_test: Starting waiter\n");
+ status = pthread_attr_init(&attr);
+ if (status != 0)
+ {
+ printf("cond_test: pthread_attr_init failed, status=%d\n", status);
+ }
+
+ prio_min = sched_get_priority_min(SCHED_FIFO);
+ prio_max = sched_get_priority_max(SCHED_FIFO);
+ prio_mid = (prio_min + prio_max) / 2;
+
+ sparam.sched_priority = prio_mid;
+ status = pthread_attr_setschedparam(&attr,&sparam);
+ if (status != OK)
+ {
+ printf("cond_test: pthread_attr_setschedparam failed, status=%d\n", status);
+ }
+ else
+ {
+ printf("cond_test: Set thread 1 priority to %d\n", sparam.sched_priority);
+ }
+
+ status = pthread_create(&waiter, &attr, thread_waiter, NULL);
+ if (status != 0)
+ {
+ printf("cond_test: pthread_create failed, status=%d\n", status);
+ }
+
+ printf("cond_test: Starting signaler\n");
+ status = pthread_attr_init(&attr);
+ if (status != 0)
+ {
+ printf("cond_test: pthread_attr_init failed, status=%d\n", status);
+ }
+
+ sparam.sched_priority = (prio_min + prio_mid) / 2;
+ status = pthread_attr_setschedparam(&attr,&sparam);
+ if (status != OK)
+ {
+ printf("cond_test: pthread_attr_setschedparam failed, status=%d\n", status);
+ }
+ else
+ {
+ printf("cond_test: Set thread 2 priority to %d\n", sparam.sched_priority);
+ }
+
+ status = pthread_create(&signaler, &attr, thread_signaler, NULL);
+ if (status != 0)
+ {
+ printf("cond_test: pthread_create failed, status=%d\n", status);
+ }
+
+ /* Wait for the threads to stop */
+
+#ifdef SDCC
+ pthread_join(signaler, &result);
+#else
+ pthread_join(signaler, NULL);
+#endif
+ printf("cond_test: signaler terminated, now cancel the waiter\n");
+ pthread_detach(waiter);
+ pthread_cancel(waiter);
+
+ printf("cond_test: \tWaiter\tSignaler\n");
+ printf("cond_test: Loops\t%d\t%d\n", waiter_nloops, signaler_nloops);
+ printf("cond_test: Errors\t%d\t%d\n", waiter_nerrors, signaler_nerrors);
+ printf("cond_test:\n");
+ printf("cond_test: %d times, waiter did not have to wait for data\n", waiter_nloops - waiter_waits);
+ printf("cond_test: %d times, data was already available when the signaler run\n", signaler_already);
+ printf("cond_test: %d times, the waiter was in an unexpected state when the signaler ran\n", signaler_state);
+}
diff --git a/apps/examples/ostest/dev_null.c b/apps/examples/ostest/dev_null.c
new file mode 100644
index 000000000..e8fc6cf3f
--- /dev/null
+++ b/apps/examples/ostest/dev_null.c
@@ -0,0 +1,92 @@
+/****************************************************************************
+ * examples/ostest/dev_null.c
+ *
+ * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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. Neither the name NuttX 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "ostest.h"
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+
+static FAR char buffer[1024];
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int dev_null(void)
+{
+ int nbytes;
+ int fd;
+
+ fd = open("/dev/null", O_RDWR);
+ if (fd < 0)
+ {
+ printf("dev_null: ERROR Failed to open /dev/null\n");
+ return -1;
+ }
+
+ nbytes = read(fd, buffer, 1024);
+ if (nbytes < 0)
+ {
+ printf("dev_null: ERROR Failed to read from /dev/null\n");
+ close(fd);
+ return -1;
+ }
+ printf("dev_null: Read %d bytes from /dev/null\n", nbytes);
+
+ nbytes = write(fd, buffer, 1024);
+ if (nbytes < 0)
+ {
+ printf("dev_null: ERROR Failed to write to /dev/null\n");
+ close(fd);
+ return -1;
+ }
+ printf("dev_null: Wrote %d bytes to /dev/null\n", nbytes);
+
+ close(fd);
+ return 0;
+}
+
+#endif /*CONFIG_NFILE_DESCRIPTORS */
diff --git a/apps/examples/ostest/main.c b/apps/examples/ostest/main.c
new file mode 100644
index 000000000..53be10764
--- /dev/null
+++ b/apps/examples/ostest/main.c
@@ -0,0 +1,523 @@
+/****************************************************************************
+ * examples/ostest/main.c
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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. Neither the name NuttX 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sched.h>
+#include <nuttx/init.h>
+
+#include "ostest.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+#define PRIORITY 100
+#define NARGS 4
+#define HALF_SECOND_USEC 500000L
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const char arg1[] = "Arg1";
+static const char arg2[] = "Arg2";
+static const char arg3[] = "Arg3";
+static const char arg4[] = "Arg4";
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+static const char write_data1[] = "stdio_test: write fd=1\n";
+static const char write_data2[] = "stdio_test: write fd=2\n";
+#endif
+
+#ifdef SDCC
+/* I am not yet certain why SDCC does not like the following
+ * initializer. It involves some issues with 2- vs 3-byte
+ * pointer types.
+ */
+
+static const char *g_argv[NARGS+1];
+#else
+static const char *g_argv[NARGS+1] = { arg1, arg2, arg3, arg4, NULL };
+#endif
+
+#ifndef CONFIG_DISABLE_SIGNALS
+static struct mallinfo g_mmbefore;
+static struct mallinfo g_mmprevious;
+static struct mallinfo g_mmafter;
+#endif
+
+#ifndef CONFIG_DISABLE_ENVIRON
+const char g_var1_name[] = "Variable1";
+const char g_var1_value[] = "GoodValue1";
+const char g_var2_name[] = "Variable2";
+const char g_var2_value[] = "GoodValue2";
+const char g_var3_name[] = "Variable3";
+const char g_var3_value[] = "GoodValue3";
+
+const char g_bad_value1[] = "BadValue1";
+const char g_bad_value2[] = "BadValue2";
+
+const char g_putenv_value[] = "Variable1=BadValue3";
+
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: show_memory_usage
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_SIGNALS
+static void show_memory_usage(struct mallinfo *mmbefore,
+ struct mallinfo *mmafter)
+{
+ printf("VARIABLE BEFORE AFTER\n");
+ printf("======== ======== ========\n");
+ printf("arena %8x %8x\n", mmbefore->arena, mmafter->arena);
+ printf("ordblks %8d %8d\n", mmbefore->ordblks, mmafter->ordblks);
+ printf("mxordblk %8x %8x\n", mmbefore->mxordblk, mmafter->mxordblk);
+ printf("uordblks %8x %8x\n", mmbefore->uordblks, mmafter->uordblks);
+ printf("fordblks %8x %8x\n", mmbefore->fordblks, mmafter->fordblks);
+}
+#else
+# define show_memory_usage(mm1, mm2)
+#endif
+
+/****************************************************************************
+ * Name: check_test_memory_usage
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_SIGNALS
+static void check_test_memory_usage(void)
+{
+ /* Wait a little bit to let any threads terminate */
+
+ usleep(HALF_SECOND_USEC);
+
+ /* Get the current memory usage */
+
+#ifdef CONFIG_CAN_PASS_STRUCTS
+ g_mmafter = mallinfo();
+#else
+ (void)mallinfo(&g_mmafter);
+#endif
+
+ /* Show the change from the previous time */
+
+ printf("\nEnd of test memory usage:\n");
+ show_memory_usage(&g_mmprevious, &g_mmafter);
+
+ /* Set up for the next test */
+
+#ifdef CONFIG_CAN_PASS_STRUCTS
+ g_mmprevious = g_mmafter;
+#else
+ memcpy(&g_mmprevious, &g_mmafter, sizeof(struct mallinfo));
+#endif
+
+ /* If so enabled, show the use of priority inheritance resources */
+
+ dump_nfreeholders("user_main:");
+}
+#else
+# define check_test_memory_usage()
+#endif
+
+/****************************************************************************
+ * Name: show_variable
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_ENVIRON
+static void show_variable(const char *var_name, const char *exptd_value, bool var_valid)
+{
+ char *actual_value = getenv(var_name);
+ if (actual_value)
+ {
+ if (var_valid)
+ {
+ if (strcmp(actual_value, exptd_value) == 0)
+ {
+ printf("show_variable: Variable=%s has value=%s\n", var_name, exptd_value);
+ }
+ else
+ {
+ printf("show_variable: ERROR Variable=%s has the wrong value\n", var_name);
+ printf("show_variable: found=%s expected=%s\n", actual_value, exptd_value);
+ }
+ }
+ else
+ {
+ printf("show_variable: ERROR Variable=%s has a value when it should not\n", var_name);
+ printf("show_variable: value=%s\n", actual_value);
+ }
+ }
+ else if (var_valid)
+ {
+ printf("show_variable: ERROR Variable=%s has no value\n", var_name);
+ printf("show_variable: Should have had value=%s\n", exptd_value);
+ }
+ else
+ {
+ printf("show_variable: Variable=%s has no value\n", var_name);
+ }
+}
+
+static void show_environment(bool var1_valid, bool var2_valid, bool var3_valid)
+{
+ show_variable(g_var1_name, g_var1_value, var1_valid);
+ show_variable(g_var2_name, g_var2_value, var2_valid);
+ show_variable(g_var3_name, g_var3_value, var3_valid);
+}
+#else
+# define show_environment()
+#endif
+
+/****************************************************************************
+ * Name: user_main
+ ****************************************************************************/
+
+static int user_main(int argc, char *argv[])
+{
+ int i;
+
+ /* Sample the memory usage now */
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ usleep(HALF_SECOND_USEC);
+
+#ifdef CONFIG_CAN_PASS_STRUCTS
+ g_mmbefore = mallinfo();
+ g_mmprevious = g_mmbefore;
+#else
+ (void)mallinfo(&g_mmbefore);
+ memcpy(&g_mmprevious, &g_mmbefore, sizeof(struct mallinfo));
+#endif
+#endif
+
+ printf("\nuser_main: Begin argument test\n");
+ printf("user_main: Started with argc=%d\n", argc);
+
+ /* Verify passed arguments */
+
+ if (argc != NARGS + 1)
+ {
+ printf("user_main: Error expected argc=%d got argc=%d\n",
+ NARGS+1, argc);
+ }
+
+ for (i = 0; i <= NARGS; i++)
+ {
+ printf("user_main: argv[%d]=\"%s\"\n", i, argv[i]);
+ }
+
+ for (i = 1; i <= NARGS; i++)
+ {
+ if (strcmp(argv[i], g_argv[i-1]) != 0)
+ {
+ printf("user_main: ERROR argv[%d]: Expected \"%s\" found \"%s\"\n",
+ i, g_argv[i-1], argv[i]);
+ }
+ }
+ check_test_memory_usage();
+
+ /* Check environment variables */
+#ifndef CONFIG_DISABLE_ENVIRON
+ show_environment(true, true, true);
+
+ unsetenv(g_var1_name);
+ show_environment(false, true, true);
+ check_test_memory_usage();
+
+ clearenv();
+ show_environment(false, false, false);
+ check_test_memory_usage();
+#endif
+
+ /* Top of test loop */
+
+#if CONFIG_EXAMPLES_OSTEST_LOOPS > 1
+ for (i = 0; i < CONFIG_EXAMPLES_OSTEST_LOOPS; i++)
+#elif CONFIG_EXAMPLES_OSTEST_LOOPS == 0
+ for (;;)
+#endif
+ {
+#if CONFIG_NFILE_DESCRIPTORS > 0
+ /* Checkout /dev/null */
+
+ printf("\nuser_main: /dev/null test\n");
+ dev_null();
+ check_test_memory_usage();
+#endif
+
+#ifndef CONFIG_DISABLE_PTHREAD
+ /* Verify pthreads and pthread mutex */
+
+ printf("\nuser_main: mutex test\n");
+ mutex_test();
+ check_test_memory_usage();
+#endif
+
+#if !defined(CONFIG_DISABLE_PTHREAD) && defined(CONFIG_MUTEX_TYPES)
+ /* Verify recursive mutexes */
+
+ printf("\nuser_main: recursive mutex test\n");
+ recursive_mutex_test();
+ check_test_memory_usage();
+#endif
+
+#ifndef CONFIG_DISABLE_PTHREAD
+ /* Verify pthread cancellation */
+
+ printf("\nuser_main: cancel test\n");
+ cancel_test();
+ check_test_memory_usage();
+#endif
+
+#ifndef CONFIG_DISABLE_PTHREAD
+ /* Verify pthreads and semaphores */
+
+ printf("\nuser_main: semaphore test\n");
+ sem_test();
+ check_test_memory_usage();
+#endif
+
+#ifndef CONFIG_DISABLE_PTHREAD
+ /* Verify pthreads and condition variables */
+
+ printf("\nuser_main: condition variable test\n");
+#ifdef CONFIG_PRIORITY_INHERITANCE
+ printf("\n Skipping, Test logic incompatible with priority inheritance\n");
+#else
+ cond_test();
+ check_test_memory_usage();
+#endif
+#endif
+
+#if !defined(CONFIG_DISABLE_SIGNALS) && !defined(CONFIG_DISABLE_PTHREAD) && !defined(CONFIG_DISABLE_CLOCK)
+ /* Verify pthreads and condition variable timed waits */
+
+ printf("\nuser_main: timed wait test\n");
+ timedwait_test();
+ check_test_memory_usage();
+#endif
+
+#if !defined(CONFIG_DISABLE_MQUEUE) && !defined(CONFIG_DISABLE_PTHREAD)
+ /* Verify pthreads and message queues */
+
+ printf("\nuser_main: message queue test\n");
+ mqueue_test();
+ check_test_memory_usage();
+#endif
+
+#if !defined(CONFIG_DISABLE_MQUEUE) && !defined(CONFIG_DISABLE_PTHREAD) && !defined(CONFIG_DISABLE_CLOCK)
+ /* Verify pthreads and message queues */
+
+ printf("\nuser_main: timed message queue test\n");
+ timedmqueue_test();
+ check_test_memory_usage();
+#endif
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ /* Verify signal handlers */
+
+ printf("\nuser_main: signal handler test\n");
+ sighand_test();
+ check_test_memory_usage();
+#endif
+
+#if !defined(CONFIG_DISABLE_POSIX_TIMERS) && !defined(CONFIG_DISABLE_SIGNALS)
+ /* Verify posix timers */
+
+ printf("\nuser_main: POSIX timer test\n");
+ timer_test();
+ check_test_memory_usage();
+#endif
+
+#if !defined(CONFIG_DISABLE_PTHREAD) && CONFIG_RR_INTERVAL > 0
+ /* Verify round robin scheduling */
+
+ printf("\nuser_main: round-robin scheduler test\n");
+ rr_test();
+ check_test_memory_usage();
+#endif
+
+#ifndef CONFIG_DISABLE_PTHREAD
+ /* Verify pthread barriers */
+
+ printf("\nuser_main: barrier test\n");
+ barrier_test();
+ check_test_memory_usage();
+#endif
+
+#if defined(CONFIG_PRIORITY_INHERITANCE) && !defined(CONFIG_DISABLE_SIGNALS) && !defined(CONFIG_DISABLE_PTHREAD)
+ /* Verify priority inheritance */
+
+ printf("\nuser_main: priority inheritance test\n");
+ priority_inheritance();
+ check_test_memory_usage();
+#endif /* CONFIG_PRIORITY_INHERITANCE && !CONFIG_DISABLE_SIGNALS && !CONFIG_DISABLE_PTHREAD */
+
+ /* Compare memory usage at time user_start started until
+ * user_main exits. These should not be identical, but should
+ * be similar enough that we can detect any serious OS memory
+ * leaks.
+ */
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ usleep(HALF_SECOND_USEC);
+
+#ifdef CONFIG_CAN_PASS_STRUCTS
+ g_mmafter = mallinfo();
+#else
+ (void)mallinfo(&g_mmafter);
+#endif
+
+ printf("\nFinal memory usage:\n");
+ show_memory_usage(&g_mmbefore, &g_mmafter);
+#endif
+ }
+ printf("user_main: Exitting\n");
+ return 0;
+}
+
+/****************************************************************************
+ * Name: stdio_test
+ ****************************************************************************/
+
+static void stdio_test(void)
+{
+ /* Verify that we can communicate */
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+ write(1, write_data1, sizeof(write_data1)-1);
+#endif
+ printf("stdio_test: Standard I/O Check: printf\n");
+
+#if CONFIG_NFILE_DESCRIPTORS > 1
+ write(2, write_data2, sizeof(write_data2)-1);
+#endif
+#if CONFIG_NFILE_STREAMS > 0
+ fprintf(stderr, "stdio_test: Standard I/O Check: fprintf to stderr\n");
+#endif
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * user_initialize
+ ****************************************************************************/
+
+void user_initialize(void)
+{
+ /* stub */
+}
+
+/****************************************************************************
+ * user_start
+ ****************************************************************************/
+
+int user_start(int argc, char *argv[])
+{
+ int result;
+
+ /* Verify that stdio works first */
+
+ stdio_test();
+
+#ifdef SDCC
+ /* I am not yet certain why SDCC does not like the following initilizers.
+ * It involves some issues with 2- vs 3-byte pointer types.
+ */
+
+ g_argv[0] = arg1;
+ g_argv[1] = arg2;
+ g_argv[2] = arg3;
+ g_argv[3] = arg4;
+ g_argv[4] = NULL;
+#endif
+
+ /* Set up some environment variables */
+
+#ifndef CONFIG_DISABLE_ENVIRON
+ printf("user_start: putenv(%s)\n", g_putenv_value);
+ putenv(g_putenv_value); /* Varaible1=BadValue3 */
+ printf("user_start: setenv(%s, %s, TRUE)\n", g_var1_name, g_var1_value);
+ setenv(g_var1_name, g_var1_value, TRUE); /* Variable1=GoodValue1 */
+
+ printf("user_start: setenv(%s, %s, FALSE)\n", g_var2_name, g_bad_value1);
+ setenv(g_var2_name, g_bad_value1, FALSE); /* Variable2=BadValue1 */
+ printf("user_start: setenv(%s, %s, TRUE)\n", g_var2_name, g_var2_value);
+ setenv(g_var2_name, g_var2_value, TRUE); /* Variable2=GoodValue2 */
+
+ printf("user_start: setenv(%s, %s, FALSE)\n", g_var3_name, g_var3_name);
+ setenv(g_var3_name, g_var3_value, FALSE); /* Variable3=GoodValue3 */
+ printf("user_start: setenv(%s, %s, FALSE)\n", g_var3_name, g_var3_name);
+ setenv(g_var3_name, g_bad_value2, FALSE); /* Variable3=GoodValue3 */
+ show_environment(true, true, true);
+#endif
+
+ /* Verify that we can spawn a new task */
+
+#ifndef CONFIG_CUSTOM_STACK
+ result = task_create("ostest", PRIORITY, STACKSIZE, user_main, g_argv);
+#else
+ result = task_create("ostest", PRIORITY, user_main, g_argv);
+#endif
+ if (result == ERROR)
+ {
+ printf("user_start: ERROR Failed to start user_main\n");
+ }
+ else
+ {
+ printf("user_start: Started user_main at PID=%d\n", result);
+ }
+
+ printf("user_start: Exitting\n");
+ return 0;
+}
diff --git a/apps/examples/ostest/mqueue.c b/apps/examples/ostest/mqueue.c
new file mode 100644
index 000000000..e68cfc012
--- /dev/null
+++ b/apps/examples/ostest/mqueue.c
@@ -0,0 +1,394 @@
+/**************************************************************************
+ * mqueue.c
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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. Neither the name NuttX 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
+ *
+ **************************************************************************/
+
+/**************************************************************************
+ * Included Files
+ **************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <mqueue.h>
+#include <sched.h>
+#include <errno.h>
+
+#include "ostest.h"
+
+/**************************************************************************
+ * Private Definitions
+ **************************************************************************/
+
+#define TEST_MESSAGE "This is a test and only a test"
+#if defined(SDCC) || defined(__ZILOG__)
+ /* Cannot use strlen in array size */
+
+# define TEST_MSGLEN (31)
+#else
+ /* Message lenght is the size of the message plus the null terminator */
+
+# define TEST_MSGLEN (strlen(TEST_MESSAGE)+1)
+#endif
+
+#define TEST_SEND_NMSGS (10)
+#ifndef CONFIG_DISABLE_SIGNALS
+# define TEST_RECEIVE_NMSGS (11)
+#else
+# define TEST_RECEIVE_NMSGS (10)
+#endif
+
+#define HALF_SECOND_USEC_USEC 500000L
+
+/**************************************************************************
+ * Private Types
+ **************************************************************************/
+
+/**************************************************************************
+ * Private Function Prototypes
+ **************************************************************************/
+
+/**************************************************************************
+ * Global Variables
+ **************************************************************************/
+
+/**************************************************************************
+ * Private Variables
+ **************************************************************************/
+
+/**************************************************************************
+ * Private Functions
+ **************************************************************************/
+
+/**************************************************************************
+ * Public Functions
+ **************************************************************************/
+
+static void *sender_thread(void *arg)
+{
+ mqd_t mqfd;
+ char msg_buffer[TEST_MSGLEN];
+ struct mq_attr attr;
+ int status = 0;
+ int nerrors = 0;
+ int i;
+
+ printf("sender_thread: Starting\n");
+
+ /* Fill in attributes for message queue */
+
+ attr.mq_maxmsg = 20;
+ attr.mq_msgsize = TEST_MSGLEN;
+ attr.mq_flags = 0;
+
+ /* Set the flags for the open of the queue.
+ * Make it a blocking open on the queue, meaning it will block if
+ * this process tries to send to the queue and the queue is full.
+ *
+ * O_CREAT - the queue will get created if it does not already exist.
+ * O_WRONLY - we are only planning to write to the queue.
+ *
+ * Open the queue, and create it if the receiving process hasn't
+ * already created it.
+ */
+
+ mqfd = mq_open("testmq", O_WRONLY|O_CREAT, 0666, &attr);
+ if (mqfd < 0)
+ {
+ printf("sender_thread: ERROR mq_open failed\n");
+ pthread_exit((pthread_addr_t)1);
+ }
+
+ /* Fill in a test message buffer to send */
+
+ memcpy(msg_buffer, TEST_MESSAGE, TEST_MSGLEN);
+
+ /* Perform the send TEST_SEND_NMSGS times */
+
+ for (i = 0; i < TEST_SEND_NMSGS; i++)
+ {
+ status = mq_send(mqfd, msg_buffer, TEST_MSGLEN, 42);
+ if (status < 0)
+ {
+ printf("sender_thread: ERROR mq_send failure=%d on msg %d\n", status, i);
+ nerrors++;
+ }
+ else
+ {
+ printf("sender_thread: mq_send succeeded on msg %d\n", i);
+ }
+ }
+
+ /* Close the queue and return success */
+
+ if (mq_close(mqfd) < 0)
+ {
+ printf("sender_thread: ERROR mq_close failed\n");
+ }
+
+ printf("sender_thread: returning nerrors=%d\n", nerrors);
+ return (pthread_addr_t)nerrors;
+}
+
+static void *receiver_thread(void *arg)
+{
+ mqd_t mqfd;
+ char msg_buffer[TEST_MSGLEN];
+ struct mq_attr attr;
+ int nbytes;
+ int nerrors = 0;
+ int i;
+
+ printf("receiver_thread: Starting\n");
+
+ /* Fill in attributes for message queue */
+
+ attr.mq_maxmsg = 20;
+ attr.mq_msgsize = TEST_MSGLEN;
+ attr.mq_flags = 0;
+
+ /* Set the flags for the open of the queue.
+ * Make it a blocking open on the queue, meaning it will block if
+ * this task tries to read from the queue when the queue is empty
+ *
+ * O_CREAT - the queue will get created if it does not already exist.
+ * O_RDONLY - we are only planning to read from the queue.
+ *
+ * Open the queue, and create it if the sending process hasn't
+ * already created it.
+ */
+
+ mqfd = mq_open("testmq", O_RDONLY|O_CREAT, 0666, &attr);
+ if (mqfd < 0)
+ {
+ printf("receiver_thread: ERROR mq_open failed\n");
+ pthread_exit((pthread_addr_t)1);
+ }
+
+ /* Perform the receive TEST_RECEIVE_NMSGS times */
+
+ for (i = 0; i < TEST_RECEIVE_NMSGS; i++)
+ {
+ memset(msg_buffer, 0xaa, TEST_MSGLEN);
+ nbytes = mq_receive(mqfd, msg_buffer, TEST_MSGLEN, 0);
+ if (nbytes < 0)
+ {
+ /* mq_receive failed. If the error is because of EINTR then
+ * it is not a failure.
+ */
+
+ if (*get_errno_ptr() != EINTR)
+ {
+ printf("receiver_thread: ERROR mq_receive failure on msg %d, errno=%d\n", i, *get_errno_ptr());
+ nerrors++;
+ }
+ else
+ {
+ printf("receiver_thread: mq_receive interrupted!\n", i);
+ }
+ }
+ else if (nbytes != TEST_MSGLEN)
+ {
+ printf("receiver_thread: mq_receive return bad size %d on msg %d\n", nbytes, i);
+ nerrors++;
+ }
+ else if (memcmp(TEST_MESSAGE, msg_buffer, nbytes) != 0)
+ {
+ int j;
+
+ printf("receiver_thread: mq_receive returned corrupt message on msg %d\n", i);
+ printf("receiver_thread: i Expected Received\n");
+
+ for (j = 0; j < TEST_MSGLEN-1; j++)
+ {
+ if (isprint(msg_buffer[j]))
+ {
+ printf("receiver_thread: %2d %02x (%c) %02x (%c)\n",
+ j, TEST_MESSAGE[j], TEST_MESSAGE[j], msg_buffer[j], msg_buffer[j]);
+ }
+ else
+ {
+ printf("receiver_thread: %2d %02x (%c) %02x\n",
+ j, TEST_MESSAGE[j], TEST_MESSAGE[j], msg_buffer[j]);
+ }
+ }
+ printf("receiver_thread: %2d 00 %02x\n",
+ j, msg_buffer[j]);
+ }
+ else
+ {
+ printf("receiver_thread: mq_receive succeeded on msg %d\n", i);
+ }
+ }
+
+ /* Close the queue and return success */
+
+ if (mq_close(mqfd) < 0)
+ {
+ printf("receiver_thread: ERROR mq_close failed\n");
+ nerrors++;
+ }
+
+ /* Destroy the queue */
+
+ if (mq_unlink("testmq") < 0)
+ {
+ printf("receiver_thread: ERROR mq_close failed\n");
+ nerrors++;
+ }
+
+ printf("receiver_thread: returning nerrors=%d\n", nerrors);
+ pthread_exit((pthread_addr_t)nerrors);
+ return (pthread_addr_t)nerrors;
+}
+
+void mqueue_test(void)
+{
+ pthread_t sender;
+ pthread_t receiver;
+ void *result;
+ pthread_attr_t attr;
+ struct sched_param sparam;
+ int prio_min;
+ int prio_max;
+ int prio_mid;
+ int status;
+
+ /* Start the sending thread at higher priority */
+
+ printf("mqueue_test: Starting receiver\n");
+ status = pthread_attr_init(&attr);
+ if (status != 0)
+ {
+ printf("mqueue_test: pthread_attr_init failed, status=%d\n", status);
+ }
+
+ status = pthread_attr_setstacksize(&attr, STACKSIZE);
+ if (status != 0)
+ {
+ printf("mqueue_test: pthread_attr_setstacksize failed, status=%d\n", status);
+ }
+
+ prio_min = sched_get_priority_min(SCHED_FIFO);
+ prio_max = sched_get_priority_max(SCHED_FIFO);
+ prio_mid = (prio_min + prio_max) / 2;
+
+ sparam.sched_priority = prio_mid;
+ status = pthread_attr_setschedparam(&attr,&sparam);
+ if (status != OK)
+ {
+ printf("mqueue_test: pthread_attr_setschedparam failed, status=%d\n", status);
+ }
+ else
+ {
+ printf("mqueue_test: Set receiver priority to %d\n", sparam.sched_priority);
+ }
+
+ status = pthread_create(&receiver, &attr, receiver_thread, NULL);
+ if (status != 0)
+ {
+ printf("mqueue_test: pthread_create failed, status=%d\n", status);
+ }
+
+ /* Start the sending thread at lower priority */
+
+ printf("mqueue_test: Starting sender\n");
+ status = pthread_attr_init(&attr);
+ if (status != 0)
+ {
+ printf("mqueue_test: pthread_attr_init failed, status=%d\n", status);
+ }
+
+ status = pthread_attr_setstacksize(&attr, STACKSIZE);
+ if (status != 0)
+ {
+ printf("mqueue_test: pthread_attr_setstacksize failed, status=%d\n", status);
+ }
+
+ sparam.sched_priority = (prio_min + prio_mid) / 2;
+ status = pthread_attr_setschedparam(&attr,&sparam);
+ if (status != OK)
+ {
+ printf("mqueue_test: pthread_attr_setschedparam failed, status=%d\n", status);
+ }
+ else
+ {
+ printf("mqueue_test: Set sender thread priority to %d\n", sparam.sched_priority);
+ }
+
+ status = pthread_create(&sender, &attr, sender_thread, NULL);
+ if (status != 0)
+ {
+ printf("mqueue_test: pthread_create failed, status=%d\n", status);
+ }
+
+ printf("mqueue_test: Waiting for sender to complete\n");
+ pthread_join(sender, &result);
+ if (result != (void*)0)
+ {
+ printf("mqueue_test: ERROR sender thread exited with %d errors\n", (int)result);
+ }
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ /* Wake up the receiver thread with a signal */
+
+ printf("mqueue_test: Killing receiver\n");
+ pthread_kill(receiver, 9);
+
+ /* Wait a bit to see if the thread exits on its own */
+
+ usleep(HALF_SECOND_USEC_USEC);
+#endif
+
+ /* Then cancel the thread and see if it did */
+
+ printf("mqueue_test: Canceling receiver\n");
+ status = pthread_cancel(receiver);
+ if (status == ESRCH)
+ {
+ printf("mqueue_test: receiver has already terminated\n");
+ }
+
+ pthread_join(receiver, &result);
+ if (result != (void*)0)
+ {
+ printf("mqueue_test: ERROR receiver thread exited with %d errors\n", (int)result);
+ }
+}
+
+
diff --git a/apps/examples/ostest/mutex.c b/apps/examples/ostest/mutex.c
new file mode 100644
index 000000000..752f833f2
--- /dev/null
+++ b/apps/examples/ostest/mutex.c
@@ -0,0 +1,142 @@
+/***********************************************************************
+ * mutex.c
+ *
+ * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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. Neither the name NuttX 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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 <stdio.h>
+#include <pthread.h>
+#include "ostest.h"
+
+#ifndef NULL
+# define NULL (void*)0
+#endif
+
+#define NLOOPS 32
+
+static pthread_mutex_t mut;
+static volatile int my_mutex = 0;
+static unsigned long nloops[2] = {0, 0};
+static unsigned long nerrors[2] = {0, 0};
+
+static void *thread_func(void *parameter)
+{
+ int id = (int)parameter;
+ int ndx = id - 1;
+ int i;
+
+ for (nloops[ndx] = 0; nloops[ndx] < NLOOPS; nloops[ndx]++)
+ {
+ int status = pthread_mutex_lock(&mut);
+ if (status != 0)
+ {
+ printf("ERROR thread %d: pthread_mutex_lock failed, status=%d\n",
+ id, status);
+ }
+
+ if (my_mutex == 1)
+ {
+ printf("ERROR thread=%d: "
+ "my_mutex should be zero, instead my_mutex=%d\n",
+ id, my_mutex);
+ nerrors[ndx]++;
+ }
+
+ my_mutex = 1;
+ for (i = 0; i < 10; i++)
+ {
+ pthread_yield();
+ }
+ my_mutex = 0;
+
+ status = pthread_mutex_unlock(&mut);
+ if (status != 0)
+ {
+ printf("ERROR thread %d: pthread_mutex_unlock failed, status=%d\n",
+ id, status);
+ }
+ }
+ pthread_exit(NULL);
+ return NULL; /* Non-reachable -- needed for some compilers */
+}
+
+void mutex_test(void)
+{
+ pthread_t thread1, thread2;
+#ifdef SDCC
+ pthread_addr_t result1, result2;
+ pthread_attr_t attr;
+#endif
+ int status;
+
+ /* Initialize the mutex */
+
+ printf("Initializing mutex\n");
+ pthread_mutex_init(&mut, NULL);
+
+ /* Start two thread instances */
+
+ printf("Starting thread 1\n");
+#ifdef SDCC
+ (void)pthread_attr_init(&attr);
+ status = pthread_create(&thread1, &attr, thread_func, (pthread_addr_t)1);
+#else
+ status = pthread_create(&thread1, NULL, thread_func, (pthread_addr_t)1);
+#endif
+ if (status != 0)
+ {
+ printf("Error in thread#1 creation\n");
+ }
+
+ printf("Starting thread 2\n");
+#ifdef SDCC
+ status = pthread_create(&thread2, &attr, thread_func, (pthread_addr_t)2);
+#else
+ status = pthread_create(&thread2, NULL, thread_func, (pthread_addr_t)2);
+#endif
+ if (status != 0)
+ {
+ printf("Error in thread#2 creation\n");
+ }
+
+#ifdef SDCC
+ pthread_join(thread1, &result1);
+ pthread_join(thread2, &result2);
+#else
+ pthread_join(thread1, NULL);
+ pthread_join(thread2, NULL);
+#endif
+
+ printf("\t\tThread1\tThread2\n");
+ printf("\tLoops\t%ld\t%ld\n", nloops[0], nloops[1]);
+ printf("\tErrors\t%ld\t%ld\n", nerrors[0], nerrors[1]);
+}
diff --git a/apps/examples/ostest/ostest.h b/apps/examples/ostest/ostest.h
new file mode 100644
index 000000000..1cd705898
--- /dev/null
+++ b/apps/examples/ostest/ostest.h
@@ -0,0 +1,162 @@
+/****************************************************************************
+ * examples/ostest/ostest.h
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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. Neither the name NuttX 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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 __OSTEST_H
+#define __OSTEST_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/* The task_create task size can be specified in the defconfig file */
+
+#ifdef CONFIG_EXAMPLES_OSTEST_STACKSIZE
+# define STACKSIZE CONFIG_EXAMPLES_OSTEST_STACKSIZE
+#else
+# define STACKSIZE 8192
+#endif
+
+/* The number of times to execute the test can be specified in the defconfig
+ * file.
+ */
+
+#ifndef CONFIG_EXAMPLES_OSTEST_LOOPS
+# define CONFIG_EXAMPLES_OSTEST_LOOPS 1
+#endif
+
+/* This is the number of threads that are created in the barrier test.
+ * A smaller number should be selected on systems without sufficient memory
+ * to start so many threads.
+ */
+
+#ifndef CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS
+# define CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS 8
+#endif
+
+/* Priority inheritance */
+
+#if defined(CONFIG_DEBUG) && defined(CONFIG_PRIORITY_INHERITANCE) && defined(CONFIG_SEM_PHDEBUG)
+# define dump_nfreeholders(s) printf(s " nfreeholders: %d\n", sem_nfreeholders())
+#else
+# define dump_nfreeholders(s)
+#endif
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/* dev_null.c ***************************************************************/
+
+extern int dev_null(void);
+
+/* mutex.c ******************************************************************/
+
+extern void mutex_test(void);
+
+/* rmutex.c ******************************************************************/
+
+extern void recursive_mutex_test(void);
+
+/* sem.c ********************************************************************/
+
+extern void sem_test(void);
+
+/* cond.c *******************************************************************/
+
+extern void cond_test(void);
+
+/* mqueue.c *****************************************************************/
+
+extern void mqueue_test(void);
+
+/* timedmqueue.c ************************************************************/
+
+extern void timedmqueue_test(void);
+
+/* cancel.c *****************************************************************/
+
+extern void cancel_test(void);
+
+/* timedwait.c **************************************************************/
+
+extern void timedwait_test(void);
+
+/* sighand.c ****************************************************************/
+
+extern void sighand_test(void);
+
+/* posixtimers.c ************************************************************/
+
+extern void timer_test(void);
+
+/* roundrobin.c *************************************************************/
+
+extern void rr_test(void);
+
+/* barrier.c ****************************************************************/
+
+extern void barrier_test(void);
+
+/* prioinherit.c ************************************************************/
+
+extern void priority_inheritance(void);
+
+/* APIs exported (conditionally) by the OS specifically for testing of
+ * priority inheritance
+ */
+
+#if defined(CONFIG_DEBUG) && defined(CONFIG_PRIORITY_INHERITANCE) && defined(CONFIG_SEM_PHDEBUG)
+extern void sem_enumholders(FAR sem_t *sem);
+extern int sem_nfreeholders(void);
+#else
+# define sem_enumholders(sem)
+# define sem_nfreeholders()
+#endif
+
+#endif /* __OSTEST_H */
diff --git a/apps/examples/ostest/posixtimer.c b/apps/examples/ostest/posixtimer.c
new file mode 100644
index 000000000..457b4c1a2
--- /dev/null
+++ b/apps/examples/ostest/posixtimer.c
@@ -0,0 +1,268 @@
+/***********************************************************************
+ * examples/ostest/posixtimer.c
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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. Neither the name NuttX 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
+ *
+ ***********************************************************************/
+
+/**************************************************************************
+ * Included Files
+ **************************************************************************/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <sched.h>
+#include <errno.h>
+#include "ostest.h"
+
+/**************************************************************************
+ * Private Definitions
+ **************************************************************************/
+
+#ifndef NULL
+# define NULL (void*)0
+#endif
+
+#define MY_TIMER_SIGNAL 17
+#define SIGVALUE_INT 42
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0
+# define FFLUSH() fflush(stdout)
+#else
+# define FFLUSH()
+#endif
+
+/**************************************************************************
+ * Private Data
+ **************************************************************************/
+
+static sem_t sem;
+static int g_nsigreceived = 0;
+
+/**************************************************************************
+ * Private Functions
+ **************************************************************************/
+
+static void timer_expiration(int signo, siginfo_t *info, void *ucontext)
+{
+ sigset_t oldset;
+ sigset_t allsigs;
+ int status;
+
+ printf("timer_expiration: Received signal %d\n" , signo);
+
+ g_nsigreceived++;
+
+ /* Check signo */
+
+ if (signo != MY_TIMER_SIGNAL)
+ {
+ printf("timer_expiration: ERROR expected signo=%d\n" , MY_TIMER_SIGNAL);
+ }
+
+ /* Check siginfo */
+
+ if (info->si_value.sival_int != SIGVALUE_INT)
+ {
+ printf("timer_expiration: ERROR sival_int=%d expected %d\n",
+ info->si_value.sival_int, SIGVALUE_INT);
+ }
+ else
+ {
+ printf("timer_expiration: sival_int=%d\n" , info->si_value.sival_int);
+ }
+
+ if (info->si_signo != MY_TIMER_SIGNAL)
+ {
+ printf("timer_expiration: ERROR expected si_signo=%d, got=%d\n",
+ MY_TIMER_SIGNAL, info->si_signo);
+ }
+
+ if (info->si_code == SI_TIMER)
+ {
+ printf("timer_expiration: si_code=%d (SI_TIMER)\n" , info->si_code);
+ }
+ else
+ {
+ printf("timer_expiration: ERROR si_code=%d, expected SI_TIMER=%d\n",
+ info->si_code, SI_TIMER);
+ }
+
+ /* Check ucontext_t */
+
+ printf("timer_expiration: ucontext=%p\n" , ucontext);
+
+ /* Check sigprocmask */
+
+ (void)sigfillset(&allsigs);
+ status = sigprocmask(SIG_SETMASK, NULL, &oldset);
+ if (status != OK)
+ {
+ printf("timer_expiration: ERROR sigprocmask failed, status=%d\n",
+ status);
+ }
+
+ if (oldset != allsigs)
+ {
+ printf("timer_expiration: ERROR sigprocmask=%x expected=%x\n",
+ oldset, allsigs);
+ }
+
+}
+
+/**************************************************************************
+ * Public Functions
+ **************************************************************************/
+
+void timer_test(void)
+{
+ sigset_t sigset;
+ struct sigaction act;
+ struct sigaction oact;
+ struct sigevent notify;
+ struct itimerspec timer;
+ timer_t timerid;
+ int status;
+ int i;
+
+ printf("timer_test: Initializing semaphore to 0\n" );
+ sem_init(&sem, 0, 0);
+
+ /* Start waiter thread */
+
+ printf("timer_test: Unmasking signal %d\n" , MY_TIMER_SIGNAL);
+
+ (void)sigemptyset(&sigset);
+ (void)sigaddset(&sigset, MY_TIMER_SIGNAL);
+ status = sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+ if (status != OK)
+ {
+ printf("timer_test: ERROR sigprocmask failed, status=%d\n",
+ status);
+ }
+
+ printf("timer_test: Registering signal handler\n" );
+ act.sa_sigaction = timer_expiration;
+ act.sa_flags = SA_SIGINFO;
+
+ (void)sigfillset(&act.sa_mask);
+ (void)sigdelset(&act.sa_mask, MY_TIMER_SIGNAL);
+
+ status = sigaction(MY_TIMER_SIGNAL, &act, &oact);
+ if (status != OK)
+ {
+ printf("timer_test: ERROR sigaction failed, status=%d\n" , status);
+ }
+
+#ifndef SDCC
+ printf("timer_test: oact.sigaction=%p oact.sa_flags=%x oact.sa_mask=%x\n",
+ oact.sa_sigaction, oact.sa_flags, oact.sa_mask);
+#endif
+
+ /* Create the POSIX timer */
+
+ printf("timer_test: Creating timer\n" );
+
+ notify.sigev_notify = SIGEV_SIGNAL;
+ notify.sigev_signo = MY_TIMER_SIGNAL;
+ notify.sigev_value.sival_int = SIGVALUE_INT;
+
+ status = timer_create(CLOCK_REALTIME, &notify, &timerid);
+ if (status != OK)
+ {
+ printf("timer_test: timer_create failed, errno=%d\n", errno);
+ goto errorout;
+ }
+
+ /* Start the POSIX timer */
+
+ printf("timer_test: Starting timer\n" );
+
+ timer.it_value.tv_sec = 2;
+ timer.it_value.tv_nsec = 0;
+ timer.it_interval.tv_sec = 2;
+ timer.it_interval.tv_nsec = 0;
+
+ status = timer_settime(timerid, 0, &timer, NULL);
+ if (status != OK)
+ {
+ printf("timer_test: timer_settime failed, errno=%d\n", errno);
+ goto errorout;
+ }
+
+ /* Take the semaphore */
+
+ for (i = 0; i < 5; i++)
+ {
+ printf("timer_test: Waiting on semaphore\n" );
+ FFLUSH();
+ status = sem_wait(&sem);
+ if (status != 0)
+ {
+ int error = errno;
+ if (error == EINTR)
+ {
+ printf("timer_test: sem_wait() successfully interrupted by signal\n" );
+ }
+ else
+ {
+ printf("timer_test: ERROR sem_wait failed, errno=%d\n" , error);
+ }
+ }
+ else
+ {
+ printf("timer_test: ERROR awakened with no error!\n" );
+ }
+ printf("timer_test: g_nsigreceived=%d\n", g_nsigreceived);
+ }
+
+errorout:
+ sem_destroy(&sem);
+
+ /* Then delete the timer */
+
+ printf("timer_test: Deleting timer\n" );
+ status = timer_delete(timerid);
+ if (status != OK)
+ {
+ printf("timer_test: timer_create failed, errno=%d\n", errno);
+ }
+
+ /* Detach the signal handler */
+
+ act.sa_sigaction = SIG_DFL;
+ status = sigaction(MY_TIMER_SIGNAL, &act, &oact);
+
+ printf("timer_test: done\n" );
+ FFLUSH();
+}
diff --git a/apps/examples/ostest/prioinherit.c b/apps/examples/ostest/prioinherit.c
new file mode 100644
index 000000000..5d59c1297
--- /dev/null
+++ b/apps/examples/ostest/prioinherit.c
@@ -0,0 +1,541 @@
+/****************************************************************************
+ * examples/ostest/prioinherit.c
+ *
+ * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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. Neither the name NuttX 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <semaphore.h>
+#include <pthread.h>
+#include <errno.h>
+
+#ifdef CONFIG_ARCH_SIM
+# include <nuttx/arch.h>
+#endif
+
+#include "ostest.h"
+
+#if defined(CONFIG_PRIORITY_INHERITANCE) && !defined(CONFIG_DISABLE_SIGNALS) && !defined(CONFIG_DISABLE_PTHREAD)
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_SEM_PREALLOCHOLDERS
+# define CONFIG_SEM_PREALLOCHOLDERS 0
+#endif
+#define NLOWPRI_THREADS (CONFIG_SEM_PREALLOCHOLDERS+1)
+
+#ifndef CONFIG_SEM_NNESTPRIO
+# define CONFIG_SEM_NNESTPRIO 0
+#endif
+#define NHIGHPRI_THREADS (CONFIG_SEM_NNESTPRIO+1)
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+enum thstate_e
+{
+ NOTSTARTED = 0,
+ RUNNING,
+ WAITING,
+ DONE
+};
+
+static sem_t g_sem;
+static volatile enum thstate_e g_middlestate;
+static volatile enum thstate_e g_highstate[NHIGHPRI_THREADS];
+static volatile enum thstate_e g_lowstate[NLOWPRI_THREADS];
+static int g_highpri;
+static int g_medpri;
+static int g_lowpri;
+
+/****************************************************************************
+ * Name: nhighpri_waiting
+ ****************************************************************************/
+
+static int nhighpri_waiting(void)
+{
+ int n = 0;
+ int i;
+
+ for (i = 0; i < NHIGHPRI_THREADS; i++)
+ {
+ if (g_highstate[i] == WAITING)
+ {
+ n++;
+ }
+ }
+ return n;
+}
+
+/****************************************************************************
+ * Name: nhighpri_running
+ ****************************************************************************/
+
+static int nhighpri_running(void)
+{
+ int n = 0;
+ int i;
+
+ for (i = 0; i < NHIGHPRI_THREADS; i++)
+ {
+ if (g_highstate[i] != DONE)
+ {
+ n++;
+ }
+ }
+ return n;
+}
+
+/****************************************************************************
+ * Name: highpri_thread
+ ****************************************************************************/
+
+static void *highpri_thread(void *parameter)
+{
+ int threadno = (int)parameter;
+ int ret;
+
+ g_highstate[threadno-1] = RUNNING;
+
+ printf("highpri_thread-%d: Started\n", threadno);
+ fflush(stdout);
+ sleep(1);
+
+ printf("highpri_thread-%d: Calling sem_wait()\n", threadno);
+ g_highstate[threadno-1] = WAITING;
+ ret = sem_wait(&g_sem);
+ g_highstate[threadno-1] = DONE;
+
+ if (ret != 0)
+ {
+ printf("highpri_thread-%d: sem_take failed: %d\n", threadno, ret);
+ }
+ else if (g_middlestate == RUNNING)
+ {
+ printf("highpri_thread-%d: SUCCESS midpri_thread is still running!\n", threadno);
+ }
+ else
+ {
+ printf("highpri_thread-%d: ERROR -- midpri_thread has already exited!\n", threadno);
+ }
+
+ sem_post(&g_sem);
+ printf("highpri_thread-%d: Okay... I'm done!\n", threadno);
+ fflush(stdout);
+ return NULL;
+}
+
+/****************************************************************************
+ * Name: hog_cpu
+ ****************************************************************************/
+
+static inline void hog_cpu(void)
+{
+#ifdef CONFIG_ARCH_SIM
+ /* The simulator doesn't have any mechanism to do asynchronous pre-emption
+ * (basically because it doesn't have any interupts/asynchronous events).
+ * The simulator does "fake" a timer interrupt in up_idle() -- the idle
+ * thread that only executes when nothing else is running. In the simulator,
+ * we cannot suspend the middle priority task, or we wouldn't have the
+ * test that we want. So, we have no option but to pump the fake clock
+ * here by calling up_idle(). Sigh!
+ */
+
+ up_idle();
+#else
+ /* On real platforms with a real timer interrupt, we really can hog the
+ * CPU. When the sleep() goes off in priority_inheritance(), it will
+ * wake up and start the high priority thread.
+ */
+
+ volatile int i;
+ for (i = 0; i < INT_MAX; i++);
+#endif
+}
+
+/****************************************************************************
+ * Name: medpri_thread
+ ****************************************************************************/
+
+static void *medpri_thread(void *parameter)
+{
+ printf("medpri_thread: Started ... I won't let go of the CPU!\n");
+ g_middlestate = RUNNING;
+ fflush(stdout);
+
+ /* The following loop will completely block lowpri_thread from running.
+ * UNLESS priority inheritance is working. In that case, its priority
+ * will be boosted.
+ */
+
+ while (nhighpri_running() > 0)
+ {
+ hog_cpu();
+ }
+
+ printf("medpri_thread: Okay... I'm done!\n");
+ fflush(stdout);
+ g_middlestate = DONE;
+ return NULL;
+}
+
+/****************************************************************************
+ * Name: lowpri_thread
+ ****************************************************************************/
+
+static void *lowpri_thread(void *parameter)
+{
+ void *retval = (void*)-1;
+ struct sched_param sparam;
+ int threadno = (int)parameter;
+ int expected;
+ int count;
+ int policy;
+ int ret;
+ int nwaiting;
+ int i;
+
+ g_lowstate[threadno-1] = RUNNING;
+ printf("lowpri_thread-%d: Started\n", threadno);
+
+ ret = pthread_getschedparam(pthread_self(), &policy, &sparam);
+ if (ret != 0)
+ {
+ printf("lowpri_thread-%d: ERROR pthread_getschedparam failed: %d\n", threadno, ret);
+ }
+ else
+ {
+ printf("lowpri_thread-%d: initial priority: %d\n", threadno, sparam.sched_priority);
+ if (sparam.sched_priority != g_lowpri)
+ {
+ printf(" ERROR should have been %d\n", g_lowpri);
+ }
+ }
+
+ g_lowstate[threadno-1] = WAITING;
+ ret = sem_wait(&g_sem);
+ if (ret != 0)
+ {
+ printf("lowpri_thread-%d: sem_take failed: %d\n", threadno, ret);
+ }
+ else
+ {
+ /* Hang on to the thread until the middle priority thread runs */
+
+ while (g_middlestate == NOTSTARTED && nhighpri_waiting() < NHIGHPRI_THREADS)
+ {
+ printf("lowpri_thread-%d: Waiting for the midle pri task to run\n", threadno);
+ printf(" g_middlestate: %d\n", (int)g_middlestate);
+ for (i = 0; i < NHIGHPRI_THREADS; i++)
+ {
+ printf(" g_highstate[%d]: %d\n", i, (int)g_highstate[i]);
+ }
+ printf(" I still have a count on the semaphore\n");
+ sem_enumholders(&g_sem);
+ fflush(stdout);
+ sleep(1);
+ }
+
+ /* Account for all of the semaphore counts. At any given time if there are 'n'
+ * running hight prioity tasks, then the semaphore count should be '-n'
+ */
+
+ sched_lock(); /* Needs to be atomic */
+ ret = sem_getvalue(&g_sem, &count);
+ nwaiting = nhighpri_waiting();
+ sched_unlock();
+
+ if (ret < 0)
+ {
+ printf("lowpri_thread-%d: ERROR sem_getvalue failed: %d\n", threadno, errno);
+ }
+ printf("lowpri_thread-%d: Sem count: %d, No. highpri thread: %d\n", threadno, count, nwaiting);
+
+ /* The middle priority task is running, let go of the semaphore */
+
+ if (g_middlestate == RUNNING && nwaiting == -count)
+ {
+ /* Good.. the middle priority task is still running and the counts are okay. */
+
+ retval = NULL;
+ }
+ else
+ {
+ /* If the sem count is positive, then there all of the higher priority threads
+ * should have already completed.
+ */
+
+ printf("lowpri_thread-%d: %s the middle priority task has already exitted!\n",
+ threadno, count >= 0 ? "SUCCESS" : "ERROR" );
+ printf(" g_middlestate: %d sem count=%d\n", (int)g_middlestate, count);
+ for (i = 0; i < NHIGHPRI_THREADS; i++)
+ {
+ printf(" g_highstate[%d]: %d\n", i, (int)g_highstate[i]);
+ }
+ }
+ }
+
+ ret = pthread_getschedparam(pthread_self(), &policy, &sparam);
+ sem_enumholders(&g_sem);
+ sem_post(&g_sem);
+ if (ret != 0)
+ {
+ printf("lowpri_thread-%d: ERROR pthread_getschedparam failed: %d\n", threadno, ret);
+ }
+ else
+ {
+ if (nwaiting > 0)
+ {
+ expected = g_highpri;
+ }
+ else
+ {
+ expected = g_lowpri;
+ }
+
+ printf("lowpri_thread-%d: %s priority before sem_post: %d\n",
+ threadno,
+ sparam.sched_priority != expected ? "ERROR" : "SUCCESS",
+ sparam.sched_priority);
+
+ if (sparam.sched_priority != expected)
+ {
+ printf(" ERROR should have been %d\n", expected);
+ }
+ }
+
+ ret = pthread_getschedparam(pthread_self(), &policy, &sparam);
+ if (ret != 0)
+ {
+ printf("lowpri_thread-%d: ERROR pthread_getschedparam failed: %d\n", threadno, ret);
+ }
+ else
+ {
+ printf("lowpri_thread-%d: %s final priority: %d\n",
+ threadno,
+ sparam.sched_priority != g_lowpri ? "ERROR" : "SUCCESS",
+ sparam.sched_priority);
+
+ if (sparam.sched_priority != g_lowpri)
+ {
+ printf(" ERROR should have been %d\n", g_lowpri);
+ }
+ }
+ sem_enumholders(&g_sem);
+
+ printf("lowpri_thread-%d: Okay... I'm done!\n", threadno);
+ fflush(stdout);
+ g_lowstate[threadno-1] = DONE;
+ return retval;
+}
+#endif /* CONFIG_PRIORITY_INHERITANCE && !CONFIG_DISABLE_SIGNALS && !CONFIG_DISABLE_PTHREAD */
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: priority_inheritance
+ ****************************************************************************/
+
+void priority_inheritance(void)
+{
+#if defined(CONFIG_PRIORITY_INHERITANCE) && !defined(CONFIG_DISABLE_SIGNALS) && !defined(CONFIG_DISABLE_PTHREAD)
+ pthread_t lowpri[NLOWPRI_THREADS];
+ pthread_t medpri;
+ pthread_t highpri[NHIGHPRI_THREADS];
+ pthread_addr_t result;
+ pthread_attr_t attr;
+ struct sched_param sparam;
+ int my_pri;
+ int status;
+ int i;
+
+ printf("priority_inheritance: Started\n");
+
+ g_middlestate = NOTSTARTED;
+ for (i = 0; i < NHIGHPRI_THREADS; i++) g_highstate[i] = NOTSTARTED;
+ for (i = 0; i < NLOWPRI_THREADS; i++) g_lowstate[i] = NOTSTARTED;
+
+ status = sched_getparam (getpid(), &sparam);
+ if (status != 0)
+ {
+ printf("priority_inheritance: sched_getparam failed\n");
+ sparam.sched_priority = PTHREAD_DEFAULT_PRIORITY;
+ }
+ my_pri = sparam.sched_priority;
+
+ g_highpri = sched_get_priority_max(SCHED_FIFO);
+ g_lowpri = sched_get_priority_min(SCHED_FIFO);
+ g_medpri = my_pri - 1;
+
+ sem_init(&g_sem, 0, NLOWPRI_THREADS);
+ dump_nfreeholders("priority_inheritance:");
+
+ /* Start the low priority threads */
+
+ for (i = 0; i < NLOWPRI_THREADS; i++)
+ {
+ int threadno = i+1;
+ printf("priority_inheritance: Starting lowpri_thread-%d (of %d) at %d\n",
+ threadno, NLOWPRI_THREADS, g_lowpri);
+ status = pthread_attr_init(&attr);
+ if (status != 0)
+ {
+ printf("priority_inheritance: pthread_attr_init failed, status=%d\n", status);
+ }
+ sparam.sched_priority = g_lowpri;
+ status = pthread_attr_setschedparam(&attr,& sparam);
+ if (status != OK)
+ {
+ printf("priority_inheritance: pthread_attr_setschedparam failed, status=%d\n", status);
+ }
+ else
+ {
+ printf("priority_inheritance: Set lowpri_thread-%d priority to %d\n",
+ threadno, sparam.sched_priority);
+ }
+
+ status = pthread_create(&lowpri[i], &attr, lowpri_thread, (void*)threadno);
+ if (status != 0)
+ {
+ printf("priority_inheritance: pthread_create failed, status=%d\n", status);
+ }
+ }
+ printf("priority_inheritance: Waiting...\n");
+ sleep(2);
+ dump_nfreeholders("priority_inheritance:");
+
+ /* Start the medium priority thread */
+
+ printf("priority_inheritance: Starting medpri_thread at %d\n", g_medpri);
+ status = pthread_attr_init(&attr);
+ if (status != 0)
+ {
+ printf("priority_inheritance: pthread_attr_init failed, status=%d\n", status);
+ }
+
+ sparam.sched_priority = g_medpri;
+ status = pthread_attr_setschedparam(&attr,& sparam);
+ if (status != OK)
+ {
+ printf("priority_inheritance: pthread_attr_setschedparam failed, status=%d\n", status);
+ }
+ else
+ {
+ printf("priority_inheritance: Set medpri_thread priority to %d\n", sparam.sched_priority);
+ }
+ fflush(stdout);
+
+ status = pthread_create(&medpri, &attr, medpri_thread, NULL);
+ if (status != 0)
+ {
+ printf("priority_inheritance: pthread_create failed, status=%d\n", status);
+ }
+ printf("priority_inheritance: Waiting...\n");
+ sleep(1);
+ dump_nfreeholders("priority_inheritance:");
+
+ /* Start the high priority threads */
+
+ for (i = 0; i < NHIGHPRI_THREADS; i++)
+ {
+ int threadno = i+1;
+ printf("priority_inheritance: Starting highpri_thread-%d (of %d) at %d\n",
+ threadno, NHIGHPRI_THREADS, g_highpri);
+ status = pthread_attr_init(&attr);
+ if (status != 0)
+ {
+ printf("priority_inheritance: pthread_attr_init failed, status=%d\n", status);
+ }
+
+ sparam.sched_priority = g_highpri - i;
+ status = pthread_attr_setschedparam(&attr,& sparam);
+ if (status != OK)
+ {
+ printf("priority_inheritance: pthread_attr_setschedparam failed, status=%d\n", status);
+ }
+ else
+ {
+ printf("priority_inheritance: Set highpri_thread-%d priority to %d\n",
+ threadno, sparam.sched_priority);
+ }
+ fflush(stdout);
+
+ status = pthread_create(&highpri[i], &attr, highpri_thread, (void*)threadno);
+ if (status != 0)
+ {
+ printf("priority_inheritance: pthread_create failed, status=%d\n", status);
+ }
+ }
+ dump_nfreeholders("priority_inheritance:");
+ fflush(stdout);
+
+ /* Wait for all thread instances to complete */
+
+ for (i = 0; i < NHIGHPRI_THREADS; i++)
+ {
+ printf("priority_inheritance: Waiting for highpri_thread-%d to complete\n", i+1);
+ fflush(stdout);
+ (void)pthread_join(highpri[i], &result);
+ dump_nfreeholders("priority_inheritance:");
+ }
+ printf("priority_inheritance: Waiting for medpri_thread to complete\n");
+ fflush(stdout);
+ (void)pthread_join(medpri, &result);
+ dump_nfreeholders("priority_inheritance:");
+ for (i = 0; i < NLOWPRI_THREADS; i++)
+ {
+ printf("priority_inheritance: Waiting for lowpri_thread-%d to complete\n", i+1);
+ fflush(stdout);
+ (void)pthread_join(lowpri[i], &result);
+ dump_nfreeholders("priority_inheritance:");
+ }
+
+ printf("priority_inheritance: Finished\n");
+ sem_destroy(&g_sem);
+ dump_nfreeholders("priority_inheritance:");
+ fflush(stdout);
+#endif /* CONFIG_PRIORITY_INHERITANCE && !CONFIG_DISABLE_SIGNALS && !CONFIG_DISABLE_PTHREAD */
+}
diff --git a/apps/examples/ostest/rmutex.c b/apps/examples/ostest/rmutex.c
new file mode 100644
index 000000000..44eb4bb3b
--- /dev/null
+++ b/apps/examples/ostest/rmutex.c
@@ -0,0 +1,166 @@
+/***********************************************************************
+ * rmutex.c
+ *
+ * Copyright (C) 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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. Neither the name NuttX 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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 <stdio.h>
+#include <pthread.h>
+#include "ostest.h"
+
+#ifndef NULL
+# define NULL (void*)0
+#endif
+
+#define NTHREADS 3
+#define NLOOPS 3
+#define NRECURSIONS 3
+
+static pthread_mutex_t mut;
+
+static void thread_inner(int id, int level)
+{
+ int status;
+ if (level < NRECURSIONS)
+ {
+ /* Take the mutex */
+
+ printf("thread_inner[%d, %d]: Locking\n", id, level);
+ status = pthread_mutex_lock(&mut);
+ if (status != 0)
+ {
+ printf("thread_inner[%d, %d]: ERROR pthread_mutex_lock failed: %d\n",
+ id, level, status);
+ }
+ printf("thread_inner[%d, %d]: Locked\n", id, level);
+
+ /* Give the other threads a chance */
+
+ pthread_yield();
+ thread_inner(id, level+1);
+ pthread_yield();
+
+ /* Unlock the mutex */
+
+ printf("thread_inner[%d, %d]: Unlocking\n", id, level);
+ status = pthread_mutex_unlock(&mut);
+ if (status != 0)
+ {
+ printf("thread_inner[%d, %d]: ERROR pthread_mutex_unlock failed: %d\n",
+ id, level, status);
+ }
+ printf("thread_inner[%d, %d]: Unlocked\n", id, level);
+ pthread_yield();
+ }
+}
+
+static void *thread_outer(void *parameter)
+{
+ int i;
+ printf("thread_outer[%d]: Started\n", (int)parameter);
+ for (i = 0; i < NLOOPS; i++)
+ {
+ printf("thread_outer[%d]: Loop %d\n", (int)parameter, i);
+ thread_inner((int)parameter, 0);
+ }
+ printf("thread_outer[%d]: Exitting\n", (int)parameter);
+ pthread_exit(NULL);
+ return NULL; /* Non-reachable -- needed for some compilers */
+}
+
+void recursive_mutex_test(void)
+{
+ pthread_t thread[NTHREADS];
+#ifdef SDCC
+ pthread_addr_t result[NTHREADS];
+ pthread_attr_t attr;
+#endif
+ pthread_mutexattr_t mattr;
+ int type;
+ int status;
+ int i;
+
+ /* Initialize the mutex attributes */
+
+ pthread_mutexattr_init(&mattr);
+ status = pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
+ if (status != 0)
+ {
+ printf("recursive_mutex_test: ERROR pthread_mutexattr_settype failed, status=%d\n", status);
+ }
+
+ status = pthread_mutexattr_gettype(&mattr, &type);
+ if (status != 0)
+ {
+ printf("recursive_mutex_test: ERROR pthread_mutexattr_gettype failed, status=%d\n", status);
+ }
+ if (type != PTHREAD_MUTEX_RECURSIVE)
+ {
+ printf("recursive_mutex_test: ERROR pthread_mutexattr_gettype return type=%d\n", type);
+ }
+
+ /* Initialize the mutex */
+
+ printf("recursive_mutex_test: Initializing mutex\n");
+ pthread_mutex_init(&mut, &mattr);
+
+ /* Start the threads -- all at the same, default priority */
+
+ for (i = 0; i < NTHREADS; i++)
+ {
+ printf("recursive_mutex_test: Starting thread %d\n", i+1);
+#ifdef SDCC
+ (void)pthread_attr_init(&attr);
+ status = pthread_create(&thread[i], &attr, thread_outer, (pthread_addr_t)i+1);
+#else
+ status = pthread_create(&thread[i], NULL, thread_outer, (pthread_addr_t)i+1);
+#endif
+ if (status != 0)
+ {
+ printf("recursive_mutex_test: ERRROR thread#%d creation: %d\n", i+1, status);
+ }
+ }
+
+ /* Wait for all; of the threads to complete */
+
+ for (i = 0; i < NTHREADS; i++)
+ {
+ printf("recursive_mutex_test: Waiting for thread %d\n", i+1);
+#ifdef SDCC
+ pthread_join(thread[i], &result1);
+#else
+ pthread_join(thread[i], NULL);
+#endif
+ }
+
+ printf("recursive_mutex_test: Complete\n");
+}
diff --git a/apps/examples/ostest/roundrobin.c b/apps/examples/ostest/roundrobin.c
new file mode 100644
index 000000000..061d51f3d
--- /dev/null
+++ b/apps/examples/ostest/roundrobin.c
@@ -0,0 +1,232 @@
+/********************************************************************************
+ * examples/ostest/roundrobin.c
+ *
+ * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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. Neither the name NuttX 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
+ *
+ ********************************************************************************/
+
+/********************************************************************************
+ * Included Files
+ ********************************************************************************/
+
+#include <nuttx/config.h>
+#include <stdio.h>
+#include "ostest.h"
+
+#if CONFIG_RR_INTERVAL > 0
+
+/********************************************************************************
+ * Definitions
+ ********************************************************************************/
+
+/* This number may need to be tuned for different processor speeds. Since these
+ * arrays must be large to very correct SCHED_RR behavior, this test may require
+ * too much memory on many targets.
+ */
+
+/* #define CONFIG_NINTEGERS 32768 Takes forever on 60Mhz ARM7 */
+
+#define CONFIG_NINTEGERS 2048
+
+/********************************************************************************
+ * Private Data
+ ********************************************************************************/
+
+static int prime1[CONFIG_NINTEGERS];
+static int prime2[CONFIG_NINTEGERS];
+
+/********************************************************************************
+ * Private Functions
+ ********************************************************************************/
+
+/********************************************************************************
+ * Name: dosieve
+ *
+ * Description
+ * This implements a "sieve of aristophanes" algorithm for finding prime number.
+ * Credit for this belongs to someone, but I am not sure who anymore. Anyway,
+ * the only purpose here is that we need some algorithm that takes a long period
+ * of time to execute.
+ *
+ ********************************************************************************/
+
+static void dosieve(int *prime)
+{
+ int a,d;
+ int i;
+ int j;
+
+ a = 2;
+ d = a;
+
+ for (i = 0; i < CONFIG_NINTEGERS; i++)
+ {
+ prime[i] = i+2;
+ }
+
+ for (i = 1; i < 10; i++)
+ {
+ for (j = 0; j < CONFIG_NINTEGERS; j++)
+ {
+ d = a + d;
+ if (d < CONFIG_NINTEGERS)
+ {
+ prime[d]=0;
+ }
+ }
+ a++;
+ d = a;
+ i++;
+ }
+
+#if 0 /* We don't really care what the numbers are */
+ for (i = 0, j= 0; i < CONFIG_NINTEGERS; i++)
+ {
+ if (prime[i] != 0)
+ {
+ printf(" Prime %d: %d\n", j, prime[i]);
+ j++;
+ }
+ }
+#endif
+}
+
+/********************************************************************************
+ * Name: sieve1
+ ********************************************************************************/
+
+static void *sieve1(void *parameter)
+{
+ int i;
+
+ printf("sieve1 started\n");
+
+ for (i = 0; i < 1000; i++)
+ {
+ dosieve(prime1);
+ }
+
+ printf("sieve1 finished\n");
+
+ pthread_exit(NULL);
+ return NULL; /* To keep some compilers happy */
+}
+
+/********************************************************************************
+ * Name: sieve2
+ ********************************************************************************/
+
+static void *sieve2(void *parameter)
+{
+ int i;
+
+ printf("sieve2 started\n");
+
+ for (i = 0; i < 1000; i++)
+ {
+ dosieve(prime2);
+ }
+
+ printf("sieve2 finished\n");
+
+ pthread_exit(NULL);
+ return NULL; /* To keep some compilers happy */
+}
+
+/********************************************************************************
+ * Public Functions
+ ********************************************************************************/
+
+/********************************************************************************
+ * Name: rr_test
+ ********************************************************************************/
+
+void rr_test(void)
+{
+ pthread_t sieve1_thread;
+ pthread_t sieve2_thread;
+ struct sched_param sparam;
+ pthread_attr_t attr;
+ pthread_addr_t result;
+ int status;
+
+ printf("rr_test: Starting sieve1 thread \n");
+ status = pthread_attr_init(&attr);
+ if (status != OK)
+ {
+ printf("rr_test: pthread_attr_init failed, status=%d\n", status);
+ }
+
+ sparam.sched_priority = sched_get_priority_min(SCHED_FIFO);
+ status = pthread_attr_setschedparam(&attr, &sparam);
+ if (status != OK)
+ {
+ printf("rr_test: pthread_attr_setschedparam failed, status=%d\n", status);
+ }
+ else
+ {
+ printf("rr_test: Set thread priority to %d\n", sparam.sched_priority);
+ }
+
+ status = pthread_attr_setschedpolicy(&attr, SCHED_RR);
+ if (status != OK)
+ {
+ printf("rr_test: pthread_attr_setschedpolicy failed, status=%d\n", status);
+ }
+ else
+ {
+ printf("rr_test: Set thread policty to SCHED_RR\n");
+ }
+
+ status = pthread_create(&sieve1_thread, &attr, sieve1, NULL);
+ if (status != 0)
+ {
+ printf("rr_test: Error in thread 1 creation, status=%d\n", status);
+ }
+
+ printf("rr_test: Starting sieve1 thread \n");
+
+ status = pthread_create(&sieve2_thread, &attr, sieve2, NULL);
+ if (status != 0)
+ {
+ printf("rr_test: Error in thread 2 creation, status=%d\n", status);
+ }
+
+ printf("rr_test: Waiting for sieves to complete -- this should take awhile\n");
+ printf("rr_test: If RR scheduling is working, they should start and complete at\n");
+ printf("rr_test: about the same time\n");
+
+ pthread_join(sieve2_thread, &result);
+ pthread_join(sieve1_thread, &result);
+ printf("rr_test: Done\n");
+}
+
+#endif /* CONFIG_RR_INTERVAL */
diff --git a/apps/examples/ostest/sem.c b/apps/examples/ostest/sem.c
new file mode 100644
index 000000000..850cf8040
--- /dev/null
+++ b/apps/examples/ostest/sem.c
@@ -0,0 +1,246 @@
+/***********************************************************************
+ * sem.c
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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. Neither the name NuttX 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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 <stdio.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <sched.h>
+#include "ostest.h"
+
+#ifndef NULL
+# define NULL (void*)0
+#endif
+
+static sem_t sem;
+
+static void *waiter_func(void *parameter)
+{
+ int id = (int)parameter;
+ int status;
+ int value;
+
+ printf("waiter_func: Thread %d Started\n", id);
+
+ /* Take the semaphore */
+
+ status = sem_getvalue(&sem, &value);
+ if (status < 0)
+ {
+ printf("waiter_func: ERROR thread %d could not get semaphore value\n", id);
+ }
+ else
+ {
+ printf("waiter_func: Thread %d initial semaphore value = %d\n", id, value);
+ }
+
+ printf("waiter_func: Thread %d waiting on semaphore\n", id);
+ status = sem_wait(&sem);
+ if (status != 0)
+ {
+ printf("waiter_func: ERROR thread %d sem_wait failed\n", id);
+ }
+ printf("waiter_func: Thread %d awakened\n", id);
+
+ status = sem_getvalue(&sem, &value);
+ if (status < 0)
+ {
+ printf("waiter_func: ERROR thread %d could not get semaphore value\n", id);
+ }
+ else
+ {
+ printf("waiter_func: Thread %d new semaphore value = %d\n", id, value);
+ }
+
+ printf("waiter_func: Thread %d done\n", id);
+ return NULL;
+}
+
+static void *poster_func(void *parameter)
+{
+ int id = (int)parameter;
+ int status;
+ int value;
+
+ printf("poster_func: Thread %d started\n", id);
+
+ /* Take the semaphore */
+
+ do
+ {
+ status = sem_getvalue(&sem, &value);
+ if (status < 0)
+ {
+ printf("poster_func: ERROR thread %d could not get semaphore value\n", id);
+ }
+ else
+ {
+ printf("poster_func: Thread %d semaphore value = %d\n", id, value);
+ }
+
+ if (value < 0)
+ {
+ printf("poster_func: Thread %d posting semaphore\n", id);
+ status = sem_post(&sem);
+ if (status != 0)
+ {
+ printf("poster_func: ERROR thread %d sem_wait failed\n", id);
+ }
+
+ pthread_yield();
+
+ status = sem_getvalue(&sem, &value);
+ if (status < 0)
+ {
+ printf("poster_func: ERROR thread %d could not get semaphore value\n", id);
+ }
+ else
+ {
+ printf("poster_func: Thread %d new semaphore value = %d\n", id, value);
+ }
+ }
+ }
+ while (value < 0);
+
+ printf("poster_func: Thread %d done\n", id);
+ return NULL;
+
+}
+
+void sem_test(void)
+{
+ pthread_t waiter_thread1;
+ pthread_t waiter_thread2;
+ pthread_t poster_thread;
+#ifdef SDCC
+ pthread_addr_t result;
+#endif
+ struct sched_param sparam;
+ int prio_min;
+ int prio_max;
+ int prio_mid;
+ pthread_attr_t attr;
+ int status;
+
+ printf("sem_test: Initializing semaphore to 0\n");
+ sem_init(&sem, 0, 0);
+
+ /* Start two waiter thread instances */
+
+ printf("sem_test: Starting waiter thread 1\n");
+ status = pthread_attr_init(&attr);
+ if (status != OK)
+ {
+ printf("sem_test: pthread_attr_init failed, status=%d\n", status);
+ }
+
+ prio_min = sched_get_priority_min(SCHED_FIFO);
+ prio_max = sched_get_priority_max(SCHED_FIFO);
+ prio_mid = (prio_min + prio_max) / 2;
+
+ sparam.sched_priority = (prio_mid + prio_max) / 2;
+ status = pthread_attr_setschedparam(&attr,&sparam);
+ if (status != OK)
+ {
+ printf("sem_test: pthread_attr_setschedparam failed, status=%d\n", status);
+ }
+ else
+ {
+ printf("sem_test: Set thread 1 priority to %d\n", sparam.sched_priority);
+ }
+
+ status = pthread_create(&waiter_thread1, &attr, waiter_func, (pthread_addr_t)1);
+ if (status != 0)
+ {
+ printf("sem_test: Error in thread 1 creation, status=%d\n", status);
+ }
+
+ printf("sem_test: Starting waiter thread 2\n");
+ status = pthread_attr_init(&attr);
+ if (status != 0)
+ {
+ printf("sem_test: pthread_attr_init failed, status=%d\n", status);
+ }
+
+ sparam.sched_priority = prio_mid;
+ status = pthread_attr_setschedparam(&attr,&sparam);
+ if (status != OK)
+ {
+ printf("sem_test: pthread_attr_setschedparam failed, status=%d\n", status);
+ }
+ else
+ {
+ printf("sem_test: Set thread 2 priority to %d\n", sparam.sched_priority);
+ }
+
+ status = pthread_create(&waiter_thread2, &attr, waiter_func, (pthread_addr_t)2);
+ if (status != 0)
+ {
+ printf("sem_test: Error in thread 2 creation, status=%d\n", status);
+ }
+
+ printf("sem_test: Starting poster thread 3\n");
+ status = pthread_attr_init(&attr);
+ if (status != 0)
+ {
+ printf("sem_test: pthread_attr_init failed, status=%d\n", status);
+ }
+
+ sparam.sched_priority = (prio_min + prio_mid) / 2;
+ status = pthread_attr_setschedparam(&attr,&sparam);
+ if (status != OK)
+ {
+ printf("sem_test: pthread_attr_setschedparam failed, status=%d\n", status);
+ }
+ else
+ {
+ printf("sem_test: Set thread 3 priority to %d\n", sparam.sched_priority);
+ }
+
+ status = pthread_create(&poster_thread, &attr, poster_func, (pthread_addr_t)3);
+ if (status != 0)
+ {
+ printf("sem_test: Error in thread 3 creation, status=%d\n", status);
+ }
+
+#ifdef SDCC
+ pthread_join(waiter_thread1, &result);
+ pthread_join(waiter_thread2, &result);
+ pthread_join(poster_thread, &result);
+#else
+ pthread_join(waiter_thread1, NULL);
+ pthread_join(waiter_thread2, NULL);
+ pthread_join(poster_thread, NULL);
+#endif
+}
diff --git a/apps/examples/ostest/sighand.c b/apps/examples/ostest/sighand.c
new file mode 100644
index 000000000..46650be1c
--- /dev/null
+++ b/apps/examples/ostest/sighand.c
@@ -0,0 +1,279 @@
+/***********************************************************************
+ * examples/ostest/sighand.c
+ *
+ * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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. Neither the name NuttX 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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 <sys/types.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <sched.h>
+#include <errno.h>
+#include "ostest.h"
+
+#ifndef NULL
+# define NULL (void*)0
+#endif
+
+#define WAKEUP_SIGNAL 17
+#define SIGVALUE_INT 42
+
+static sem_t sem;
+static bool sigreceived = false;
+static bool threadexited = false;
+
+static void wakeup_action(int signo, siginfo_t *info, void *ucontext)
+{
+ sigset_t oldset;
+ sigset_t allsigs;
+ int status;
+
+ printf("wakeup_action: Received signal %d\n" , signo);
+
+ sigreceived = true;
+
+ /* Check signo */
+
+ if (signo != WAKEUP_SIGNAL)
+ {
+ printf("wakeup_action: ERROR expected signo=%d\n" , WAKEUP_SIGNAL);
+ }
+
+ /* Check siginfo */
+
+ if (info->si_value.sival_int != SIGVALUE_INT)
+ {
+ printf("wakeup_action: ERROR sival_int=%d expected %d\n",
+ info->si_value.sival_int, SIGVALUE_INT);
+ }
+ else
+ {
+ printf("wakeup_action: sival_int=%d\n" , info->si_value.sival_int);
+ }
+
+ if (info->si_signo != WAKEUP_SIGNAL)
+ {
+ printf("wakeup_action: ERROR expected si_signo=%d, got=%d\n",
+ WAKEUP_SIGNAL, info->si_signo);
+ }
+
+ printf("wakeup_action: si_code=%d\n" , info->si_code);
+
+ /* Check ucontext_t */
+
+ printf("wakeup_action: ucontext=%p\n" , ucontext);
+
+ /* Check sigprocmask */
+
+ (void)sigfillset(&allsigs);
+ status = sigprocmask(SIG_SETMASK, NULL, &oldset);
+ if (status != OK)
+ {
+ printf("wakeup_action: ERROR sigprocmask failed, status=%d\n",
+ status);
+ }
+
+ if (oldset != allsigs)
+ {
+ printf("wakeup_action: ERROR sigprocmask=%x expected=%x\n",
+ oldset, allsigs);
+ }
+}
+
+static int waiter_main(int argc, char *argv[])
+{
+ sigset_t sigset;
+ struct sigaction act;
+ struct sigaction oact;
+ int status;
+
+ printf("waiter_main: Waiter started\n" );
+
+ printf("waiter_main: Unmasking signal %d\n" , WAKEUP_SIGNAL);
+ (void)sigemptyset(&sigset);
+ (void)sigaddset(&sigset, WAKEUP_SIGNAL);
+ status = sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+ if (status != OK)
+ {
+ printf("waiter_main: ERROR sigprocmask failed, status=%d\n",
+ status);
+ }
+
+ printf("waiter_main: Registering signal handler\n" );
+ act.sa_sigaction = wakeup_action;
+ act.sa_flags = SA_SIGINFO;
+
+ (void)sigfillset(&act.sa_mask);
+ (void)sigdelset(&act.sa_mask, WAKEUP_SIGNAL);
+
+ status = sigaction(WAKEUP_SIGNAL, &act, &oact);
+ if (status != OK)
+ {
+ printf("waiter_main: ERROR sigaction failed, status=%d\n" , status);
+ }
+
+#ifndef SDCC
+ printf("waiter_main: oact.sigaction=%p oact.sa_flags=%x oact.sa_mask=%x\n",
+ oact.sa_sigaction, oact.sa_flags, oact.sa_mask);
+#endif
+
+ /* Take the semaphore */
+
+ printf("waiter_main: Waiting on semaphore\n" );
+
+#if CONFIG_NFILE_STREAMS > 0
+ fflush(stdout);
+#endif
+
+ status = sem_wait(&sem);
+ if (status != 0)
+ {
+ int error = *get_errno_ptr();
+ if (error == EINTR)
+ {
+ printf("waiter_main: sem_wait() successfully interrupted by signal\n" );
+ }
+ else
+ {
+ printf("waiter_main: ERROR sem_wait failed, errno=%d\n" , error);
+ }
+ }
+ else
+ {
+ printf("waiter_main: ERROR awakened with no error!\n" );
+ }
+
+ /* Detach the signal handler */
+
+ act.sa_sigaction = SIG_DFL;
+ status = sigaction(WAKEUP_SIGNAL, &act, &oact);
+
+ printf("waiter_main: done\n" );
+
+#if CONFIG_NFILE_STREAMS > 0
+ fflush(stdout);
+#endif
+
+ threadexited = true;
+ return 0;
+}
+
+void sighand_test(void)
+{
+ struct sched_param param;
+ union sigval sigvalue;
+ pid_t waiterpid;
+ int policy;
+ int status;
+
+ printf("sighand_test: Initializing semaphore to 0\n" );
+ sem_init(&sem, 0, 0);
+
+ /* Start waiter thread */
+
+ printf("sighand_test: Starting waiter task\n" );
+ status = sched_getparam (0, &param);
+ if (status != OK)
+ {
+ printf("sighand_test: ERROR sched_getparam() failed\n" );
+ param.sched_priority = PTHREAD_DEFAULT_PRIORITY;
+ }
+
+ policy = sched_getscheduler(0);
+ if (policy == ERROR)
+ {
+ printf("sighand_test: ERROR sched_getscheduler() failed\n" );
+ policy = SCHED_FIFO;
+ }
+
+ waiterpid = task_create("waiter", param.sched_priority,
+ PTHREAD_STACK_DEFAULT, waiter_main, NULL);
+ if (waiterpid == ERROR)
+ {
+ printf("sighand_test: ERROR failed to start waiter_main\n" );
+ }
+ else
+ {
+ printf("sighand_test: Started waiter_main pid=%d\n", waiterpid);
+ }
+
+ /* Wait a bit */
+
+#if CONFIG_NFILE_STREAMS > 0
+ fflush(stdout);
+#endif
+ sleep(2);
+
+ /* Then signal the waiter thread. */
+
+ printf("sighand_test: Signaling pid=%d with signo=%d sigvalue=%d\n",
+ waiterpid, WAKEUP_SIGNAL, SIGVALUE_INT);
+
+ sigvalue.sival_int = SIGVALUE_INT;
+#ifdef CONFIG_CAN_PASS_STRUCTS
+ status = sigqueue(waiterpid, WAKEUP_SIGNAL, sigvalue);
+#else
+ status = sigqueue(waiterpid, WAKEUP_SIGNAL, sigvalue.sival_ptr);
+#endif
+ if (status != OK)
+ {
+ printf("sighand_test: ERROR sigqueue failed\n" );
+ task_delete(waiterpid);
+ }
+
+ /* Wait a bit */
+
+#if CONFIG_NFILE_STREAMS > 0
+ fflush(stdout);
+#endif
+ sleep(2);
+
+ /* Then check the result */
+
+ if (!threadexited)
+ {
+ printf("sighand_test: ERROR waiter task did not exit\n" );
+ }
+
+ if (!sigreceived)
+ {
+ printf("sighand_test: ERROR signal handler did not run\n" );
+ }
+
+ printf("sighand_test: done\n" );
+#if CONFIG_NFILE_STREAMS > 0
+ fflush(stdout);
+#endif
+}
diff --git a/apps/examples/ostest/timedmqueue.c b/apps/examples/ostest/timedmqueue.c
new file mode 100644
index 000000000..9c14ec414
--- /dev/null
+++ b/apps/examples/ostest/timedmqueue.c
@@ -0,0 +1,393 @@
+/**************************************************************************
+ * examples/ostest/mqueue.c
+ *
+ * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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. Neither the name NuttX 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
+ *
+ **************************************************************************/
+
+/**************************************************************************
+ * Included Files
+ **************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <mqueue.h>
+#include <sched.h>
+#include <errno.h>
+
+#include "ostest.h"
+
+/**************************************************************************
+ * Private Definitions
+ **************************************************************************/
+
+#define TEST_MESSAGE "This is a test and only a test"
+#if defined(SDCC) || defined(__ZILOG__)
+ /* Cannot use strlen in array size */
+
+# define TEST_MSGLEN (31)
+#else
+ /* Message lenght is the size of the message plus the null terminator */
+
+# define TEST_MSGLEN (strlen(TEST_MESSAGE)+1)
+#endif
+
+#define TEST_SEND_NMSGS (10)
+#define TEST_RECEIVE_NMSGS (10)
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0
+# define FFLUSH() fflush(stdout)
+#else
+# define FFLUSH()
+#endif
+
+/**************************************************************************
+ * Private Types
+ **************************************************************************/
+
+/**************************************************************************
+ * Private Function Prototypes
+ **************************************************************************/
+
+/**************************************************************************
+ * Global Variables
+ **************************************************************************/
+
+/**************************************************************************
+ * Private Variables
+ **************************************************************************/
+
+/**************************************************************************
+ * Private Functions
+ **************************************************************************/
+
+/**************************************************************************
+ * Public Functions
+ **************************************************************************/
+
+static void *sender_thread(void *arg)
+{
+ mqd_t mqfd;
+ char msg_buffer[TEST_MSGLEN];
+ struct mq_attr attr;
+ int status = 0;
+ int nerrors = 0;
+ int i;
+
+ printf("sender_thread: Starting\n");
+
+ /* Fill in attributes for message queue */
+
+ attr.mq_maxmsg = TEST_SEND_NMSGS-1;
+ attr.mq_msgsize = TEST_MSGLEN;
+ attr.mq_flags = 0;
+
+ /* Set the flags for the open of the queue.
+ * Make it a blocking open on the queue, meaning it will block if
+ * this process tries to send to the queue and the queue is full.
+ *
+ * O_CREAT - the queue will get created if it does not already exist.
+ * O_WRONLY - we are only planning to write to the queue.
+ *
+ * Open the queue, and create it if the receiving process hasn't
+ * already created it.
+ */
+
+ mqfd = mq_open("testmq", O_WRONLY|O_CREAT, 0666, &attr);
+ if (mqfd < 0)
+ {
+ printf("sender_thread: ERROR mq_open failed\n");
+ pthread_exit((pthread_addr_t)1);
+ }
+
+ /* Fill in a test message buffer to send */
+
+ memcpy(msg_buffer, TEST_MESSAGE, TEST_MSGLEN);
+
+ /* Perform the send TEST_SEND_NMSGS times */
+
+ for (i = 0; i < TEST_SEND_NMSGS; i++)
+ {
+ struct timespec time;
+ status = clock_gettime(CLOCK_REALTIME, &time);
+ if (status != 0)
+ {
+ printf("sender_thread: ERROR clock_gettime failed\n");
+ }
+ time.tv_sec += 5;
+
+ /* The first TEST_SEND_NMSGS-1 send should succeed. The last
+ * one should fail with errno == ETIMEDOUT
+ */
+
+ status = mq_timedsend(mqfd, msg_buffer, TEST_MSGLEN, 42, &time);
+ if (status < 0)
+ {
+ if (i == TEST_SEND_NMSGS-1 && *get_errno_ptr() == ETIMEDOUT)
+ {
+ printf("sender_thread: mq_timedsend %d timed out as expected\n", i);
+ }
+ else
+ {
+ printf("sender_thread: ERROR mq_timedsend failure=%d on msg %d\n", *get_errno_ptr(), i);
+ nerrors++;
+ }
+ }
+ else
+ {
+ if (i == TEST_SEND_NMSGS-1)
+ {
+ printf("sender_thread: ERROR mq_timedsend of msg %d succeeded\n", i);
+ nerrors++;
+ }
+ else
+ {
+ printf("sender_thread: mq_timedsend succeeded on msg %d\n", i);
+ }
+ }
+ }
+
+ /* Close the queue and return success */
+
+ if (mq_close(mqfd) < 0)
+ {
+ printf("sender_thread: ERROR mq_close failed\n");
+ }
+
+ printf("sender_thread: returning nerrors=%d\n", nerrors);
+ FFLUSH();
+ return (pthread_addr_t)nerrors;
+}
+
+static void *receiver_thread(void *arg)
+{
+ mqd_t mqfd;
+ char msg_buffer[TEST_MSGLEN];
+ struct mq_attr attr;
+ int nbytes;
+ int nerrors = 0;
+ int i;
+
+ printf("receiver_thread: Starting\n");
+
+ /* Fill in attributes for message queue */
+
+ attr.mq_maxmsg = TEST_SEND_NMSGS-1;
+ attr.mq_msgsize = TEST_MSGLEN;
+ attr.mq_flags = 0;
+
+ /* Set the flags for the open of the queue.
+ * Make it a blocking open on the queue, meaning it will block if
+ * this process tries to* send to the queue and the queue is full.
+ *
+ * O_CREAT - the queue will get created if it does not already exist.
+ * O_RDONLY - we are only planning to write to the queue.
+ *
+ * Open the queue, and create it if the sending process hasn't
+ * already created it.
+ */
+
+ mqfd = mq_open("testmq", O_RDONLY|O_CREAT, 0666, &attr);
+ if (mqfd < 0)
+ {
+ printf("receiver_thread: ERROR mq_open failed\n");
+ pthread_exit((pthread_addr_t)1);
+ }
+
+ /* Perform the receive TEST_RECEIVE_NMSGS times */
+
+ for (i = 0; i < TEST_RECEIVE_NMSGS; i++)
+ {
+ struct timespec time;
+ int status = clock_gettime(CLOCK_REALTIME, &time);
+ if (status != 0)
+ {
+ printf("sender_thread: ERROR clock_gettime failed\n");
+ }
+ time.tv_sec += 5;
+
+ /* The first TEST_SEND_NMSGS-1 send should succeed. The last
+ * one should fail with errno == ETIMEDOUT
+ */
+
+ memset(msg_buffer, 0xaa, TEST_MSGLEN);
+ nbytes = mq_timedreceive(mqfd, msg_buffer, TEST_MSGLEN, 0, &time);
+ if (nbytes < 0)
+ {
+ if (i == TEST_SEND_NMSGS-1 && *get_errno_ptr() == ETIMEDOUT)
+ {
+ printf("receiver_thread: Receive %d timed out as expected\n", i);
+ }
+ else
+ {
+ printf("receiver_thread: ERROR mq_timedreceive failure=%d on msg %d\n", *get_errno_ptr(), i);
+ nerrors++;
+ }
+ }
+ else if (nbytes != TEST_MSGLEN)
+ {
+ printf("receiver_thread: mq_timedreceive return bad size %d on msg %d\n", nbytes, i);
+ nerrors++;
+ }
+ else if (memcmp(TEST_MESSAGE, msg_buffer, nbytes) != 0)
+ {
+ int j;
+
+ printf("receiver_thread: mq_timedreceive returned corrupt message on msg %d\n", i);
+ printf("receiver_thread: i Expected Received\n");
+
+ for (j = 0; j < TEST_MSGLEN-1; j++)
+ {
+ if (isprint(msg_buffer[j]))
+ {
+ printf("receiver_thread: %2d %02x (%c) %02x (%c)\n",
+ j, TEST_MESSAGE[j], TEST_MESSAGE[j], msg_buffer[j], msg_buffer[j]);
+ }
+ else
+ {
+ printf("receiver_thread: %2d %02x (%c) %02x\n",
+ j, TEST_MESSAGE[j], TEST_MESSAGE[j], msg_buffer[j]);
+ }
+ }
+ printf("receiver_thread: %2d 00 %02x\n",
+ j, msg_buffer[j]);
+ }
+ else if (i == TEST_SEND_NMSGS-1)
+ {
+ printf("receiver_thread: ERROR mq_timedreceive of msg %d succeeded\n", i);
+ nerrors++;
+ }
+ else
+ {
+ printf("receiver_thread: mq_timedreceive succeeded on msg %d\n", i);
+ }
+ }
+
+ /* Close the queue and return success */
+
+ if (mq_close(mqfd) < 0)
+ {
+ printf("receiver_thread: ERROR mq_close failed\n");
+ nerrors++;
+ }
+
+ /* Destroy the queue */
+
+ if (mq_unlink("testmq") < 0)
+ {
+ printf("receiver_thread: ERROR mq_close failed\n");
+ nerrors++;
+ }
+
+ printf("receiver_thread: returning nerrors=%d\n", nerrors);
+ FFLUSH();
+ pthread_exit((pthread_addr_t)nerrors);
+ return (pthread_addr_t)nerrors;
+}
+
+void timedmqueue_test(void)
+{
+ pthread_t sender;
+ pthread_t receiver;
+ void *result;
+ pthread_attr_t attr;
+ int status;
+
+ /* Start the sending thread at the default priority */
+
+ printf("timedmqueue_test: Starting sender\n");
+ status = pthread_attr_init(&attr);
+ if (status != 0)
+ {
+ printf("timedmqueue_test: pthread_attr_init failed, status=%d\n", status);
+ }
+
+ status = pthread_attr_setstacksize(&attr, STACKSIZE);
+ if (status != 0)
+ {
+ printf("timedmqueue_test: pthread_attr_setstacksize failed, status=%d\n", status);
+ }
+
+ status = pthread_create(&sender, &attr, sender_thread, NULL);
+ if (status != 0)
+ {
+ printf("timedmqueue_test: pthread_create failed, status=%d\n", status);
+ }
+
+ /* Wait for the sending thread to complete */
+
+ printf("timedmqueue_test: Waiting for sender to complete\n");
+ pthread_join(sender, &result);
+ if (result != (void*)0)
+ {
+ printf("timedmqueue_test: ERROR sender thread exited with %d errors\n", (int)result);
+ }
+
+ /* Start the receiving thread at the default priority */
+
+ printf("timedmqueue_test: Starting receiver\n");
+ status = pthread_attr_init(&attr);
+ if (status != 0)
+ {
+ printf("timedmqueue_test: pthread_attr_init failed, status=%d\n", status);
+ }
+
+ status = pthread_attr_setstacksize(&attr, STACKSIZE);
+ if (status != 0)
+ {
+ printf("timedmqueue_test: pthread_attr_setstacksize failed, status=%d\n", status);
+ }
+
+ status = pthread_create(&receiver, &attr, receiver_thread, NULL);
+ if (status != 0)
+ {
+ printf("timedmqueue_test: pthread_create failed, status=%d\n", status);
+ }
+
+ /* Wait for the receiving thread to complete */
+
+ printf("timedmqueue_test: Waiting for receiver to complete\n");
+ pthread_join(receiver, &result);
+ if (result != (void*)0)
+ {
+ printf("timedmqueue_test: ERROR receiver thread exited with %d errors\n", (int)result);
+ }
+
+ printf("timedmqueue_test: Test complete\n");
+}
+
+
diff --git a/apps/examples/ostest/timedwait.c b/apps/examples/ostest/timedwait.c
new file mode 100644
index 000000000..51622bad8
--- /dev/null
+++ b/apps/examples/ostest/timedwait.c
@@ -0,0 +1,201 @@
+/***********************************************************************
+ * examples/ostest/timedwait.c
+ *
+ * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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. Neither the name NuttX 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
+ *
+ ***********************************************************************/
+
+/**************************************************************************
+ * Included Files
+ **************************************************************************/
+
+#include <stdio.h>
+#include <time.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "ostest.h"
+
+/**************************************************************************
+ * Private Definitions
+ **************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0
+# define FFLUSH() fflush(stdout)
+#else
+# define FFLUSH()
+#endif
+
+/**************************************************************************
+ * Private Data
+ **************************************************************************/
+
+static pthread_mutex_t mutex;
+static pthread_cond_t cond;
+
+/**************************************************************************
+ * Private Functions
+ **************************************************************************/
+
+static void *thread_waiter(void *parameter)
+{
+ struct timespec time;
+ int status;
+
+ /* Take the mutex */
+
+ printf("thread_waiter: Taking mutex\n");
+ status = pthread_mutex_lock(&mutex);
+ if (status != 0)
+ {
+ printf("thread_waiter: ERROR pthread_mutex_lock failed, status=%d\n", status);
+ }
+
+ printf("thread_waiter: Starting 5 second wait for condition\n");
+
+ status = clock_gettime(CLOCK_REALTIME, &time);
+ if (status != 0)
+ {
+ printf("thread_waiter: ERROR clock_gettime failed\n");
+ }
+ time.tv_sec += 5;
+
+ /* The wait -- no-one is ever going to awaken us */
+
+ status = pthread_cond_timedwait(&cond, &mutex, &time);
+ if (status != 0)
+ {
+ if (status == ETIMEDOUT)
+ {
+ printf("thread_waiter: pthread_cond_timedwait timed out\n");
+ }
+ else
+ {
+ printf("thread_waiter: ERROR pthread_cond_timedwait failed, status=%d\n", status);
+ }
+ }
+ else
+ {
+ printf("thread_waiter: ERROR pthread_cond_timedwait returned without timeout, status=%d\n", status);
+ }
+
+ /* Release the mutex */
+
+ printf("thread_waiter: Releasing mutex\n");
+ status = pthread_mutex_unlock(&mutex);
+ if (status != 0)
+ {
+ printf("thread_waiter: ERROR pthread_mutex_unlock failed, status=%d\n", status);
+ }
+
+ printf("thread_waiter: Exit with status 0x12345678\n");
+ pthread_exit((pthread_addr_t)0x12345678);
+ return NULL;
+}
+
+/**************************************************************************
+ * Public Definitions
+ **************************************************************************/
+
+void timedwait_test(void)
+{
+ pthread_t waiter;
+ pthread_attr_t attr;
+ struct sched_param sparam;
+ void *result;
+ int prio_max;
+ int status;
+
+ /* Initialize the mutex */
+
+ printf("thread_waiter: Initializing mutex\n");
+ status = pthread_mutex_init(&mutex, NULL);
+ if (status != 0)
+ {
+ printf("timedwait_test: ERROR pthread_mutex_init failed, status=%d\n", status);
+ }
+
+ /* Initialize the condition variable */
+
+ printf("timedwait_test: Initializing cond\n");
+ status = pthread_cond_init(&cond, NULL);
+ if (status != 0)
+ {
+ printf("timedwait_test: ERROR pthread_condinit failed, status=%d\n", status);
+ }
+
+ /* Start the waiter thread at higher priority */
+
+ printf("timedwait_test: Starting waiter\n");
+ status = pthread_attr_init(&attr);
+ if (status != 0)
+ {
+ printf("timedwait_test: pthread_attr_init failed, status=%d\n", status);
+ }
+
+ prio_max = sched_get_priority_max(SCHED_FIFO);
+ status = sched_getparam (getpid(), &sparam);
+ if (status != 0)
+ {
+ printf("timedwait_test: sched_getparam failed\n");
+ sparam.sched_priority = PTHREAD_DEFAULT_PRIORITY;
+ }
+
+ sparam.sched_priority = (prio_max + sparam.sched_priority) / 2;
+ status = pthread_attr_setschedparam(&attr,&sparam);
+ if (status != OK)
+ {
+ printf("timedwait_test: pthread_attr_setschedparam failed, status=%d\n", status);
+ }
+ else
+ {
+ printf("timedwait_test: Set thread 2 priority to %d\n", sparam.sched_priority);
+ }
+
+ status = pthread_create(&waiter, &attr, thread_waiter, NULL);
+ if (status != 0)
+ {
+ printf("timedwait_test: pthread_create failed, status=%d\n", status);
+ }
+
+ printf("timedwait_test: Joining\n");
+ FFLUSH();
+ status = pthread_join(waiter, &result);
+ if (status != 0)
+ {
+ printf("timedwait_test: ERROR pthread_join failed, status=%d\n", status);
+ }
+ else
+ {
+ printf("timedwait_test: waiter exited with result=%p\n", result);
+ }
+}