ostest: Add initial support for CONFIG_BUILD_KERNEL

task_* APIs are unavailable in kernel build mode, replacing with
posix_spawn or pthread_* API to pass the case. But posix_spawn requires
some dependency, for example CONFIG_BUILTIN and CONFIG_LIBC_EXECFUNCS,
so pthread_* APIs are used in most scenarios. Some tests should be
re-visited because the intent is to user another task (in this case
another process) to e.g. receive signals.
That will require quite a bit of extra work.

Tests that had to be disabled:
- restart: task_restart() does not work at all with kernel mode so it is
  disabled entirely
- fpu: make sure the FPU test is not even attempted, because it will cause
  ASSERT() and stop the test
- vfork: vfork() does not work for some reason in CONFIG_BUILD_KERNEL,
  there is something missing on the kernel side, so just disable the test for now

Tests that should be re-visited:
- The signal tests, now they signal the process itself while before the
  signal was sent to another task. This will require building the part
  that receives the signal as a separate process
- waitpid: Like stated above, waitpid does not work for pthreads
- suspend: kill to send signal does not work for pthreads

Signed-off-by: fangxinyong <fangxinyong@xiaomi.com>
Co-authored-by: Ville Juven <ville.juven@unikie.com>
This commit is contained in:
fangxinyong 2023-11-14 18:46:17 +08:00 committed by Xiang Xiao
parent f12586c51e
commit ba075747be
8 changed files with 116 additions and 38 deletions

View File

@ -115,7 +115,9 @@ void aio_test(void);
/* restart.c ****************************************************************/
#ifndef CONFIG_BUILD_KERNEL
void restart_test(void);
#endif
/* waitpid.c ****************************************************************/

View File

@ -339,7 +339,8 @@ static int user_main(int argc, char *argv[])
check_test_memory_usage();
#endif
#if defined(CONFIG_ARCH_FPU) && !defined(CONFIG_TESTING_OSTEST_FPUTESTDISABLE)
#if defined(CONFIG_ARCH_FPU) && !defined(CONFIG_TESTING_OSTEST_FPUTESTDISABLE) && \
!defined(CONFIG_BUILD_KERNEL)
/* Check that the FPU is properly supported during context switching */
printf("\nuser_main: FPU test\n");
@ -347,13 +348,15 @@ static int user_main(int argc, char *argv[])
check_test_memory_usage();
#endif
#ifndef CONFIG_BUILD_KERNEL
/* Checkout task_restart() */
printf("\nuser_main: task_restart test\n");
restart_test();
check_test_memory_usage();
#endif
#ifdef CONFIG_SCHED_WAITPID
#if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_BUILD_KERNEL)
/* Check waitpid() and friends */
printf("\nuser_main: waitpid test\n");
@ -508,7 +511,8 @@ static int user_main(int argc, char *argv[])
signest_test();
check_test_memory_usage();
#if defined(CONFIG_SIG_SIGSTOP_ACTION) && defined(CONFIG_SIG_SIGKILL_ACTION)
#if defined(CONFIG_SIG_SIGSTOP_ACTION) && defined(CONFIG_SIG_SIGKILL_ACTION) && \
!defined(CONFIG_BUILD_KERNEL)
printf("\nuser_main: signal action test\n");
suspend_test();
check_test_memory_usage();
@ -581,8 +585,16 @@ static int user_main(int argc, char *argv[])
#endif
#if defined(CONFIG_ARCH_HAVE_FORK) && defined(CONFIG_SCHED_WAITPID)
#ifndef CONFIG_BUILD_KERNEL
printf("\nuser_main: vfork() test\n");
vfork_test();
#else
/* REVISIT: The issue with vfork() is on the kernel side, fix the issue
* and re-enable this test with CONFIG_BUILD_KERNEL
*/
printf("\nuser_main: vfork() test DISABLED (CONFIG_BUILD_KERNEL)\n");
#endif
#endif
#ifdef CONFIG_SMP_CALL
@ -635,13 +647,36 @@ static void stdio_test(void)
int main(int argc, FAR char **argv)
{
int result;
#ifdef CONFIG_TESTING_OSTEST_WAITRESULT
int ostest_result = ERROR;
#else
int ostest_result = OK;
#endif
#ifndef CONFIG_BUILD_KERNEL
int result;
#else
struct sched_param param;
posix_spawnattr_t attr;
FAR const char * const arg[7] =
{
argv[0], "user_main", arg1, arg2, arg3, arg4, NULL
};
pid_t result;
int status;
/* Use posix_spawn API to spawn the new task for tests, should re-enter
* the main entry in new task, the second arg as to identify the real
* entry point of the test tasks.
*/
if (argc >= 2 && strcmp(argv[1], "user_main") == 0)
{
return user_main(argc - 1 , &argv[1]);
}
#endif
/* Verify that stdio works first */
stdio_test();
@ -680,9 +715,19 @@ int main(int argc, FAR char **argv)
/* Verify that we can spawn a new task */
#ifdef CONFIG_BUILD_KERNEL
posix_spawnattr_init(&attr);
param.sched_priority = PRIORITY;
posix_spawnattr_setschedparam(&attr, &param);
posix_spawnattr_setstacksize(&attr, STACKSIZE);
status = posix_spawn(&result, arg[0], NULL, &attr,
(char * const *)arg, NULL);
if (status != 0)
#else
result = task_create("ostest", PRIORITY, STACKSIZE, user_main,
(FAR char * const *)g_argv);
if (result == ERROR)
#endif
{
printf("ostest_main: ERROR Failed to start user_main\n");
ASSERT(false);

View File

@ -44,7 +44,7 @@
* Private Functions
****************************************************************************/
static void *pthread_exit_thread(FAR void *parameter)
static FAR void *pthread_exit_thread(FAR void *parameter)
{
unsigned me = (unsigned)pthread_self();
@ -56,7 +56,7 @@ static void *pthread_exit_thread(FAR void *parameter)
return NULL;
}
static int pthread_exit_main(int argc, char **argv)
static FAR void *pthread_exit_main(FAR void *arg)
{
pthread_t child;
#ifdef SDCC
@ -87,7 +87,7 @@ static int pthread_exit_main(int argc, char **argv)
printf("pthread_exit_main %u: ERROR: Still running\n", me);
exit(0);
return 0;
return NULL;
}
/****************************************************************************
@ -96,20 +96,29 @@ static int pthread_exit_main(int argc, char **argv)
void pthread_exit_test(void)
{
int statloc;
struct sched_param param;
pthread_attr_t attr;
pid_t pid;
int ret;
ret = task_create("pthread_exit", PRIORITY, STACKSIZE, pthread_exit_main,
NULL);
pthread_attr_init(&attr);
param.sched_priority = PRIORITY;
pthread_attr_setschedparam(&attr, &param);
pthread_attr_setstacksize(&attr, STACKSIZE);
ret = pthread_create(&pid, &attr, pthread_exit_main, NULL);
if (ret < 0)
{
printf("pthread_exit_test: ERROR task_create Failed\n");
printf("pthread_exit_test: ERROR pthread_create Failed\n");
}
else
{
printf("pthread_exit_test: Started pthread_exit_main at PID=%d\n",
ret);
waitpid((pid_t)ret, &statloc, 0);
pid);
if (pthread_join(pid, NULL) != 0)
{
printf("pthread_exit_test: ERROR Failed to join to terminate\n");
ASSERT(false);
};
}
}

View File

@ -36,6 +36,8 @@
#include "ostest.h"
#ifndef CONFIG_BUILD_KERNEL
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@ -225,3 +227,5 @@ void restart_test(void)
printf("restart_main: Exiting\n");
}
#endif /* !CONFIG_BUILD_KERNEL */

View File

@ -128,7 +128,7 @@ static void wakeup_action(int signo, siginfo_t *info, void *ucontext)
}
}
static int waiter_main(int argc, char *argv[])
static FAR void *waiter_main(FAR void *arg)
{
sigset_t set;
struct sigaction act;
@ -218,6 +218,7 @@ void sighand_test(void)
sigset_t set;
#endif
struct sched_param param;
pthread_attr_t attr;
union sigval sigvalue;
pid_t waiterpid;
int status;
@ -265,9 +266,11 @@ void sighand_test(void)
param.sched_priority = PTHREAD_DEFAULT_PRIORITY;
}
waiterpid = task_create("waiter", param.sched_priority,
STACKSIZE, waiter_main, NULL);
if (waiterpid == ERROR)
pthread_attr_init(&attr);
pthread_attr_setschedparam(&attr, &param);
pthread_attr_setstacksize(&attr, STACKSIZE);
status = pthread_create(&waiterpid, &attr, waiter_main, NULL);
if (status != 0)
{
printf("sighand_test: ERROR failed to start waiter_main\n");
ASSERT(false);
@ -293,7 +296,7 @@ void sighand_test(void)
{
printf("sighand_test: ERROR sigqueue failed\n");
ASSERT(false);
task_delete(waiterpid);
pthread_cancel(waiterpid);
}
/* Wait a bit */

View File

@ -94,7 +94,6 @@ static void waiter_action(int signo)
sched_lock();
nest_level = g_nest_level++;
sched_unlock();
if ((signo & 1) != 0)
{
@ -114,11 +113,12 @@ static void waiter_action(int signo)
}
g_nest_level = nest_level;
sched_unlock();
sem_post(&g_sem_signal_finish);
}
static int waiter_main(int argc, char *argv[])
static FAR void *waiter_main(FAR void *arg)
{
sigset_t set;
struct sigaction act;
@ -134,7 +134,7 @@ static int waiter_main(int argc, char *argv[])
{
printf("waiter_main: ERROR sigprocmask failed: %d\n", errno);
ASSERT(false);
return EXIT_FAILURE;
return NULL;
}
printf("waiter_main: Registering signal handler\n");
@ -160,7 +160,7 @@ static int waiter_main(int argc, char *argv[])
{
printf("waiter_main: WARNING sigaction failed with %d\n",
errno);
return EXIT_FAILURE;
return NULL;
}
}
}
@ -180,10 +180,10 @@ static int waiter_main(int argc, char *argv[])
/* Just exit, the system should clean up the signal handlers */
g_waiter_running = false;
return EXIT_SUCCESS;
return NULL;
}
static int interfere_main(int argc, char *argv[])
static FAR void *interfere_main(FAR void *arg)
{
/* Now just loop staying in the way as much as possible */
@ -202,7 +202,7 @@ static int interfere_main(int argc, char *argv[])
return EXIT_SUCCESS;
}
void wait_finish(int pid, int sig)
static void wait_finish(int pid, int sig)
{
struct timespec ts;
int wait_times;
@ -239,6 +239,7 @@ void wait_finish(int pid, int sig)
void signest_test(void)
{
struct sched_param param;
pthread_attr_t attr;
pid_t waiterpid;
pid_t interferepid;
int total_signals;
@ -246,7 +247,6 @@ void signest_test(void)
int total_nested;
int even_signals;
int odd_signals;
int prio;
int ret;
int i;
int j;
@ -280,11 +280,14 @@ void signest_test(void)
/* Start waiter thread */
prio = param.sched_priority + 1;
printf("signest_test: Starting signal waiter task at priority %d\n", prio);
waiterpid = task_create("waiter", prio, STACKSIZE,
waiter_main, NULL);
if (waiterpid == ERROR)
param.sched_priority++;
printf("signest_test: Starting signal waiter task at priority %d\n",
param.sched_priority);
pthread_attr_init(&attr);
pthread_attr_setschedparam(&attr, &param);
pthread_attr_setstacksize(&attr, STACKSIZE);
ret = pthread_create(&waiterpid, &attr, waiter_main, NULL);
if (ret != 0)
{
printf("signest_test: ERROR failed to start waiter_main\n");
ASSERT(false);
@ -295,11 +298,12 @@ void signest_test(void)
/* Start interfering thread */
prio++;
printf("signest_test: Starting interfering task at priority %d\n", prio);
interferepid = task_create("interfere", prio, STACKSIZE,
interfere_main, NULL);
if (interferepid == ERROR)
param.sched_priority++;
printf("signest_test: Starting interfering task at priority %d\n",
param.sched_priority);
pthread_attr_setschedparam(&attr, &param);
ret = pthread_create(&interferepid, &attr, interfere_main, NULL);
if (ret != 0)
{
printf("signest_test: ERROR failed to start interfere_main\n");
ASSERT(false);

View File

@ -37,6 +37,12 @@
#include "ostest.h"
/* REVISIT: This could be implemented for CONFIG_BUILD_KERNEL as well, by
* starting a new process instead of using task_create()
*/
#ifndef CONFIG_BUILD_KERNEL
/****************************************************************************
* Public Functions
****************************************************************************/
@ -136,3 +142,4 @@ void suspend_test(void)
printf("suspend_test: done\n");
FFLUSH();
}
#endif /* !CONFIG_BUILD_KERNEL */

View File

@ -35,7 +35,11 @@
#include "ostest.h"
#ifdef CONFIG_SCHED_WAITPID
/* REVISIT: This could be implemented for CONFIG_BUILD_KERNEL as well, by
* starting a new process instead of using task_create()
*/
#if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_BUILD_KERNEL)
/****************************************************************************
* Pre-processor Definitions
@ -392,4 +396,4 @@ int waitpid_test(void)
return 0;
}
#endif /* CONFIG_SCHED_WAITPID */
#endif /* defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_BUILD_KERNEL) */