Skip to content

Commit ad71b78

Browse files
cfriedtjgl-meta
authored andcommitted
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]>
1 parent 2b2cbf8 commit ad71b78

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed

tests/posix/common/src/pthread.c

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

0 commit comments

Comments
 (0)