0

I’m trying to reimplement in a backward-compatible way the RobotC API from C (although some details would better fit or would be easier with C++), and trying to reimplement their multithreading API in some portable way, so I try to use sched_get_priority_max(2) and sched_get_priority_min(2). But on one hand nice(1) and sched(7) say priority is between -20 (highest priority) and 19 (lower priority), on another hand, the former man pages stated that:

[…] numerically higher priority values are scheduled before processes with numerically lower priority values. Thus, the value returned by sched_get_priority_max() will be greater than the value returned by sched_get_priority_min()

which would mean the opposite: positive value being of higher priority and negative of lower priority (it also gives the example of real-time policies where priority is between 1 and 99).

What is going to be returned by sched_get_priority_max and _min? what should I use with pthread_attr_setschedparam(3)?

I have three values defining my custom priority range: the low priority (kLowPriority, set to 0), the high one (kHighPriority, set to 255) and the default one (kDefaultPriority, set to 7). Ideally I suppose the default being 0 for the scheduling policies having a default, kDefaultPriority/7 should become 0, kHighPriority/255 the highest priority (19? 99? whatever sched_get_priority_max(3) returns) or maybe the highest priority that can be assigned if unpriviledged? and then kLowPriority either 0 ± kDefaultPriority, either the lowest priority …what would be the more reasonable?

Currently I think I do it this way:

pthread_attr_t attr;
pthread_t thread;
struct sched_param param;
const int policy = sched_getscheduler(0),
  sched_high_prio = sched_get_priority_max(policy), // 19,
  sched_low_prio = sched_get_priority_min(policy), // -20,
  sched_range_prio = sched_high_prio - sched_low_prio;
pthread_attr_init (&attr);
pthread_attr_getinheritsched(&attr, PTHREAD_INHERIT_SCHED);
pthread_attr_getschedparam (&attr, &param);
param.sched_priority = -(((nTaskPriority
                           - kLowPriority) * sched_range_prio
                          / kHighPriority) + sched_low_prio
                         - kDefaultTaskPriority);

PS: I’m not sure if the best place to ask this question about POSIX API is here or stackoverflow, so I’m doing both, please delete my post or ask me to delete if you think it’s at the wrong place. EDIT: SO post deleted.

  • Please delete your SO post, otherwise this one is likely to be closed as cross-posted. – Stephen Kitt Mar 25 '18 at 13:26
  • @StephenKitt: done, it anyway was receiving less activity than this one while being older, so I guess it’s a better place here. – galex-713 Mar 26 '18 at 9:59
0

I take it you’re looking for a portable answer, but a good start to understand this is to look at the behaviour on Linux, as documented in the manpage for sched(7), in the “Scheduling policies” section:

The scheduler is the kernel component that decides which runnable thread will be executed by the CPU next. Each thread has an associated scheduling policy and a static scheduling priority, sched_priority. The scheduler makes its decisions based on knowledge of the scheduling policy and static priority of all threads on the system.

For threads scheduled under one of the normal scheduling policies (SCHED_OTHER, SCHED_IDLE, SCHED_BATCH), sched_priority is not used in scheduling decisions (it must be specified as 0).

Processes scheduled under one of the real-time policies (SCHED_FIFO, SCHED_RR) have a sched_priority value in the range 1 (low) to 99 (high). (As the numbers imply, real-time threads always have higher priority than normal threads.) Note well: POSIX.1 requires an implementation to support only a minimum 32 distinct priority levels for the real-time policies, and some systems supply just this minimum. Portable programs should use sched_get_priority_min(2) and sched_get_priority_max(2) to find the range of priorities supported for a particular policy.

See also the POSIX documentation for pthread_setschedparam, which only requires three policies (SCHED_OTHER, SCHED_FIFO and SCHED_RR), and states that behaviour under the first is implementation-defined.

So if you want to schedule threads using a priority, portably, you need to use the appropriate policy first (FIFO or round-robin). Then you determine the range of values, and set the priority as appropriate. Threads and processes are scheduled by decreasing priority: threads with a higher priority will run first.

On Linux, the default behaviour (implementation-defined as per POSIX) uses a dynamic priority which is calculated based on the nice value, and how often a given thread is not scheduled. On Linux, the nice value determines priority lowest-first, so -20 is the highest priority, 19 the lowest. POSIX describes nice as a per-process value, but on Linux it’s per-thread, so you can use to schedule threads there (but that’s not portable).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.