nasa / osal

The Core Flight System (cFS) Operating System Abstraction Layer (OSAL)
Apache License 2.0
545 stars 213 forks source link

way to get raw OS task priority/OSAL has too many priorities #222

Open skliper opened 4 years ago

skliper commented 4 years ago

OSAL attempts to provide a uniform set of task priority by translating the given priority to a native OS priority. This is often done by assigning bins that certain priorities can fall into. Typically, applications can set their priorities far enough apart that this is not a problem. However, sometimes tighter control would be nice especially in systems where the number of available priorities is fewer than OSAL. (For example, OSAL provides 255 priorities but POSIX only 100.)

POSIX, for example, can see priorities squashed where tasks become round-robin instead of higher priority than one another. Having to pick OSAL priorities when writing apps with many child threads based on what you know the characteristics of the underlying OS to be defeats the purpose of OSAL.

One way to fix this is to create a macro os_raw_prio(X) where the most significant bit of a priority is set, which has meaning to OSAL's thread creation mechanism. This would tell it to use the raw value instead of translating.

Another approach would be to lower the number of maximum OSAL priorities to a number lower than most RTOSs (like 50 or so) so that there can always be unique priorities in any underlying OS. Or, this could be made configurable when building the system.

skliper commented 4 years ago

Imported from trac issue 199. Created by sseeger on 2018-06-23T09:52:31, last modified: 2019-08-14T14:11:46

skliper commented 4 years ago

Trac comment by jphickey on 2019-04-12 11:47:00:

I would concur with the "OSAL has too many priorities" statement. IMO most apps should probably use less than 4-5 different priority levels. If an application is using lots of different priority levels then it is probably too complicated. In an ideal world I would suggest cutting OSAL back to ~16 priority levels.

That being said, due to existing applications I don't think we can change this easily. The assumption of 255 levels comes from the VxWorks world and OSAL simply matches that paradigm.

I would recommend this be solved by documentation. There is an easy workaround: just make sure your configuration has a spread of at least 10 OSAL priority levels between tasks for which you want to make absolutely sure are prioritized over one another.

For example, if task A at OSAL priority level 10 must always preempt task B, make sure task B is set to OSAL priority 20 or greater.

(Note that POSIX compliance only requires 32 priority levels, this is probably the worst case for an RTOS. Assume that the highest and lowest/idle level are "reserved", that leaves 30 usable levels. A spread of 10 ensures that even in this case, the tasks will be assigned different kernel priority levels).

yashi commented 4 years ago

I do also agree that too many priority is too confusing. More so with priority number conversion. Especially when the number space / range is different from OSAL to the underlying OS.

To simplify, can we avoid conversion from OSAL priority to the underlying OS priority? OSAL itself doesn't need a priority except for unit test. It'd be nice if we can abstract the numbers somehow to OS specific values. per OS defines is easy to come up with.

yashi commented 4 years ago

BTW, does 255 priorities fixed in spec? Or, is it up to an OSAL implementation to define the max?

jphickey commented 4 years ago

BTW, does 255 priorities fixed in spec? Or, is it up to an OSAL implementation to define the max?

255 priority levels is historical and comes from VxWorks. Originally on this platform the OSAL priority was the same as the underlying OS priority. The other OSAL implementations abstract the value such that the numbers work in the same manner (i.e. lower numeric value preempts higher numeric value).

The whole point of OSAL is to create an OS-independent API for application execution. Application developers assign abstract priority numbers where lower numbers represent higher execution priority. One should not have to change these numbers around when switching from one platform to another.

While I do (still) agree that 255 is too many, it is what it is - changing this has a high backward compatibility cost and not much real benefit. Just space the numbers out by at least 10.

joelsherrill commented 4 years ago

POSIX only requires 32 priority levels for a scheduler. If the application assumes more priority levels than provided by the underlying threading implementation, then there is the issue of mapping in a way that does not two OSAL priorities to the same native priority level.

RTEMS Classic API is like VxWorks low number is higher priority and you can have 255 levels. RTEMS allows you to configure a system to have a lower number of priorities which can save memory with some thread schedulers.

Interestingly, if you read it carefully enough, you will notice that POSIX never says which way priorities run (high number == high or low priority) but AFAIK all implementations follow the same pattern which is the opposite of the RTEMS Classic API and VxWorks way.

For portability, OSAL should define its own priority scheme and map that onto the target thread model in a way that doesn't result in conflicts. Probably restricts you to 32 priorities. As always, is would be up to the system integrator to ensure OS service threads play nicely with application threads.

jphickey commented 4 years ago

Right... I think we are more or less saying the same thing on this subject?

  1. OSAL needs to define its own priority numbering independent of the OS, to create a consistent environment for apps to use.
  2. OSAL has too many priority levels, which can cause confusion if the underlying RTOS actually has fewer levels.

Note that POSIX does define sched_get_priority_max and sched_get_priority_min which at least the manpage for this function does say that numerically higher values preempt numerically lower values (i.e. opposite of VxWorks). Not sure if this is actually a POSIX requirement or just the way Linux/Glibc implements it though.

Nonetheless, I think the current OSAL does item (1) above sufficiently, and item (2) above is potentially incovenient/confusing but not really major issue, and fixing it by defining a lower number of OSAL priority levels would cause significant backward compatibility headaches, for no real benefit. Just space your priority numbers out adequately, and its not a problem.

joelsherrill commented 4 years ago

Right... I think we are more or less saying the same thing on this subject?

Yep.

  1. OSAL needs to define its own priority numbering independent of the OS, to create a consistent environment for apps to use.
  2. OSAL has too many priority levels, which can cause confusion if the underlying RTOS actually has fewer levels.

Agreed. OSAL has to limit itself to the least common denominator which is likely 32.

My first reply (that I lost) had a long explanation of the priority domain problem which this is a specific example of. My dissertation dealt with this area and I got excited even being able to mention it. :)

Note that POSIX does define sched_get_priority_max and sched_get_priority_min which at least the manpage for this function does say that numerically higher values preempt numerically lower values (i.e. opposite of VxWorks). Not sure if this is actually a POSIX requirement or just the way Linux/Glibc implements it though.

This is the POSIX page:

https://pubs.opengroup.org/onlinepubs/009695399/functions/sched_get_priority_max.html

The Linux man page project (and RTEMS and NetBSD) has permission to lift text from the POSIX standard so it must be deliberate to discuss the numerical meaning of priority.

POSIX not addressing this was a surprise to me but one of the kernel guys from a major RTOS walked me and the members of the FACE Technical Standard Operating System Subcommittee through it. It does appear that Linux, *BSD, RTEMS, and all the major RTOSes treat the number the same way if that helps. But the number of priorities per scheduler varies across the major RTOSes with all meeting the 32 minimum.

Nonetheless, I think the current OSAL does item (1) above sufficiently, and item (2) above is potentially incovenient/confusing but not really major issue, and fixing it by defining a lower number of OSAL priority levels would cause significant backward compatibility headaches, for no real benefit. Just space your priority numbers out adequately, and its not a problem.

yashi commented 4 years ago

hmm. I guess I'm a minority side. Let me try to share my thoughts.

It's very confusing to have a separate priority numbers in the applications, other than underneath OS especially when a) you have to convert OSAL priority to the OS priority numbers b) two priority number systems have different size in space, ie) POSIX 32 vs OSAL 256.

OSAL needs to define its own priority numbering independent of the OS, to create a consistent environment for apps to use.

I can understand the sentence and what it claim "a consistent environment" is a good thing. But,

1) Do we really think in OSAL layer, and only in OSAL layer, when we code? Doesn't the priority leak from the underneath OS to application authors? Especially when non-OSAL threads with different priority is in the system. If it leaks, it's much worse than transparent numbering. Because we have to think both OSAL layer and the OS layer and convert them back and forth. 2) Why do OSAL need another layer for the priority numbers? I can understand and see the benefit for the common denominator functions, which allows us to write a single unified code. That's what this kind of library is for. But what about the actual numbers? What does it abstract?

I'm not just saying this out of the blue. It's nothing compare to you guys but we've been coding on OSAL/cFE for months with non RTEMS and this OSAL priority is confusing for our team. I was about to ditch the whole OSAL priority numbers and use the OS priority throughout the configurations.

The priorities can be changed for mission to mission, and we should define them in configuration system. So having a standard priority number in application doesn't mean anything, IMHO.

What I can propose are:

a) Define a small set of priorities, say, HIGH, LOW, DEFAULT, IDLE. And let OSAL define them. b) Use defined names in OSAL/cFE layer. But never assume them as number, but have OSAL define comparison function if we really need. b) Pass the number down to the OS without touching it.

This give us a simple, clean, and transparent priority numbering system in OSAL and cFE.

Thoughts?

joelsherrill commented 4 years ago

You need some flexibility in the number of priority levels or you cannot use Rate Monotonic Priority Assignment and Rate Monotonic Scheduling. This algorithm for assigning priorities in a way to produce an analyzable task set requires more than a handful of priorities. You need one for each unique period in the system.

jphickey commented 4 years ago

I'm OK with defining names corresponding to certain priority levels such as HIGH, LOW, etc. That would be backward compatible, and if its in the osconfig file, then it could be tuned/customized. That's fine.

But the numeric range of priorities are part of the API. We cannot define APIs application use without also fully defining/specifying the parameter(s) of those APIs at the OSAL level. The current numeric priority abstraction is used by many existing apps and if we are going to make a change that breaks them, we need to have a really good/justified reason to do so. As of now I don't see it. The whole point of OSAL is to facilitate moving between RTOS environments without changing code or configuration. Why would we remove an important aspect of that?

skliper commented 4 years ago

@keegan-moore ping.