tests: posix: common: separate xsi_threads_ext into standalone test

posix.common contains testsuites that can be separated into smaller
groups of tests. This change moves tests in the xsi_threads_ext
option group into a singular testsuite tests/posix/xsi_threads_ext
app directory.

Signed-off-by: Marvin Ouma <pancakesdeath@protonmail.com>
This commit is contained in:
Marvin Ouma 2024-11-25 13:07:54 +03:00 committed by Benjamin Cabé
commit d27e4dc463
6 changed files with 331 additions and 182 deletions

View file

@ -517,29 +517,6 @@ ZTEST(pthread, test_pthread_equal)
zassert_false(pthread_equal(pthread_self(), (pthread_t)4242));
}
ZTEST(pthread, test_pthread_set_get_concurrency)
{
/* EINVAL if the value specified by new_level is negative */
zassert_equal(EINVAL, pthread_setconcurrency(-42));
/*
* Note: the special value 0 indicates the implementation will
* maintain the concurrency level at its own discretion.
*
* pthread_getconcurrency() should return a value of 0 on init.
*/
zassert_equal(0, pthread_getconcurrency());
for (int i = 0; i <= CONFIG_MP_MAX_NUM_CPUS; ++i) {
zassert_ok(pthread_setconcurrency(i));
/* verify parameter is saved */
zassert_equal(i, pthread_getconcurrency());
}
/* EAGAIN if the a system resource to be exceeded */
zassert_equal(EAGAIN, pthread_setconcurrency(CONFIG_MP_MAX_NUM_CPUS + 1));
}
static void cleanup_handler(void *arg)
{
bool *boolp = (bool *)arg;

View file

@ -237,165 +237,6 @@ ZTEST(pthread_attr, test_pthread_attr_setschedpolicy)
can_create_thread(&attr);
}
ZTEST(pthread_attr, test_pthread_attr_getstack)
{
void *stackaddr = (void *)BIOS_FOOD;
size_t stacksize = BIOS_FOOD;
/* degenerate cases */
{
if (false) {
/* undefined behaviour */
zassert_equal(pthread_attr_getstack(NULL, NULL, NULL), EINVAL);
zassert_equal(pthread_attr_getstack(NULL, NULL, &stacksize), EINVAL);
zassert_equal(pthread_attr_getstack(NULL, &stackaddr, NULL), EINVAL);
zassert_equal(pthread_attr_getstack(NULL, &stackaddr, &stacksize), EINVAL);
zassert_equal(pthread_attr_getstack(&uninit_attr, &stackaddr, &stacksize),
EINVAL);
}
zassert_equal(pthread_attr_getstack(&attr, NULL, NULL), EINVAL);
zassert_equal(pthread_attr_getstack(&attr, NULL, &stacksize), EINVAL);
zassert_equal(pthread_attr_getstack(&attr, &stackaddr, NULL), EINVAL);
}
zassert_ok(pthread_attr_getstack(&attr, &stackaddr, &stacksize));
zassert_not_equal(stackaddr, (void *)BIOS_FOOD);
zassert_not_equal(stacksize, BIOS_FOOD);
}
ZTEST(pthread_attr, test_pthread_attr_setstack)
{
void *stackaddr;
size_t stacksize;
void *new_stackaddr;
size_t new_stacksize;
/* valid values */
zassert_ok(pthread_attr_getstack(&attr, &stackaddr, &stacksize));
/* degenerate cases */
{
if (false) {
/* undefined behaviour */
zassert_equal(pthread_attr_setstack(NULL, NULL, 0), EACCES);
zassert_equal(pthread_attr_setstack(NULL, NULL, stacksize), EINVAL);
zassert_equal(pthread_attr_setstack(NULL, stackaddr, 0), EINVAL);
zassert_equal(pthread_attr_setstack(NULL, stackaddr, stacksize), EINVAL);
zassert_equal(pthread_attr_setstack((pthread_attr_t *)&uninit_attr,
stackaddr, stacksize),
EINVAL);
}
zassert_equal(pthread_attr_setstack(&attr, NULL, 0), EACCES);
zassert_equal(pthread_attr_setstack(&attr, NULL, stacksize), EACCES);
zassert_equal(pthread_attr_setstack(&attr, stackaddr, 0), EINVAL);
}
/* ensure we can create and join a thread with the default attrs */
can_create_thread(&attr);
/* set stack / addr to the current values of stack / addr */
zassert_ok(pthread_attr_setstack(&attr, stackaddr, stacksize));
can_create_thread(&attr);
/* qemu_x86 seems to be unable to set thread stacks to be anything less than 4096 */
if (!IS_ENABLED(CONFIG_X86)) {
/*
* check we can set a smaller stacksize
* should not require dynamic reallocation
* size may get rounded up to some alignment internally
*/
zassert_ok(pthread_attr_setstack(&attr, stackaddr, stacksize - 1));
/* ensure we read back the same values as we specified */
zassert_ok(pthread_attr_getstack(&attr, &new_stackaddr, &new_stacksize));
zassert_equal(new_stackaddr, stackaddr);
zassert_equal(new_stacksize, stacksize - 1);
can_create_thread(&attr);
}
if (IS_ENABLED(DYNAMIC_THREAD_ALLOC)) {
/* ensure we can set a dynamic stack */
k_thread_stack_t *stack;
stack = k_thread_stack_alloc(2 * stacksize, 0);
zassert_not_null(stack);
zassert_ok(pthread_attr_setstack(&attr, (void *)stack, 2 * stacksize));
/* ensure we read back the same values as we specified */
zassert_ok(pthread_attr_getstack(&attr, &new_stackaddr, &new_stacksize));
zassert_equal(new_stackaddr, (void *)stack);
zassert_equal(new_stacksize, 2 * stacksize);
can_create_thread(&attr);
}
}
ZTEST(pthread_attr, test_pthread_attr_getstacksize)
{
size_t stacksize = BIOS_FOOD;
/* degenerate cases */
{
if (false) {
/* undefined behaviour */
zassert_equal(pthread_attr_getstacksize(NULL, NULL), EINVAL);
zassert_equal(pthread_attr_getstacksize(NULL, &stacksize), EINVAL);
zassert_equal(pthread_attr_getstacksize(&uninit_attr, &stacksize), EINVAL);
}
zassert_equal(pthread_attr_getstacksize(&attr, NULL), EINVAL);
}
zassert_ok(pthread_attr_getstacksize(&attr, &stacksize));
zassert_not_equal(stacksize, BIOS_FOOD);
}
ZTEST(pthread_attr, test_pthread_attr_setstacksize)
{
size_t stacksize;
size_t new_stacksize;
/* valid size */
zassert_ok(pthread_attr_getstacksize(&attr, &stacksize));
/* degenerate cases */
{
if (false) {
/* undefined behaviour */
zassert_equal(pthread_attr_setstacksize(NULL, 0), EINVAL);
zassert_equal(pthread_attr_setstacksize(NULL, stacksize), EINVAL);
zassert_equal(pthread_attr_setstacksize((pthread_attr_t *)&uninit_attr,
stacksize),
EINVAL);
}
zassert_equal(pthread_attr_setstacksize(&attr, 0), EINVAL);
}
/* ensure we can spin up a thread with the default stack size */
can_create_thread(&attr);
/* set stack / addr to the current values of stack / addr */
zassert_ok(pthread_attr_setstacksize(&attr, stacksize));
/* ensure we can read back the values we just set */
zassert_ok(pthread_attr_getstacksize(&attr, &new_stacksize));
zassert_equal(new_stacksize, stacksize);
can_create_thread(&attr);
/* qemu_x86 seems to be unable to set thread stacks to be anything less than 4096 */
if (!IS_ENABLED(CONFIG_X86)) {
zassert_ok(pthread_attr_setstacksize(&attr, stacksize - 1));
/* ensure we can read back the values we just set */
zassert_ok(pthread_attr_getstacksize(&attr, &new_stacksize));
zassert_equal(new_stacksize, stacksize - 1);
can_create_thread(&attr);
}
if (IS_ENABLED(CONFIG_DYNAMIC_THREAD_ALLOC)) {
zassert_ok(pthread_attr_setstacksize(&attr, 2 * stacksize));
/* ensure we read back the same values as we specified */
zassert_ok(pthread_attr_getstacksize(&attr, &new_stacksize));
zassert_equal(new_stacksize, 2 * stacksize);
can_create_thread(&attr);
}
}
ZTEST(pthread_attr, test_pthread_attr_getscope)
{
int contentionscope = BIOS_FOOD;

View file

@ -0,0 +1,9 @@
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(xsi_threads_ext)
target_sources(app PRIVATE src/main.c)
target_compile_options(app PRIVATE -U_POSIX_C_SOURCE -D_POSIX_C_SOURCE=200809L)

View file

@ -0,0 +1,7 @@
CONFIG_POSIX_API=y
CONFIG_ZTEST=y
CONFIG_XSI_THREADS_EXT=y
CONFIG_DYNAMIC_THREAD_ALLOC=y
CONFIG_TEST_EXTRA_STACK_SIZE=4096

View file

@ -0,0 +1,287 @@
/*
* Copyright (c) 2024, Meta
* Copyright (c) 2024, Marvin Ouma <pancakesdeath@protonmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <pthread.h>
#include <zephyr/sys/util.h>
#include <zephyr/ztest.h>
#define BIOS_FOOD 0xB105F00D
static bool attr_valid;
static pthread_attr_t attr;
static const pthread_attr_t uninit_attr;
static bool detached_thread_has_finished;
/*
* This should be discarded by the linker, in this specific testsuite, if
* CONFIG_DYNAMIC_THREAD_ALLOC is not set
*/
#define STATIC_THREAD_STACK_SIZE (MAX(1024, PTHREAD_STACK_MIN + CONFIG_TEST_EXTRA_STACK_SIZE))
static K_THREAD_STACK_DEFINE(static_thread_stack, STATIC_THREAD_STACK_SIZE);
static void *thread_entry(void *arg)
{
bool joinable = (bool)POINTER_TO_UINT(arg);
if (!joinable) {
detached_thread_has_finished = true;
}
return NULL;
}
static void create_thread_common_entry(const pthread_attr_t *attrp, bool expect_success,
bool joinable, void *(*entry)(void *arg), void *arg)
{
pthread_t th;
if (!joinable) {
detached_thread_has_finished = false;
}
if (expect_success) {
zassert_ok(pthread_create(&th, attrp, entry, arg));
} else {
zassert_not_ok(pthread_create(&th, attrp, entry, arg));
return;
}
if (joinable) {
zassert_ok(pthread_join(th, NULL), "failed to join joinable thread");
return;
}
/* should not be able to join detached thread */
zassert_not_ok(pthread_join(th, NULL));
for (size_t i = 0; i < 10; ++i) {
k_msleep(2 * CONFIG_PTHREAD_RECYCLER_DELAY_MS);
if (detached_thread_has_finished) {
break;
}
}
zassert_true(detached_thread_has_finished, "detached thread did not seem to finish");
}
static void create_thread_common(const pthread_attr_t *attrp, bool expect_success, bool joinable)
{
create_thread_common_entry(attrp, expect_success, joinable, thread_entry,
UINT_TO_POINTER(joinable));
}
static inline void can_create_thread(const pthread_attr_t *attrp)
{
create_thread_common(attrp, true, true);
}
ZTEST(xsi_threads_ext, test_pthread_attr_getstack)
{
void *stackaddr = (void *)BIOS_FOOD;
size_t stacksize = BIOS_FOOD;
/* degenerate cases */
{
if (false) {
/* undefined behaviour */
zassert_equal(pthread_attr_getstack(NULL, NULL, NULL), EINVAL);
zassert_equal(pthread_attr_getstack(NULL, NULL, &stacksize), EINVAL);
zassert_equal(pthread_attr_getstack(NULL, &stackaddr, NULL), EINVAL);
zassert_equal(pthread_attr_getstack(NULL, &stackaddr, &stacksize), EINVAL);
zassert_equal(pthread_attr_getstack(&uninit_attr, &stackaddr, &stacksize),
EINVAL);
}
zassert_equal(pthread_attr_getstack(&attr, NULL, NULL), EINVAL);
zassert_equal(pthread_attr_getstack(&attr, NULL, &stacksize), EINVAL);
zassert_equal(pthread_attr_getstack(&attr, &stackaddr, NULL), EINVAL);
}
zassert_ok(pthread_attr_getstack(&attr, &stackaddr, &stacksize));
zassert_not_equal(stackaddr, (void *)BIOS_FOOD);
zassert_not_equal(stacksize, BIOS_FOOD);
}
ZTEST(xsi_threads_ext, test_pthread_attr_setstack)
{
void *stackaddr;
size_t stacksize;
void *new_stackaddr;
size_t new_stacksize;
/* valid values */
zassert_ok(pthread_attr_getstack(&attr, &stackaddr, &stacksize));
/* degenerate cases */
{
if (false) {
/* undefined behaviour */
zassert_equal(pthread_attr_setstack(NULL, NULL, 0), EACCES);
zassert_equal(pthread_attr_setstack(NULL, NULL, stacksize), EINVAL);
zassert_equal(pthread_attr_setstack(NULL, stackaddr, 0), EINVAL);
zassert_equal(pthread_attr_setstack(NULL, stackaddr, stacksize), EINVAL);
zassert_equal(pthread_attr_setstack((pthread_attr_t *)&uninit_attr,
stackaddr, stacksize),
EINVAL);
}
zassert_equal(pthread_attr_setstack(&attr, NULL, 0), EACCES);
zassert_equal(pthread_attr_setstack(&attr, NULL, stacksize), EACCES);
zassert_equal(pthread_attr_setstack(&attr, stackaddr, 0), EINVAL);
}
/* ensure we can create and join a thread with the default attrs */
can_create_thread(&attr);
/* set stack / addr to the current values of stack / addr */
zassert_ok(pthread_attr_setstack(&attr, stackaddr, stacksize));
can_create_thread(&attr);
/* qemu_x86 seems to be unable to set thread stacks to be anything less than 4096 */
if (!IS_ENABLED(CONFIG_X86)) {
/*
* check we can set a smaller stacksize
* should not require dynamic reallocation
* size may get rounded up to some alignment internally
*/
zassert_ok(pthread_attr_setstack(&attr, stackaddr, stacksize - 1));
/* ensure we read back the same values as we specified */
zassert_ok(pthread_attr_getstack(&attr, &new_stackaddr, &new_stacksize));
zassert_equal(new_stackaddr, stackaddr);
zassert_equal(new_stacksize, stacksize - 1);
can_create_thread(&attr);
}
if (IS_ENABLED(CONFIG_DYNAMIC_THREAD_ALLOC)) {
/* ensure we can set a dynamic stack */
k_thread_stack_t *stack;
stack = k_thread_stack_alloc(2 * stacksize, 0);
zassert_not_null(stack);
zassert_ok(pthread_attr_setstack(&attr, (void *)stack, 2 * stacksize));
/* ensure we read back the same values as we specified */
zassert_ok(pthread_attr_getstack(&attr, &new_stackaddr, &new_stacksize));
zassert_equal(new_stackaddr, (void *)stack);
zassert_equal(new_stacksize, 2 * stacksize);
can_create_thread(&attr);
}
}
ZTEST(xsi_threads_ext, test_pthread_set_get_concurrency)
{
/* EINVAL if the value specified by new_level is negative */
zassert_equal(EINVAL, pthread_setconcurrency(-42));
/*
* Note: the special value 0 indicates the implementation will
* maintain the concurrency level at its own discretion.
*
* pthread_getconcurrency() should return a value of 0 on init.
*/
zassert_equal(0, pthread_getconcurrency());
for (int i = 0; i <= CONFIG_MP_MAX_NUM_CPUS; ++i) {
zassert_ok(pthread_setconcurrency(i));
/* verify parameter is saved */
zassert_equal(i, pthread_getconcurrency());
}
/* EAGAIN if the a system resource to be exceeded */
zassert_equal(EAGAIN, pthread_setconcurrency(CONFIG_MP_MAX_NUM_CPUS + 1));
}
ZTEST(xsi_threads_ext, test_pthread_attr_getstacksize)
{
size_t stacksize = BIOS_FOOD;
/* degenerate cases */
{
if (false) {
/* undefined behaviour */
zassert_equal(pthread_attr_getstacksize(NULL, NULL), EINVAL);
zassert_equal(pthread_attr_getstacksize(NULL, &stacksize), EINVAL);
zassert_equal(pthread_attr_getstacksize(&uninit_attr, &stacksize), EINVAL);
}
zassert_equal(pthread_attr_getstacksize(&attr, NULL), EINVAL);
}
zassert_ok(pthread_attr_getstacksize(&attr, &stacksize));
zassert_not_equal(stacksize, BIOS_FOOD);
}
ZTEST(xsi_threads_ext, test_pthread_attr_setstacksize)
{
size_t stacksize;
size_t new_stacksize;
/* valid size */
zassert_ok(pthread_attr_getstacksize(&attr, &stacksize));
/* degenerate cases */
{
if (false) {
/* undefined behaviour */
zassert_equal(pthread_attr_setstacksize(NULL, 0), EINVAL);
zassert_equal(pthread_attr_setstacksize(NULL, stacksize), EINVAL);
zassert_equal(pthread_attr_setstacksize((pthread_attr_t *)&uninit_attr,
stacksize),
EINVAL);
}
zassert_equal(pthread_attr_setstacksize(&attr, 0), EINVAL);
}
/* ensure we can spin up a thread with the default stack size */
can_create_thread(&attr);
/* set stack / addr to the current values of stack / addr */
zassert_ok(pthread_attr_setstacksize(&attr, stacksize));
/* ensure we can read back the values we just set */
zassert_ok(pthread_attr_getstacksize(&attr, &new_stacksize));
zassert_equal(new_stacksize, stacksize);
can_create_thread(&attr);
/* qemu_x86 seems to be unable to set thread stacks to be anything less than 4096 */
if (!IS_ENABLED(CONFIG_X86)) {
zassert_ok(pthread_attr_setstacksize(&attr, stacksize - 1));
/* ensure we can read back the values we just set */
zassert_ok(pthread_attr_getstacksize(&attr, &new_stacksize));
zassert_equal(new_stacksize, stacksize - 1);
can_create_thread(&attr);
}
if (IS_ENABLED(CONFIG_DYNAMIC_THREAD_ALLOC)) {
zassert_ok(pthread_attr_setstacksize(&attr, 2 * stacksize));
/* ensure we read back the same values as we specified */
zassert_ok(pthread_attr_getstacksize(&attr, &new_stacksize));
zassert_equal(new_stacksize, 2 * stacksize);
can_create_thread(&attr);
}
}
static void before(void *arg)
{
ARG_UNUSED(arg);
zassert_ok(pthread_attr_init(&attr));
if (!IS_ENABLED(CONFIG_DYNAMIC_THREAD_ALLOC)) {
zassert_ok(pthread_attr_setstack(&attr, &static_thread_stack,
STATIC_THREAD_STACK_SIZE));
}
attr_valid = true;
}
static void after(void *arg)
{
ARG_UNUSED(arg);
if (attr_valid) {
(void)pthread_attr_destroy(&attr);
attr_valid = false;
}
}
ZTEST_SUITE(xsi_threads_ext, NULL, NULL, before, after, NULL);

View file

@ -0,0 +1,28 @@
common:
filter: not CONFIG_NATIVE_LIBC
tags:
- posix
- xsi_threads_ext
# 1 tier0 platform per supported architecture
platform_key:
- arch
- simulation
min_flash: 64
min_ram: 32
tests:
portability.posix.xsi_threads_ext: {}
portability.posix.xsi_threads_ext.minimal:
extra_configs:
- CONFIG_MINIMAL_LIBC=y
portability.posix.xsi_threads_ext.newlib:
filter: TOOLCHAIN_HAS_NEWLIB == 1
extra_configs:
- CONFIG_NEWLIB_LIBC=y
portability.posix.xsi_threads_ext.picolibc:
tags: picolibc
filter: CONFIG_PICOLIBC_SUPPORTED
extra_configs:
- CONFIG_PICOLIBC=y
portability.posix.xsi_threads_ext.static_stack:
extra_configs:
- CONFIG_DYNAMIC_THREAD_ALLOC=n