diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/ChangeLog.txt | 3 | ||||
-rw-r--r-- | apps/examples/ostest/Makefile | 4 | ||||
-rw-r--r-- | apps/examples/ostest/ostest.h | 42 | ||||
-rw-r--r-- | apps/examples/ostest/ostest_main.c | 8 | ||||
-rw-r--r-- | apps/examples/ostest/waitpid.c | 269 |
5 files changed, 307 insertions, 19 deletions
diff --git a/apps/ChangeLog.txt b/apps/ChangeLog.txt index 65d4d6134..70381a79d 100644 --- a/apps/ChangeLog.txt +++ b/apps/ChangeLog.txt @@ -464,4 +464,5 @@ * apps/exampes/posix_spawn: Added a test of poxis_spawn(). * apps/examples/ostest: Extend signal handler test to catch death-of-child signals (SIGCHLD). - + * apps/examples/ostest/waitpid.c: Add a test for waitpid(), waitid(), + and wait(). diff --git a/apps/examples/ostest/Makefile b/apps/examples/ostest/Makefile index b7ba9a9a8..5a8ff7293 100644 --- a/apps/examples/ostest/Makefile +++ b/apps/examples/ostest/Makefile @@ -52,6 +52,10 @@ ifeq ($(CONFIG_ARCH_FPU),y) CSRCS += fpu.c endif +ifeq ($(CONFIG_SCHED_WAITPID),y) +CSRCS += waitpid.c +endif + ifneq ($(CONFIG_DISABLE_PTHREAD),y) CSRCS += cancel.c cond.c mutex.c sem.c barrier.c ifneq ($(CONFIG_RR_INTERVAL),0) diff --git a/apps/examples/ostest/ostest.h b/apps/examples/ostest/ostest.h index bc46a3860..5217f0a0c 100644 --- a/apps/examples/ostest/ostest.h +++ b/apps/examples/ostest/ostest.h @@ -105,68 +105,74 @@ /* dev_null.c ***************************************************************/ -extern int dev_null(void); +int dev_null(void); /* fpu.c ********************************************************************/ -extern void fpu_test(void); +void fpu_test(void); + +/* waitpid.c ****************************************************************/ + +#ifdef CONFIG_SCHED_WAITPID +int waitpid_test(void); +#endif /* mutex.c ******************************************************************/ -extern void mutex_test(void); +void mutex_test(void); /* rmutex.c ******************************************************************/ -extern void recursive_mutex_test(void); +void recursive_mutex_test(void); /* sem.c ********************************************************************/ -extern void sem_test(void); +void sem_test(void); /* cond.c *******************************************************************/ -extern void cond_test(void); +void cond_test(void); /* mqueue.c *****************************************************************/ -extern void mqueue_test(void); +void mqueue_test(void); /* timedmqueue.c ************************************************************/ -extern void timedmqueue_test(void); +void timedmqueue_test(void); /* cancel.c *****************************************************************/ -extern void cancel_test(void); +void cancel_test(void); /* timedwait.c **************************************************************/ -extern void timedwait_test(void); +void timedwait_test(void); /* sighand.c ****************************************************************/ -extern void sighand_test(void); +void sighand_test(void); /* posixtimers.c ************************************************************/ -extern void timer_test(void); +void timer_test(void); /* roundrobin.c *************************************************************/ -extern void rr_test(void); +void rr_test(void); /* barrier.c ****************************************************************/ -extern void barrier_test(void); +void barrier_test(void); /* prioinherit.c ************************************************************/ -extern void priority_inheritance(void); +void priority_inheritance(void); /* vfork.c ******************************************************************/ #ifdef CONFIG_ARCH_HAVE_VFORK -extern int vfork_test(void); +int vfork_test(void); #endif /* APIs exported (conditionally) by the OS specifically for testing of @@ -174,8 +180,8 @@ extern int vfork_test(void); */ #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); +void sem_enumholders(FAR sem_t *sem); +int sem_nfreeholders(void); #else # define sem_enumholders(sem) # define sem_nfreeholders() diff --git a/apps/examples/ostest/ostest_main.c b/apps/examples/ostest/ostest_main.c index ca44353c3..aab1ff045 100644 --- a/apps/examples/ostest/ostest_main.c +++ b/apps/examples/ostest/ostest_main.c @@ -301,6 +301,14 @@ static int user_main(int argc, char *argv[]) check_test_memory_usage(); #endif +#ifdef CONFIG_SCHED_WAITPID + /* Check waitpid() and friends */ + + printf("\nuser_main: waitpid test\n"); + waitpid_test(); + check_test_memory_usage(); +#endif + #ifndef CONFIG_DISABLE_PTHREAD /* Verify pthreads and pthread mutex */ diff --git a/apps/examples/ostest/waitpid.c b/apps/examples/ostest/waitpid.c new file mode 100644 index 000000000..e53b49213 --- /dev/null +++ b/apps/examples/ostest/waitpid.c @@ -0,0 +1,269 @@ +/**************************************************************************** + * examples/ostest/waitpid.c + * + * Copyright (C) 2013 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <gnutt@nuttx.org> + * + * 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 <sys/wait.h> +#include <stdbool.h> +#include <stdio.h> +#include <signal.h> +#include <errno.h> + +#include "ostest.h" + +#ifdef CONFIG_SCHED_WAITPID + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define RETURN_STATUS 14 +#define NCHILDREN 3 +#define PRIORITY 100 + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static int g_waitpids[NCHILDREN]; + +/**************************************************************************** + * Priviate Functions + ****************************************************************************/ + +static int waitpid_main(int argc, char *argv[]) +{ + pid_t me = getpid(); + + printf("waitpid_main: PID %d Started\n", me); + sleep(3); + printf("waitpid_main: PID %d exitting with result=%d\n", me, RETURN_STATUS); + return RETURN_STATUS; +} + +static void waitpid_start_children(void) +{ + int ret; + int i; + + for (i = 0; i < NCHILDREN; i++) + { + ret = TASK_CREATE("waitpid", PRIORITY, STACKSIZE, waitpid_main, NULL); + if (ret < 0) + { + printf("waitpid_start_child: ERROR Failed to start user_main\n"); + } + else + { + printf("waitpid_start_child: Started waitpid_main at PID=%d\n", ret); + } + + g_waitpids[i] = ret; + } +} + +static void waitpid_last(void) +{ + int stat_loc; + int ret; + + printf("waitpid_last: Waiting for PID=%d with waitpid()\n", + g_waitpids[NCHILDREN-1]); + + ret = (int)waitpid(g_waitpids[NCHILDREN-1], &stat_loc, 0); + if (ret < 0) + { + int errcode = errno; + printf("waitpid_last: ERROR: PID %d waitpid failed: %d\n", + g_waitpids[NCHILDREN-1], errcode); + } + else if (stat_loc != RETURN_STATUS) + { + printf("waitpid_last: ERROR: PID %d return status is %d, expected %d\n", + g_waitpids[NCHILDREN-1], stat_loc, RETURN_STATUS); + } + else + { + printf("waitpid_last: PID %d waitpid succeeded with stat_loc=%d\n", + g_waitpids[NCHILDREN-1], stat_loc); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int waitpid_test(void) +{ +#ifdef CONFIG_SCHED_HAVE_PARENT + siginfo_t info; +#endif + int stat_loc; + int ret; + + /* Start the children and wait for first one to complete */ + + printf("\nTest waitpid()\n"); + waitpid_start_children(); + + printf("waitpid_test: Waiting for PID=%d with waitpid()\n", g_waitpids[0]); + ret = (int)waitpid(g_waitpids[0], &stat_loc, 0); + if (ret < 0) + { + int errcode = errno; + printf("waitpid_test: ERROR: PID %d waitpid failed: %d\n", + g_waitpids[0], errcode); + } + else if (ret != g_waitpids[0]) + { + printf("waitpid_test: ERROR: PID %d wait returned PID %d\n", + g_waitpids[0], ret); + } + else if (stat_loc != RETURN_STATUS) + { + printf("waitpid_test: ERROR: PID %d return status is %d, expected %d\n", + g_waitpids[0], stat_loc, RETURN_STATUS); + } + else + { + printf("waitpid_test: PID %d waitpid succeeded with stat_loc=%d\n", + g_waitpids[0], stat_loc); + } + + /* Wait a big to make sure that the other threads complete */ + + waitpid_last(); + sleep(1); + +#ifdef CONFIG_SCHED_HAVE_PARENT + /* Start the children and wait for first one to complete */ + + printf("\nTest waitid(P_PID)\n"); + waitpid_start_children(); + + printf("waitpid_test: Waiting for PID=%d with waitid()\n", g_waitpids[0]); + ret = waitid(P_PID, (id_t)g_waitpids[0], &info, WEXITED); + if (ret < 0) + { + int errcode = errno; + printf("waitpid_test: ERROR: PID %d waitid failed: %d\n", + g_waitpids[0], errcode); + } + else if (info.si_pid != g_waitpids[0]) + { + printf("waitpid_test: ERROR: PID %d waitid returned PID %d\n", + g_waitpids[0], info.si_pid); + } + else if (info.si_status != RETURN_STATUS) + { + printf("waitpid_test: ERROR: PID %d return status is %d, expected %d\n", + info.si_pid, info.si_status, RETURN_STATUS); + } + else + { + printf("waitpid_test: waitid PID %d succeeded with si_status=%d\n", + info.si_pid, info.si_status); + } + + /* Wait a big to make sure that the other threads complete */ + + waitpid_last(); + sleep(1); + + /* Start the children and wait for any one to complete */ + + printf("\nTest waitid(P_ALL)\n"); + waitpid_start_children(); + + printf("waitpid_test: Waiting for any child with waitid()\n"); + ret = waitid(P_ALL, 0, &info, WEXITED); + if (ret < 0) + { + int errcode = errno; + printf("waitpid_test: ERROR: waitid failed: %d\n", errcode); + } + else if (info.si_status != RETURN_STATUS) + { + printf("waitpid_test: ERROR: PID %d return status is %d, expected %d\n", + info.si_pid, info.si_status, RETURN_STATUS); + } + else + { + printf("waitpid_test: PID %d waitid succeeded with si_status=%d\n", + info.si_pid, info.si_status); + } + + /* Wait a big to make sure that the other threads complete */ + + waitpid_last(); + sleep(1); + + /* Start the children and wait for first one to complete */ + + printf("\nTest wait()\n"); + waitpid_start_children(); + + printf("waitpid_test: Waiting for any child with wait()\n"); + ret = (int)wait(&stat_loc); + if (ret < 0) + { + int errcode = errno; + printf("waitpid_test: ERROR: wait failed: %d\n", errcode); + } + else if (stat_loc != RETURN_STATUS) + { + printf("waitpid_test: ERROR: PID %d return status is %d, expected %d\n", + ret, stat_loc, RETURN_STATUS); + } + else + { + printf("waitpid_test: PID %d wait succeeded with stat_loc=%d\n", + ret, stat_loc); + } + + /* Wait a big to make sure that the other threads complete */ + + waitpid_last(); + sleep(1); +#endif + + return 0; +} + +#endif /* CONFIG_SCHED_WAITPID */ |