blob: 0de209d2d258b2173b699fde472b4d3d08fbd8bb [file] [log] [blame]
/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <ztest.h>
#include <pthread.h>
#define N_THR 3
#define STACKSZ 1024
#define ONE_SECOND 1
#define THREAD_PRIORITY 2
K_THREAD_STACK_ARRAY_DEFINE(stacks, N_THR, STACKSZ);
int exit_count;
void *thread_top(void *p1)
{
pthread_t pthread;
u32_t policy, seconds;
struct sched_param param;
pthread = (pthread_t) pthread_self();
pthread_getschedparam(pthread, &policy, &param);
printk("Thread %d scheduling policy = %d & priority %d started\n",
(s32_t) p1, policy, param.priority);
seconds = (s32_t)p1;
sleep(seconds * ONE_SECOND);
exit_count++;
printk("Exiting thread %d\n", (s32_t)p1);
pthread_exit(p1);
return NULL;
}
static bool is_sched_prio_valid(int prio, int policy)
{
if (prio < sched_get_priority_min(policy) ||
prio > sched_get_priority_max(policy)) {
return false;
}
return true;
}
void test_pthread_join(void)
{
s32_t i, ret;
pthread_attr_t attr[N_THR];
struct sched_param schedparam;
pthread_t newthread[N_THR];
u32_t detachstate, schedpolicy = SCHED_RR;
void *retval;
size_t stack_size;
printk("POSIX pthread join API\n");
/* Creating threads with lowest application priority */
for (i = 0; i < N_THR; i++) {
ret = pthread_attr_init(&attr[i]);
if (ret != 0) {
zassert_false(pthread_attr_destroy(&attr[i]),
"Unable to destroy pthread object attrib\n");
zassert_false(pthread_attr_init(&attr[i]),
"Unable to create pthread object attrib\n");
}
/* Setting pthread as JOINABLE */
pthread_attr_getdetachstate(&attr[i], &detachstate);
if (detachstate != PTHREAD_CREATE_JOINABLE) {
pthread_attr_setdetachstate(&attr[i],
PTHREAD_CREATE_JOINABLE);
}
/* Setting premptive scheduling policy */
pthread_attr_getschedpolicy(&attr[i], &schedpolicy);
if (schedpolicy != SCHED_RR) {
schedpolicy = SCHED_RR;
pthread_attr_setschedpolicy(&attr[i], schedpolicy);
}
/* Setting scheduling priority */
pthread_attr_getschedparam(&attr[i], &schedparam);
if (schedparam.priority != THREAD_PRIORITY) {
schedparam.priority = THREAD_PRIORITY;
ret = is_sched_prio_valid(schedparam.priority,
schedpolicy);
/*TESTPOINT: Check if priority is valid*/
zassert_true(ret, "Scheduling priority invalid\n");
pthread_attr_setschedparam(&attr[i], &schedparam);
}
/* Setting stack */
pthread_attr_getstacksize(&attr[i], &stack_size);
if (stack_size != STACKSZ) {
stack_size = STACKSZ;
pthread_attr_setstack(&attr[i], &stacks[i][0],
stack_size);
}
ret = pthread_create(&newthread[i], &attr[i], thread_top,
(void *)i);
/*TESTPOINT: Check if thread created successfully*/
zassert_false(ret, "Number of threads exceed max limit\n");
pthread_attr_destroy(&attr[i]);
}
for (i = 0; i < N_THR; i++) {
printk("Waiting for pthread %d to join\n", i);
pthread_join(newthread[i], &retval);
printk("Pthread %d joined to %s\n", i, __func__);
}
/* Test PASS if all threads have exited before main exit */
zassert_equal(exit_count, N_THR, "pthread join test failed\n");
}
void test_main(void)
{
ztest_test_suite(test_pthreads_join,
ztest_unit_test(test_pthread_join));
ztest_run_test_suite(test_pthreads_join);
}