Skip to content

Commit 347de78

Browse files
committed
tests: posix: ensure that min and max priority are schedulable
Verify that threads are actually schedulable for min and max scheduler priority for both `SCHED_RR` (preemptive) and `SCHED_FIFO` (cooperative). Fixes #56729 Signed-off-by: Chris Friedt <[email protected]> (cherry picked from commit ad71b78)
1 parent 26ffb63 commit 347de78

File tree

2 files changed

+132
-1
lines changed

2 files changed

+132
-1
lines changed

tests/posix/common/src/main.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ extern void test_nanosleep_1_1(void);
3939
extern void test_nanosleep_1_1001(void);
4040
extern void test_sleep(void);
4141
extern void test_usleep(void);
42+
extern void test_sched_policy(void);
4243

4344
void test_main(void)
4445
{
@@ -73,7 +74,8 @@ void test_main(void)
7374
ztest_unit_test(test_nanosleep_1_1001),
7475
ztest_unit_test(test_posix_pthread_create_negative),
7576
ztest_unit_test(test_sleep),
76-
ztest_unit_test(test_usleep)
77+
ztest_unit_test(test_usleep),
78+
ztest_unit_test(test_sched_policy)
7779
);
7880
ztest_run_test_suite(posix_apis);
7981
}

tests/posix/common/src/pthread.c

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,3 +577,132 @@ void test_pthread_descriptor_leak(void)
577577
zassert_ok(pthread_join(pthread1, &unused), "unable to join thread %zu", i);
578578
}
579579
}
580+
581+
void test_sched_policy(void)
582+
{
583+
/*
584+
* TODO:
585+
* 1. assert that _POSIX_PRIORITY_SCHEDULING is defined
586+
* 2. if _POSIX_SPORADIC_SERVER or _POSIX_THREAD_SPORADIC_SERVER are defined,
587+
* also check SCHED_SPORADIC
588+
* 3. SCHED_OTHER is mandatory (but may be equivalent to SCHED_FIFO or SCHED_RR,
589+
* and is implementation defined)
590+
*/
591+
592+
int pmin;
593+
int pmax;
594+
pthread_t th;
595+
pthread_attr_t attr;
596+
struct sched_param param;
597+
static const int policies[] = {
598+
SCHED_FIFO,
599+
SCHED_RR,
600+
SCHED_INVALID,
601+
};
602+
static const char *const policy_names[] = {
603+
"SCHED_FIFO",
604+
"SCHED_RR",
605+
"SCHED_INVALID",
606+
};
607+
static const bool policy_enabled[] = {
608+
IS_ENABLED(CONFIG_COOP_ENABLED),
609+
IS_ENABLED(CONFIG_PREEMPT_ENABLED),
610+
false,
611+
};
612+
static int nprio[] = {
613+
CONFIG_NUM_COOP_PRIORITIES,
614+
CONFIG_NUM_PREEMPT_PRIORITIES,
615+
42,
616+
};
617+
const char *const prios[] = {"pmin", "pmax"};
618+
619+
BUILD_ASSERT(!(SCHED_INVALID == SCHED_FIFO || SCHED_INVALID == SCHED_RR),
620+
"SCHED_INVALID is itself invalid");
621+
622+
for (int policy = 0; policy < ARRAY_SIZE(policies); ++policy) {
623+
if (!policy_enabled[policy]) {
624+
/* test degenerate cases */
625+
errno = 0;
626+
zassert_equal(-1, sched_get_priority_min(policies[policy]),
627+
"expected sched_get_priority_min(%s) to fail",
628+
policy_names[policy]);
629+
zassert_equal(EINVAL, errno, "sched_get_priority_min(%s) did not set errno",
630+
policy_names[policy]);
631+
632+
errno = 0;
633+
zassert_equal(-1, sched_get_priority_max(policies[policy]),
634+
"expected sched_get_priority_max(%s) to fail",
635+
policy_names[policy]);
636+
zassert_equal(EINVAL, errno, "sched_get_priority_max(%s) did not set errno",
637+
policy_names[policy]);
638+
continue;
639+
}
640+
641+
/* get pmin and pmax for policies[policy] */
642+
for (int i = 0; i < 2; ++i) {
643+
errno = 0;
644+
if (i == 0) {
645+
pmin = sched_get_priority_min(policies[policy]);
646+
param.sched_priority = pmin;
647+
} else {
648+
pmax = sched_get_priority_max(policies[policy]);
649+
param.sched_priority = pmax;
650+
}
651+
652+
zassert_not_equal(-1, param.sched_priority,
653+
"sched_get_priority_%s(%s) failed: %d",
654+
i == 0 ? "min" : "max", policy_names[policy], errno);
655+
zassert_equal(0, errno, "sched_get_priority_%s(%s) set errno to %s",
656+
i == 0 ? "min" : "max", policy_names[policy], errno);
657+
}
658+
659+
/*
660+
* IEEE 1003.1-2008 Section 2.8.4
661+
* conforming implementations should provide a range of at least 32 priorities
662+
*
663+
* Note: we relax this requirement
664+
*/
665+
zassert_true(pmax > pmin, "pmax (%d) <= pmin (%d)", pmax, pmin,
666+
"%s min/max inconsistency: pmin: %d pmax: %d", policy_names[policy],
667+
pmin, pmax);
668+
669+
/*
670+
* Getting into the weeds a bit (i.e. whitebox testing), Zephyr
671+
* cooperative threads use [-CONFIG_NUM_COOP_PRIORITIES,-1] and
672+
* preemptive threads use [0, CONFIG_NUM_PREEMPT_PRIORITIES - 1],
673+
* where the more negative thread has the higher priority. Since we
674+
* cannot map those directly (a return value of -1 indicates error),
675+
* we simply map those to the positive space.
676+
*/
677+
zassert_equal(pmin, 0, "unexpected pmin for %s", policy_names[policy]);
678+
zassert_equal(pmax, nprio[policy] - 1, "unexpected pmax for %s",
679+
policy_names[policy]); /* test happy paths */
680+
681+
for (int i = 0; i < 2; ++i) {
682+
/* create threads with min and max priority levels */
683+
zassert_equal(0, pthread_attr_init(&attr),
684+
"pthread_attr_init() failed for %s (%d) of %s", prios[i],
685+
param.sched_priority, policy_names[policy]);
686+
687+
zassert_equal(0, pthread_attr_setschedpolicy(&attr, policies[policy]),
688+
"pthread_attr_setschedpolicy() failed for %s (%d) of %s",
689+
prios[i], param.sched_priority, policy_names[policy]);
690+
691+
zassert_equal(0, pthread_attr_setschedparam(&attr, &param),
692+
"pthread_attr_setschedparam() failed for %s (%d) of %s",
693+
prios[i], param.sched_priority, policy_names[policy]);
694+
695+
zassert_equal(0, pthread_attr_setstack(&attr, &stack_e[0][0], STACKS),
696+
"pthread_attr_setstack() failed for %s (%d) of %s", prios[i],
697+
param.sched_priority, policy_names[policy]);
698+
699+
zassert_equal(0, pthread_create(&th, &attr, create_thread1, NULL),
700+
"pthread_create() failed for %s (%d) of %s", prios[i],
701+
param.sched_priority, policy_names[policy]);
702+
703+
zassert_equal(0, pthread_join(th, NULL),
704+
"pthread_join() failed for %s (%d) of %s", prios[i],
705+
param.sched_priority, policy_names[policy]);
706+
}
707+
}
708+
}

0 commit comments

Comments
 (0)