mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-05-13 04:54:44 +08:00
314 lines
6.7 KiB
C
314 lines
6.7 KiB
C
/**
|
|
* @file
|
|
*
|
|
* @brief The creation and execution of threads (RTEMS task, kproc, kthread) are tested.
|
|
*
|
|
* The main thread creates a worker and the waits until receives an event of the
|
|
* created worker.
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 2013, 2018 embedded brains GmbH. All rights reserved.
|
|
*
|
|
* embedded brains GmbH
|
|
* Dornierstr. 4
|
|
* 82178 Puchheim
|
|
* Germany
|
|
* <rtems@embedded-brains.de>
|
|
*
|
|
* 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.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <machine/rtems-bsd-kernel-space.h>
|
|
#include <machine/rtems-bsd-thread.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/param.h>
|
|
#include <sys/proc.h>
|
|
#include <sys/kthread.h>
|
|
#include <sys/errno.h>
|
|
|
|
#include <vm/uma.h>
|
|
|
|
#include <rtems/bsd/bsd.h>
|
|
|
|
#include <rtems.h>
|
|
#include <rtems/libcsupport.h>
|
|
#include <rtems/score/threaddispatch.h>
|
|
#include <rtems/score/wkspace.h>
|
|
|
|
#define TEST_NAME "LIBBSD THREAD 1"
|
|
|
|
#define TEST_KTHREAD_ADD ((void *) 0xdeadbeef)
|
|
|
|
static rtems_id main_task_id;
|
|
|
|
static char test_kproc_name[] = "kproc";
|
|
|
|
static struct kproc_desc test_kproc_start_desc;
|
|
|
|
static char test_kthread_name[] = "kthread";
|
|
|
|
static struct kthread_desc test_kthread_start_desc;
|
|
|
|
static void
|
|
test_curthread(const char *name)
|
|
{
|
|
struct thread *td_0 = rtems_bsd_get_curthread_or_null();
|
|
struct thread *td_1 = rtems_bsd_get_curthread_or_wait_forever();
|
|
struct thread *td_2 = curthread;
|
|
|
|
assert(td_0 != NULL);
|
|
assert(td_0 == td_1);
|
|
assert(td_0 == td_2);
|
|
assert(strcmp(td_0->td_thread->Join_queue.Queue.name, name) == 0);
|
|
}
|
|
|
|
static void
|
|
wake_up_main_thread(void)
|
|
{
|
|
rtems_status_code sc;
|
|
|
|
sc = rtems_event_transient_send(main_task_id);
|
|
assert(sc == RTEMS_SUCCESSFUL);
|
|
}
|
|
|
|
static void
|
|
wait_for_worker_thread(void)
|
|
{
|
|
rtems_status_code sc;
|
|
|
|
sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
|
|
assert(sc == RTEMS_SUCCESSFUL);
|
|
}
|
|
|
|
static void
|
|
non_bsd_thread(rtems_task_argument arg)
|
|
{
|
|
|
|
test_curthread("");
|
|
wake_up_main_thread();
|
|
rtems_task_exit();
|
|
}
|
|
|
|
static void
|
|
test_non_bsd_thread(void)
|
|
{
|
|
rtems_status_code sc;
|
|
rtems_id task_id;
|
|
rtems_resource_snapshot snapshot;
|
|
|
|
rtems_resource_snapshot_take(&snapshot);
|
|
|
|
sc = rtems_task_create(
|
|
rtems_build_name('T', 'A', 'S', 'K'),
|
|
RTEMS_MINIMUM_PRIORITY,
|
|
RTEMS_MINIMUM_STACK_SIZE,
|
|
RTEMS_DEFAULT_MODES,
|
|
RTEMS_FLOATING_POINT,
|
|
&task_id
|
|
);
|
|
assert(sc == RTEMS_SUCCESSFUL);
|
|
|
|
sc = rtems_task_start(task_id, non_bsd_thread, 0);
|
|
assert(sc == RTEMS_SUCCESSFUL);
|
|
|
|
wait_for_worker_thread();
|
|
|
|
assert(rtems_resource_snapshot_check(&snapshot));
|
|
}
|
|
|
|
static void
|
|
test_kproc_start_proc(void)
|
|
{
|
|
test_curthread(&test_kproc_name[0]);
|
|
wake_up_main_thread();
|
|
kproc_exit(0);
|
|
}
|
|
|
|
static void
|
|
test_kproc_start(void)
|
|
{
|
|
rtems_resource_snapshot snapshot;
|
|
struct proc *pr = NULL;
|
|
struct kproc_desc *kpd = &test_kproc_start_desc;
|
|
|
|
puts("test kproc_start()");
|
|
|
|
rtems_resource_snapshot_take(&snapshot);
|
|
|
|
kpd->arg0 = &test_kproc_name[0];
|
|
kpd->func = test_kproc_start_proc,
|
|
kpd->global_procpp = ≺
|
|
|
|
kproc_start(kpd);
|
|
wait_for_worker_thread();
|
|
|
|
assert(pr != NULL);
|
|
|
|
assert(rtems_resource_snapshot_check(&snapshot));
|
|
}
|
|
|
|
static void
|
|
test_kthread_start_thread(void)
|
|
{
|
|
test_curthread(&test_kthread_name[0]);
|
|
wake_up_main_thread();
|
|
kthread_exit();
|
|
}
|
|
|
|
static void
|
|
test_kthread_start(void)
|
|
{
|
|
rtems_resource_snapshot snapshot;
|
|
struct thread *td = NULL;
|
|
struct kthread_desc *ktd = &test_kthread_start_desc;
|
|
|
|
puts("test kthread_start()");
|
|
|
|
rtems_resource_snapshot_take(&snapshot);
|
|
|
|
ktd->arg0 = &test_kthread_name[0];
|
|
ktd->func = test_kthread_start_thread,
|
|
ktd->global_threadpp = &td;
|
|
|
|
kthread_start(ktd);
|
|
wait_for_worker_thread();
|
|
|
|
assert(td != NULL);
|
|
|
|
assert(rtems_resource_snapshot_check(&snapshot));
|
|
}
|
|
|
|
static void
|
|
test_kthread_add_thread(void *arg)
|
|
{
|
|
test_curthread(&test_kthread_name[0]);
|
|
|
|
assert(arg == TEST_KTHREAD_ADD);
|
|
|
|
wake_up_main_thread();
|
|
kthread_exit();
|
|
}
|
|
|
|
static void
|
|
test_kthread_add(void)
|
|
{
|
|
rtems_resource_snapshot snapshot;
|
|
void *greedy;
|
|
uintptr_t take_away = 2 * rtems_bsd_get_task_stack_size("");
|
|
|
|
puts("test kthread_add()");
|
|
|
|
greedy = rtems_workspace_greedy_allocate(&take_away, 1);
|
|
|
|
rtems_resource_snapshot_take(&snapshot);
|
|
|
|
assert(rtems_configuration_get_unified_work_area());
|
|
|
|
while (take_away > 0) {
|
|
void *away;
|
|
bool ok;
|
|
|
|
ok = rtems_workspace_allocate(take_away, &away);
|
|
if (ok) {
|
|
struct thread *td = NULL;
|
|
int eno;
|
|
|
|
eno = kthread_add(
|
|
test_kthread_add_thread,
|
|
TEST_KTHREAD_ADD,
|
|
NULL,
|
|
&td,
|
|
0,
|
|
0,
|
|
"%s",
|
|
&test_kthread_name[0]
|
|
);
|
|
|
|
ok = rtems_workspace_free(away);
|
|
assert(ok);
|
|
|
|
if (eno == 0) {
|
|
wait_for_worker_thread();
|
|
assert(td != NULL);
|
|
|
|
break;
|
|
} else {
|
|
assert(eno == ENOMEM);
|
|
assert(rtems_resource_snapshot_check(&snapshot));
|
|
}
|
|
}
|
|
|
|
--take_away;
|
|
}
|
|
|
|
assert(take_away > 0);
|
|
|
|
rtems_workspace_greedy_free(greedy);
|
|
}
|
|
|
|
static void
|
|
test_rtems_bsd_get_curthread_or_null(void)
|
|
{
|
|
rtems_resource_snapshot snapshot;
|
|
void *greedy;
|
|
|
|
puts("test rtems_bsd_get_curthread_or_null()");
|
|
|
|
rtems_resource_snapshot_take(&snapshot);
|
|
|
|
greedy = rtems_workspace_greedy_allocate(NULL, 0);
|
|
assert(rtems_bsd_get_curthread_or_null() == NULL);
|
|
rtems_workspace_greedy_free(greedy);
|
|
|
|
rtems_resource_snapshot_take(&snapshot);
|
|
}
|
|
|
|
static void
|
|
test_main(void)
|
|
{
|
|
|
|
main_task_id = rtems_task_self();
|
|
|
|
/*
|
|
* Stop interferences of uma_timeout() which may need some dynamic
|
|
* memory. This could disturb the no memory tests.
|
|
*/
|
|
rtems_uma_drain_timeout();
|
|
|
|
test_non_bsd_thread();
|
|
test_kproc_start();
|
|
test_kthread_start();
|
|
test_kthread_add();
|
|
test_rtems_bsd_get_curthread_or_null();
|
|
|
|
exit(0);
|
|
}
|
|
|
|
#include <rtems/bsd/test/default-init.h>
|