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

sys/pm: Correctly access pm_blocker #13977

Merged
merged 1 commit into from
Jul 15, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions sys/pm_layered/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@
/**
* @brief Global variable for keeping track of blocked modes
*/
static volatile pm_blocker_t pm_blocker = { .val_u32 = PM_BLOCKER_INITIAL };
static pm_blocker_t pm_blocker = { .val_u32 = PM_BLOCKER_INITIAL };
benpicco marked this conversation as resolved.
Show resolved Hide resolved

void pm_set_lowest(void)
{
unsigned state = irq_disable();
pm_blocker_t blocker = pm_blocker;
irq_restore(state);
unsigned mode = PM_NUM_MODES;
while (mode) {
if (blocker.val_u8[mode-1]) {
Expand All @@ -50,7 +52,7 @@ void pm_set_lowest(void)
}

/* set lowest mode if blocker is still the same */
unsigned state = irq_disable();
state = irq_disable();
if (blocker.val_u32 == pm_blocker.val_u32) {
DEBUG("pm: setting mode %u\n", mode);
pm_set(mode);
Expand Down Expand Up @@ -81,7 +83,10 @@ void pm_unblock(unsigned mode)

pm_blocker_t pm_get_blocker(void)
{
return pm_blocker;
unsigned state = irq_disable();
pm_blocker_t result = pm_blocker;
irq_restore(state);
return result;
Comment on lines +86 to +89
Copy link
Contributor

Choose a reason for hiding this comment

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

This should only be necessary on non-32 bit machines, no?

Copy link
Member Author

Choose a reason for hiding this comment

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

There sadly is no guarantee, that the compiler will generate a single read whenever possible. There were examples on GCC generating two 32 bit stores on x86_64 when writing to a volatile, as two stores with an immediate where faster than preparing the correct value in a register and writing that back to memory. As a result, some linux drivers stopped working when compiled with that GCC version. I think it is safe to say that the Linux kernel guys convinced the compiler guys that their compilers have no host to run on if they break kernels by splitting a single volatile accesses into two accesses. But for non-volatile accesses we should still be careful to do any assumptions on how the generated assembly looks like.

So what we could IMO safely do is something like this:

pm_blocker_t pm_get_blocker(void)
{
    pm_blocker_t result;
    if (ARCH_32BIT) {
        volatile uint32_t *tmp = &pm_blocker.val_u32;
        result.val_u32 = *tmp;
    }
    else {
        unsigned state = irq_disable();
        result = pm_blocker;
        irq_restore(state);
    }
    return result;
}

It would be nice to make the FEATURES like arch32_bit available to C code for this. The compiler should than drop the dead branch.

Copy link
Contributor

Choose a reason for hiding this comment

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

ARCH_32_BIT is now available, can you adapt to your suggestion?

Copy link
Contributor

Choose a reason for hiding this comment

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

ping @maribu :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Sorry for the delay. I still had #14331 in the pipeline, which is a better solution than what I suggested above.

I'm not sure if we should just stall this PR until #14331 is merged, or get it in without the optimization for now.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would merge without optimizations, that PR can take time and this is still potential source for issues.

}

#ifndef PROVIDES_PM_LAYERED_OFF
Expand Down