Skip to content

Docs: Detail issue with hard ISRs and globals. #10620

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

Merged
merged 1 commit into from
Jan 16, 2025

Conversation

peterhinch
Copy link
Contributor

This comes out of discussions with @jimmo: there seems to be a hazard which may be little known.

I am unclear about the status of user classes which have bound variables. Are these implemented as a dict?

@dpgeorge dpgeorge added the docs label Apr 11, 2023
@peterhinch
Copy link
Contributor Author

I don't normally ping, but I think there is a significant issue here.

It concerns professional applications where reliability is paramount. Knowing that small int access is atomic, the programmer might think a global provides a safe way to return data from a hard ISR. I was surprised to learn from @jimmo that this is not guaranteed.

Is there a safe way to return a small int from a hard ISR short of using (e.g) a threadsafe queue?

@jimmo
Copy link
Member

jimmo commented May 19, 2023

Sorry I missed this in January @peterhinch . I think this is a good improvement, and is a lot better than what was there before.

You are of course correct, we really need to nail down the semantics of what is and isn't defined behavior in the face of hard IRQs, and now that we're supporting GIL-less multithreading on the rp2 the same applies there too (but with a lot more scope for problems!).

It concerns professional applications where reliability is paramount. Knowing that small int access is atomic, the programmer might think a global provides a safe way to return data from a hard ISR. I was surprised to learn from @jimmo that this is not guaranteed.

My understanding is that your updated wording is correct. It is safe to write a small int to a global variable (or a class attribute *) as long as there is no chance the underlying dictionary can be in the middle of a re-hash when the IRQ fires.
This will be the case as long as the code does not define new or delete existing globals.

  • It's important that the IRQ finds the class instance via a closure around self, or equivalent, and not via globals!). e.g.
a = 0
b = SomeClass()

def on_irq(p):
  a = 1 # bad, 
  b.attr = 2 # also bad

def main():
  ...
     if something:
       c = True   # c global is created in the middle of the program's execution, might cause rehash which makes access to `a` and `b` invalid in ISR.
class Ok:
  def __init__(self):
    def on_irq(p):
      self.attr = 1 # safe as long as this instance's dict isn't changing, doesn't matter what's going on with globals

(So, for example, ThreadSafeFlag is safe).

I'm fairly sure a closure around a local would be safe to. @dpgeorge would need to confirm.

def main():
  a = 0
  def on_irq(p):
    a = 1

Is there a safe way to return a small int from a hard ISR short of using (e.g) a threadsafe queue?

Specifically for the case of returning a small int, it should always be possible to find some shared scope to put the small int on. Maybe I'm misunderstanding the question though? i.e. if you explicitly want to be able to queue up multiple interrupts worth of values to application code that consumes them asynchronously?

Even if you had some sort of ISR-safe queue, you still need a way to access the queue. (As you say in the new wording in this PR, accessing a global for read from an ISR is still a problem). It's implementing an ISR-safe queue that's the hard part!

@peterhinch
Copy link
Contributor Author

Thank you. I think for most applications the aim should be to define all globals (including class instances) before initiating hard IRQ's - and never to delete globals.

You might want to comment on #9458 - a possible ISR-safe queue.

@dpgeorge
Copy link
Member

I agree this is an issue that needs clarifying.

But maybe we can improve the situation so it "just works". See #11604 for an attempt at that, which makes rehashing atomic wrt IRQ handlers.

@projectgus projectgus self-requested a review October 3, 2024 00:12
Copy link
Contributor

@projectgus projectgus left a comment

Choose a reason for hiding this comment

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

I think we should merge this, it's an important and useful clarification. The style is maybe a bit inaccessible, it could be presented as a list of "safe" and "unsafe" code samples - but the style is already there in the existing doc so this is still an improvement.

If we make the ISR-safety of objects better in the future then we'll need to update the docs again then, anyway.

@projectgus projectgus requested a review from dpgeorge October 8, 2024 06:45
Copy link
Member

@dpgeorge dpgeorge left a comment

Choose a reason for hiding this comment

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

Yes, let's merge this.

Signed-off-by: Damien George <damien@micropython.org>
@dpgeorge dpgeorge merged commit 624bd48 into micropython:master Jan 16, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants