Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests: add test for priority inversion using muxes #7444

Closed

Conversation

haukepetersen
Copy link
Contributor

As pointed out in #7365, we do not have any protection against priority inversion in the default kernel.

As a starter, here is a simple test application, that showcases a constructed case of priority inversion. I use this test down the line to test my implementation of priority inheritance, but I think this test deserves to be merged stand-alone so we have something to keep reminding us of this issue...

@haukepetersen haukepetersen added the Area: tests Area: tests and testing framework label Aug 4, 2017
@haukepetersen haukepetersen added this to the Release 2017.10 milestone Aug 4, 2017
@haukepetersen haukepetersen added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Aug 4, 2017
@jnohlgard
Copy link
Member

See also #7372

@haukepetersen
Copy link
Contributor Author

oh damn, completely overlooked that one...

@haukepetersen
Copy link
Contributor Author

@geith, @smlng, @gebart: do you guys have any preference towards this PR or towards #7372? Would be nice to get one of them merged and the other one closed.

@smlng
Copy link
Member

smlng commented Aug 28, 2017

Both look very similar to me, which is not a surprise considering the issue at hand. Thus, no an actual preference, other than first come, first merged 😉

@haukepetersen
Copy link
Contributor Author

I added some more output (e.g. numbering the events to verify the order in which they occur). But you are right, first come first serve should be the way to go. So let's merge #7372 and I can add the improved output once merged.

@smlng
Copy link
Member

smlng commented Dec 21, 2017

#7372 is merged now, please rebase and adapt as needed

@@ -0,0 +1,9 @@
APPLICATION = mutex_priority_inversion
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this line

#include "mutex.h"
#include "xtimer.h"

#define TICK_LEN (50 * US_PER_MS)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

50UL

#define TICK_LEN (50 * US_PER_MS)
#define EXSPECTED_RESULT (4)

static mutex_t res_mtx;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static mutex_t res_mtx = MUTEX_INIT; and remove dynamic initialization in main()?

#include "xtimer.h"

#define TICK_LEN (50 * US_PER_MS)
#define EXSPECTED_RESULT (4)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here and below: EXSPECTED -> EXPECTED

@smlng
Copy link
Member

smlng commented Jan 15, 2018

@haukepetersen any chance you'll adapt to #7372 and address comments to get this merged for 2018.01 release? Otherwise, please postpone to 2018.04.

@haukepetersen
Copy link
Contributor Author

sorry for the long silence. Merged the previous test application for this matter with my approach. I see the following enhancements:

  • test is now automatable (and the pexpect script is included)
  • the numbering of events makes it easier to see if the order is correct
  • some minor code fixes (e.g. static for global variables, etc)

@smlng
Copy link
Member

smlng commented Jan 31, 2018

I'm unsure if the (re)naming makes sense, i.e., mutex_ instead of thread_priority_inversion. I mean the threads have priorities and not the mutex. Hence, thread (as used by @geith) makes IMHO more sense.

@haukepetersen
Copy link
Contributor Author

I also tended to this, but we can/should construct a second test that demonstrates the same behavior using msg...

So how about thread_priority_inversion_mutex and (for future use) thread_priority_inversion_msg?

@smlng
Copy link
Member

smlng commented Jan 31, 2018

So how about thread_priority_inversion_mutex

sounds semantically more right 😉

@haukepetersen
Copy link
Contributor Author

alright, will do.

@kaspar030 kaspar030 removed this from the Release 2018.04 milestone Apr 16, 2018
@haukepetersen
Copy link
Contributor Author

renamed the test to thread_priority_inversion_mutex as discussed above. Also removed the then deprecated thread_priority_inversion test.

IMHO this PR should be good to go, so please have one last good look :-)

@haukepetersen
Copy link
Contributor Author

wait, something went wrong when rebasing, need to re-introduce the test script...

@danpetry
Copy link
Contributor

danpetry commented Jun 7, 2018

Ok, will have a look when it's rebased

@haukepetersen
Copy link
Contributor Author

done.

Copy link
Contributor

@danpetry danpetry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The two code convention comments should be addressed, the others don't need to be (although I think a thread timing diagram would be nice)

static kernel_pid_t _pid_high;

static int _result = 0;
static int _res_addsub = 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be local to event(), although for a test it doesn't really matter

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could be done, be so far we don't really use local static variables in RIOT - though I can't recall the reasons. Poking the Internet I found quotes like

Local statics may look useful, however they cause major problems when trying to port code to a multi-task/multi-threading environment, and should generally be avoided where possible.

Although this might no apply to this particular situation, IMHO it does not hurt either to have those variables in the compilation unit scope. On top I think declaring them like this makes it much easier to see the actual memory consumption of the module.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok cool. Thanks for the info.

Event 7: t_high - unlocking mutex

*** result: SUCCESS ***
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A thread diagram could be useful, either here or in the code. Perhaps with some times along the x axis

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could be, but don't have the time to draw one...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also mind: this is a test and not some user-friendly example application. So once verified that it actually tests for the intended behavior its not like people dig into this app on a daily basis.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok sure.

{
/* record event */
_result += (_res_addsub * num);
_res_addsub *= -1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just wondering - why this approach, rather than e.g. raising a flag _success = true or something if the high priority thread finishes? That would be more readable IMO - unless there's something I'm missing re optimization or something like that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because this approach can actually detect if all threads were run in the correct order (at least to a large extend)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I see - IMO even with an order there might be a more readable way, e.g. keeping an i++ counter and comparing it with each event number or something. But that's your style/choice and it's not critical here anyway

Priority inversion is a known problem in real-time systems, leading in certain
constellations to lower priority threads indirectly blocking higher priority
threads. This test application constructs a simple situation, where exactly this
occurs: t_low owns a mutex, which t_high is waiting on. Now t_mid gets all the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of "Now t_mid gets all the CPU time" I suggest starting this sentence with "At that point, t_mid starts and pre-empts t_low"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

event(7, "t_high", "unlocking mutex");
mutex_unlock(&_res_mtx);

return NULL;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indentation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

delay(2);

event(4, "t_mid", "starting infinite loop, potentially starving others");
while(1){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while (1) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@danpetry
Copy link
Contributor

Re the premise/design/etc of the PR, all seems good

@haukepetersen
Copy link
Contributor Author

addressed comments and rebased.

unlocking the mutex shared with t_high. So t_mid is indirectly preventing t_high
from running.
occurs: t_low owns a mutex, which t_high is waiting on. At that point, t_mid
starts and pre-emts t_low (as t_mid has a higher priority than t_low),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, should be pre-empts. Last comment

@danpetry
Copy link
Contributor

After that, if you address Murdock and Travis complaints and squash (and rebase if necessary) then I'll merge it.

@haukepetersen
Copy link
Contributor Author

fixed and squashed.

@haukepetersen
Copy link
Contributor Author

fixed and squashed board blacklisting due to changed names of nucleo boards.

@stale
Copy link

stale bot commented Aug 10, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you want me to ignore this issue, please mark it with the "State: don't stale" label. Thank you for your contributions.

@stale stale bot added the State: stale State: The issue / PR has no activity for >185 days label Aug 10, 2019
@haukepetersen haukepetersen added the State: don't stale State: Tell state-bot to ignore this issue label Aug 12, 2019
@stale stale bot removed the State: stale State: The issue / PR has no activity for >185 days label Aug 12, 2019
@MrKevinWeiss MrKevinWeiss added this to the Release 2021.07 milestone Jun 21, 2021
@MrKevinWeiss MrKevinWeiss removed this from the Release 2021.07 milestone Jul 15, 2021
@MrKevinWeiss
Copy link
Contributor

Is this still relevant after #17040 or can we close it?

@Teufelchen1 Teufelchen1 closed this Feb 5, 2024
@kaspar030
Copy link
Contributor

next time please state reason for closing (even if it seems obvious to you).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: tests Area: tests and testing framework CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR State: don't stale State: Tell state-bot to ignore this issue
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants