Skip to content

Multicore aware mutex for rp2xxx#444

Merged
mattnite merged 6 commits intoZigEmbeddedGroup:mainfrom
Uthedris:multicore_semaphore
Apr 20, 2025
Merged

Multicore aware mutex for rp2xxx#444
mattnite merged 6 commits intoZigEmbeddedGroup:mainfrom
Uthedris:multicore_semaphore

Conversation

@Uthedris
Copy link
Contributor

@Uthedris Uthedris commented Apr 14, 2025

The current critical section code in microzig.intterrupt only disables interrupts, it does not block code running on another core from altering protected resources.

This code attempt to address this by both blocking interrupts and providing a mechanism to block other cores from entering.

@Grazfather
Copy link
Collaborator

Looks good. Should this go into enter_critical_section? We'd want this for other ports (that are multicore) as well, but could make those nop for now.

This is probably worth discussing more on discord, if you're not already on there I'd ask you join.

@Uthedris
Copy link
Contributor Author

I joined the discord group. Also made some changes to integrate with enter_critical_section.

@Uthedris
Copy link
Contributor Author

Uthedris commented Apr 16, 2025

Same errors here as the other PR. I don't think it's something I did as other PRs are getting them too.

@Uthedris Uthedris marked this pull request as ready for review April 17, 2025 17:36
@tact1m4n3
Copy link
Collaborator

tact1m4n3 commented Apr 18, 2025

One thing that I haven't considered earlier is that a regular interrupt free critical section might be useful even in a multicore context. I'd suggest we create this multicore critical section inside the rp2xxx port for now, separate for the one in microzig.interrupt (even in the name that should still be exclusive to this). In this case, you can also remove the functions from the cpu modules.

@Uthedris
Copy link
Contributor Author

While there may be some edge case where one only wants to disable interrupts without blocking other cores, in the vast majority of cases, especially for critical sections, I think we'd want to normally do both.

Would it be acceptable to add separate to just control interrupts interrupts?

@tact1m4n3
Copy link
Collaborator

I would say that it's quite useful. If I have a variable shared between an interrupt and the main application code (both running on a single core) a critical section like the one defined in microzig.interrupt is the ideal choice in this case to have safe concurrent access. Only if the variable is shared between cores in that case a global critical section might not be what you need either, but instead you would use a semaphore for that specific resource and you could have more of them for each resource. What usecases do you have in mind for this multicore critical section? Please correct me if I'm wrong on what I said above. I'm no expert in synchronization methods :))

@Uthedris
Copy link
Contributor Author

I do see your point. In fact originally I had meant to add a multicore semaphore until it was suggested that it go in critical section.

I still think something call "critical section" should provide the maximum amount of protection, and something the just disable interrupts be called something like, well, "disable_interrupts". But, when all is said and done its just a name. I'll back to doing it the other way.

@Uthedris Uthedris force-pushed the multicore_semaphore branch from 0351408 to b8e68b6 Compare April 19, 2025 15:16
@Uthedris
Copy link
Contributor Author

Uthedris commented Apr 19, 2025

I reverted changes to enter_critical_section and fixed the launch core 1 code in hazard3 so it works. I also added a logging function protected by a mutex so std.log.xxx messages from different cores cannot collide.

@Uthedris Uthedris changed the title Multicore aware semaphore for rp2xxx Multicore aware mutex for rp2xxx Apr 19, 2025
@Grazfather
Copy link
Collaborator

I like how this is looking.

enter_critical_section should disable interrupts and lock out the cores. We could use comptime to only do the latter in a multicore context. We should also still allow the user to only disable interrupts. We should be able to use a core mutex in enter_critical_section to protect the entire core. Is that a followup PR or should it be done in this one?

@tact1m4n3
Copy link
Collaborator

I think we should do that in a follow up PR and we can make an issue to discuss a bit the fate of interrupt.enter_critical_section before hand.

@Uthedris
Copy link
Contributor Author

I agree with @tact1m4n3 that having something that makes sure interrupts are disabled (whether they already are or not) when entering some code, and then restoring the previous state on exit is useful. That's current what enter_critical_section does. I think the current name is somewhat unfortunate, as it sounds over-broad, but it's just a name.

With this PR we do have the ability to restrict access to a resource to one thread at a time by using Mutex, but this code is specific to the Raspberry Pi.

Perhaps we should add a Mutex wrapper directly in microzig (or maybe
microzig.utilities or similar) that calls into a platform specific implementation.

@Uthedris
Copy link
Contributor Author

If we want a common Mutex, perhaps I should move this code from hal.multicore into a new hal.mutex, so we can use the same path for Mutex `implementations in other single-core CPUs too.

@mattnite mattnite merged commit 93838d8 into ZigEmbeddedGroup:main Apr 20, 2025
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants