@@ -577,3 +577,132 @@ void test_pthread_descriptor_leak(void)
577
577
zassert_ok (pthread_join (pthread1 , & unused ), "unable to join thread %zu" , i );
578
578
}
579
579
}
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