@@ -598,3 +598,132 @@ ZTEST(posix_apis, test_pthread_descriptor_leak)
598
598
zassert_ok (pthread_join (pthread1 , & unused ), "unable to join thread %zu" , i );
599
599
}
600
600
}
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