From d5f8008931ccd7a75675176a5533b95aea9bcd14 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 30 Dec 2015 16:29:21 -0600 Subject: [PATCH] OS test: Add a test of POSIX timers using SIGEV_THREAD. Also, clean up many warnings with building on a PC with 64-bit addresses --- ChangeLog.txt | 3 + examples/ostest/Makefile | 3 + examples/ostest/aio.c | 4 + examples/ostest/barrier.c | 4 +- examples/ostest/cancel.c | 2 +- examples/ostest/mqueue.c | 22 ++-- examples/ostest/mutex.c | 4 +- examples/ostest/ostest.h | 1 + examples/ostest/ostest_main.c | 10 +- examples/ostest/posixtimer.c | 10 +- examples/ostest/rmutex.c | 16 +-- examples/ostest/sem.c | 4 +- examples/ostest/sigev_thread.c | 185 +++++++++++++++++++++++++++++++++ examples/ostest/timedmqueue.c | 29 ++++-- 14 files changed, 259 insertions(+), 38 deletions(-) create mode 100644 examples/ostest/sigev_thread.c diff --git a/ChangeLog.txt b/ChangeLog.txt index 8b2ed90a3..13a2dec7a 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1504,3 +1504,6 @@ (2015-12-13). * apps/examples/pca9635: Add a simple test of PCA9635PW PWM LED driver. From Alan Carvalho de Assis (2015-12-15). + * apps/examples/ostest: Add a test of POSIX timers using + SIGEV_THREAD (20156-12-30). + diff --git a/examples/ostest/Makefile b/examples/ostest/Makefile index 32befbb71..e9c862eec 100644 --- a/examples/ostest/Makefile +++ b/examples/ostest/Makefile @@ -94,6 +94,9 @@ endif # CONFIG_DISABLE_MQUEUE ifneq ($(CONFIG_DISABLE_POSIX_TIMERS),y) CSRCS += posixtimer.c +ifeq ($(CONFIG_SIG_EVTHREAD),y) +CSRCS += sigev_thread.c +endif endif ifeq ($(CONFIG_ARCH_HAVE_VFORK),y) diff --git a/examples/ostest/aio.c b/examples/ostest/aio.c index 5313c55a6..3652e1b71 100644 --- a/examples/ostest/aio.c +++ b/examples/ostest/aio.c @@ -137,6 +137,10 @@ static void init_aiocb(bool signal) { aiocbp->aio_sigevent.sigev_notify = signal ? SIGEV_SIGNAL : SIGEV_NONE; aiocbp->aio_sigevent.sigev_signo = SIGUSR1; +#ifdef CONFIG_SIG_EVTHREAD + aiocbp->aio_sigevent.sigev_notify_function = NULL; + aiocbp->aio_sigevent.sigev_notify_attributes = NULL; +#endif aiocbp->aio_buf = g_buffers[i]; aiocbp->aio_offset = (off_t)g_offsets[i]; diff --git a/examples/ostest/barrier.c b/examples/ostest/barrier.c index 494502ce4..f099b0e7d 100644 --- a/examples/ostest/barrier.c +++ b/examples/ostest/barrier.c @@ -65,7 +65,7 @@ static pthread_barrier_t barrier; static void *barrier_func(void *parameter) { - int id = (int)parameter; + int id = (int)((intptr_t)parameter); int status; printf("barrier_func: Thread %d started\n", id); @@ -156,7 +156,7 @@ void barrier_test(void) for (i = 0; i < CONFIG_EXAMPLES_OSTEST_NBARRIER_THREADS; i++) { status = pthread_create(&barrier_thread[i], &attr, barrier_func, - (pthread_addr_t)i); + (pthread_addr_t)((uintptr_t)i)); if (status != 0) { printf("barrier_test: Error in thread %d create, status=%d\n", diff --git a/examples/ostest/cancel.c b/examples/ostest/cancel.c index 5bd395020..73b214955 100644 --- a/examples/ostest/cancel.c +++ b/examples/ostest/cancel.c @@ -140,7 +140,7 @@ static void start_thread(pthread_t *waiter, int cancelable) /* Start the waiter thread */ printf("start_thread: Starting thread\n"); - status = pthread_create(waiter, &attr, thread_waiter, (pthread_addr_t)cancelable); + status = pthread_create(waiter, &attr, thread_waiter, (pthread_addr_t)((uintptr_t)cancelable)); if (status != 0) { printf("start_thread: ERROR pthread_create failed, status=%d\n", status); diff --git a/examples/ostest/mqueue.c b/examples/ostest/mqueue.c index 3def67cbb..b7974f8db 100644 --- a/examples/ostest/mqueue.c +++ b/examples/ostest/mqueue.c @@ -168,7 +168,7 @@ static void *sender_thread(void *arg) } printf("sender_thread: returning nerrors=%d\n", nerrors); - return (pthread_addr_t)nerrors; + return (pthread_addr_t)((uintptr_t)nerrors); } static void *receiver_thread(void *arg) @@ -275,8 +275,8 @@ static void *receiver_thread(void *arg) } printf("receiver_thread: returning nerrors=%d\n", nerrors); - pthread_exit((pthread_addr_t)nerrors); - return (pthread_addr_t)nerrors; + pthread_exit((pthread_addr_t)((uintptr_t)nerrors)); + return (pthread_addr_t)((uintptr_t)nerrors); } void mqueue_test(void) @@ -345,18 +345,21 @@ void mqueue_test(void) status = pthread_attr_setstacksize(&attr, STACKSIZE); if (status != 0) { - printf("mqueue_test: pthread_attr_setstacksize failed, status=%d\n", status); + 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); + 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); + printf("mqueue_test: Set sender thread priority to %d\n", + sparam.sched_priority); } status = pthread_create(&sender, &attr, sender_thread, NULL); @@ -367,9 +370,10 @@ void mqueue_test(void) printf("mqueue_test: Waiting for sender to complete\n"); pthread_join(sender, &result); - if (result != (void*)0) + if (result != (FAR void *)0) { - printf("mqueue_test: ERROR sender thread exited with %d errors\n", (int)result); + printf("mqueue_test: ERROR sender thread exited with %d errors\n", + (int)((intptr_t)result)); } #ifndef CONFIG_DISABLE_SIGNALS @@ -406,7 +410,7 @@ void mqueue_test(void) printf("mqueue_test: ERROR receiver thread should have exited with %p\n", expected); printf(" ERROR Instead exited with nerrors=%d\n", - (int)result); + (int)((intptr_t)result)); } /* Message queues are global resources and persist for the life the the diff --git a/examples/ostest/mutex.c b/examples/ostest/mutex.c index a99ee7f69..2ee637488 100644 --- a/examples/ostest/mutex.c +++ b/examples/ostest/mutex.c @@ -48,9 +48,9 @@ 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) +static void *thread_func(FAR void *parameter) { - int id = (int)parameter; + int id = (int)((intptr_t)parameter); int ndx = id - 1; int i; diff --git a/examples/ostest/ostest.h b/examples/ostest/ostest.h index c97dd8a70..84921b50d 100644 --- a/examples/ostest/ostest.h +++ b/examples/ostest/ostest.h @@ -182,6 +182,7 @@ void signest_test(void); /* posixtimers.c ************************************************************/ void timer_test(void); +void sigev_thread_test(void); /* roundrobin.c *************************************************************/ diff --git a/examples/ostest/ostest_main.c b/examples/ostest/ostest_main.c index 1450373dc..e47fc67b5 100644 --- a/examples/ostest/ostest_main.c +++ b/examples/ostest/ostest_main.c @@ -459,11 +459,19 @@ static int user_main(int argc, char *argv[]) #endif #if !defined(CONFIG_DISABLE_POSIX_TIMERS) && !defined(CONFIG_DISABLE_SIGNALS) - /* Verify posix timers */ + /* Verify posix timers (with SIGEV_SIGNAL) */ printf("\nuser_main: POSIX timer test\n"); timer_test(); check_test_memory_usage(); + +#ifdef CONFIG_SIG_EVTHREAD + /* Verify posix timers (with SIGEV_THREAD) */ + + printf("\nuser_main: SIGEV_THREAD timer test\n"); + sigev_thread_test(); + check_test_memory_usage(); +#endif #endif #if !defined(CONFIG_DISABLE_PTHREAD) && CONFIG_RR_INTERVAL > 0 diff --git a/examples/ostest/posixtimer.c b/examples/ostest/posixtimer.c index 9f95536d3..355cb8ec6 100644 --- a/examples/ostest/posixtimer.c +++ b/examples/ostest/posixtimer.c @@ -187,9 +187,13 @@ void timer_test(void) printf("timer_test: Creating timer\n" ); - notify.sigev_notify = SIGEV_SIGNAL; - notify.sigev_signo = MY_TIMER_SIGNAL; - notify.sigev_value.sival_int = SIGVALUE_INT; + notify.sigev_notify = SIGEV_SIGNAL; + notify.sigev_signo = MY_TIMER_SIGNAL; + notify.sigev_value.sival_int = SIGVALUE_INT; +#ifdef CONFIG_SIG_EVTHREAD + notify.sigev_notify_function = NULL; + notify.sigev_notify_attributes = NULL; +#endif status = timer_create(CLOCK_REALTIME, ¬ify, &timerid); if (status != OK) diff --git a/examples/ostest/rmutex.c b/examples/ostest/rmutex.c index 4cd61d6c0..3557fdb2f 100644 --- a/examples/ostest/rmutex.c +++ b/examples/ostest/rmutex.c @@ -99,16 +99,18 @@ static void thread_inner(int id, int level) } } -static void *thread_outer(void *parameter) +static FAR void *thread_outer(FAR void *parameter) { int i; - printf("thread_outer[%d]: Started\n", (int)parameter); + + printf("thread_outer[%d]: Started\n", (int)((intptr_t)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]: Loop %d\n", (int)((intptr_t)parameter), i); + thread_inner((int)((intptr_t)parameter), 0); } - printf("thread_outer[%d]: Exitting\n", (int)parameter); + + printf("thread_outer[%d]: Exitting\n", (int)((intptr_t)parameter)); pthread_exit(NULL); return NULL; /* Non-reachable -- needed for some compilers */ } @@ -160,9 +162,9 @@ void recursive_mutex_test(void) 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); + status = pthread_create(&thread[i], &attr, thread_outer, (pthread_addr_t)((uintptr_t)i+1)); #else - status = pthread_create(&thread[i], NULL, thread_outer, (pthread_addr_t)i+1); + status = pthread_create(&thread[i], NULL, thread_outer, (pthread_addr_t)((uintptr_t)i+1)); #endif if (status != 0) { diff --git a/examples/ostest/sem.c b/examples/ostest/sem.c index 6b22c7f03..584afa310 100644 --- a/examples/ostest/sem.c +++ b/examples/ostest/sem.c @@ -63,7 +63,7 @@ static sem_t sem; static void *waiter_func(void *parameter) { - int id = (int)parameter; + int id = (int)((intptr_t)parameter); int status; int value; @@ -105,7 +105,7 @@ static void *waiter_func(void *parameter) static void *poster_func(void *parameter) { - int id = (int)parameter; + int id = (int)((intptr_t)parameter); int status; int value; diff --git a/examples/ostest/sigev_thread.c b/examples/ostest/sigev_thread.c new file mode 100644 index 000000000..eac87e6b2 --- /dev/null +++ b/examples/ostest/sigev_thread.c @@ -0,0 +1,185 @@ +/**************************************************************************** + * examples/ostest/sigev_thread.c + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include +#include +#include + +#include "ostest.h" + +/**************************************************************************** + * Private Definitions + ****************************************************************************/ + +#ifndef NULL +# define NULL (void*)0 +#endif + +#define MY_TIMER_SIGNAL 17 +#define SIGVALUE_INT 42 + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static sem_t g_sigev_thread_sem; +static int g_value_received; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifdef CONFIG_CAN_PASS_STRUCTS +static void sigev_thread_callback(union sigval value) +#else +static void sigev_thread_callback(FAR void *sival_ptr) +#endif +{ +#ifdef CONFIG_CAN_PASS_STRUCTS + int sival_int = value.sival_int; +#else + int sival_int = (int)((intptr_t)sival_ptr); +#endif + + printf("sigev_thread_callback: Received value %d\n" , sival_int); + + g_value_received = sival_int; + sem_post(&g_sigev_thread_sem); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void sigev_thread_test(void) +{ + struct sigevent notify; + struct itimerspec timer; + timer_t timerid; + int status; + + printf("sigev_thread_test: Initializing semaphore to 0\n" ); + sem_init(&g_sigev_thread_sem, 0, 0); + g_value_received = -1; + + /* Create the POSIX timer */ + + printf("sigev_thread_test: Creating timer\n" ); + + notify.sigev_notify = SIGEV_THREAD; + notify.sigev_signo = MY_TIMER_SIGNAL; + notify.sigev_value.sival_int = SIGVALUE_INT; + notify.sigev_notify_function = sigev_thread_callback; + notify.sigev_notify_attributes = NULL; + + status = timer_create(CLOCK_REALTIME, ¬ify, &timerid); + if (status != OK) + { + printf("sigev_thread_test: timer_create failed, errno=%d\n", errno); + goto errorout; + } + + /* Start the POSIX timer */ + + printf("sigev_thread_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("sigev_thread_test: timer_settime failed, errno=%d\n", errno); + goto errorout; + } + + /* Take the semaphore */ + + printf("sigev_thread_test: Waiting on semaphore\n" ); + + do + { + status = sem_wait(&g_sigev_thread_sem); + if (status < 0) + { + int error = errno; + if (error == EINTR) + { + printf("sigev_thread_test: sem_wait() interrupted by signal\n" ); + } + else + { + printf("sigev_thread_test: ERROR sem_wait failed, errno=%d\n", + error); + goto errorout; + } + } + } + while (status < 0); + + printf("sigev_thread_test: Awakened with no error!\n" ); + + /* Check sigval */ + + printf("sigev_thread_test: g_value_received=%d\n", g_value_received); + if (g_value_received != SIGVALUE_INT) + { + printf("sigev_thread_callback: ERROR sival_int=%d expected %d\n", + g_value_received, SIGVALUE_INT); + } + +errorout: + sem_destroy(&g_sigev_thread_sem); + + /* Then delete the timer */ + + printf("sigev_thread_test: Deleting timer\n" ); + status = timer_delete(timerid); + if (status != OK) + { + printf("sigev_thread_test: timer_create failed, errno=%d\n", errno); + } + + printf("sigev_thread_test: Done\n" ); +} diff --git a/examples/ostest/timedmqueue.c b/examples/ostest/timedmqueue.c index f67ee7ea3..b1bc4b2d2 100644 --- a/examples/ostest/timedmqueue.c +++ b/examples/ostest/timedmqueue.c @@ -190,7 +190,7 @@ static void *sender_thread(void *arg) printf("sender_thread: returning nerrors=%d\n", nerrors); FFLUSH(); - return (pthread_addr_t)nerrors; + return (pthread_addr_t)((uintptr_t)nerrors); } static void *receiver_thread(void *arg) @@ -310,8 +310,8 @@ static void *receiver_thread(void *arg) printf("receiver_thread: returning nerrors=%d\n", nerrors); FFLUSH(); - pthread_exit((pthread_addr_t)nerrors); - return (pthread_addr_t)nerrors; + pthread_exit((pthread_addr_t)((uintptr_t)nerrors)); + return (pthread_addr_t)((uintptr_t)nerrors); } void timedmqueue_test(void) @@ -328,19 +328,22 @@ void timedmqueue_test(void) status = pthread_attr_init(&attr); if (status != 0) { - printf("timedmqueue_test: pthread_attr_init failed, status=%d\n", status); + 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); + 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); + printf("timedmqueue_test: pthread_create failed, status=%d\n", + status); } /* Wait for the sending thread to complete */ @@ -349,7 +352,8 @@ void timedmqueue_test(void) pthread_join(sender, &result); if (result != (void*)0) { - printf("timedmqueue_test: ERROR sender thread exited with %d errors\n", (int)result); + printf("timedmqueue_test: ERROR sender thread exited with %d errors\n", + (int)((intptr_t)result)); } /* Start the receiving thread at the default priority */ @@ -358,19 +362,22 @@ void timedmqueue_test(void) status = pthread_attr_init(&attr); if (status != 0) { - printf("timedmqueue_test: pthread_attr_init failed, status=%d\n", status); + 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); + 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); + printf("timedmqueue_test: pthread_create failed, status=%d\n", + status); } /* Wait for the receiving thread to complete */ @@ -380,7 +387,7 @@ void timedmqueue_test(void) if (result != (void*)0) { printf("timedmqueue_test: ERROR receiver thread exited with %d errors\n", - (int)result); + (int)((intptr_t)result)); } /* Make sure that the message queues were properly closed (otherwise, we