Skip to content
This repository has been archived by the owner on Jan 15, 2021. It is now read-only.

Add a C re-entrant critical section API #18

Closed
wants to merge 3 commits into from
Closed

Add a C re-entrant critical section API #18

wants to merge 3 commits into from

Conversation

bremoran
Copy link
Contributor

Implements the API discussed in #16

@bremoran
Copy link
Contributor Author

static volatile uint32_t interruptEnableCounter = 0;
void critical_section_enter()
{
__disable_irq();
Copy link
Contributor

Choose a reason for hiding this comment

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

If the interrupts are disabled and you call critical_section_enter and then critical_section_exit, it'll enable interrupts. Wouldn't it be better to save/restore interrupt state?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Don't disable interrupts, call critical_section_enter.

Copy link
Contributor

Choose a reason for hiding this comment

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

I won't disable interrupts, but library code (for example) might not care if it runs with interrupts enabled or not, but still re-enable interrupts by mistake if it uses these functions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That said, I could preserve the primask if critical_section_enter is called and interruptEnableCounter is 0.

/* not allowed to overflow the interruptEnableCounter. */
if (interruptEnableCounter == UINT32_MAX) {
/* Generate a fault */
*((uint32_t *)NULL) = 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

is this guaranteed to fault for all architectures including the ones we might support? Is address 0 always going to remain unmodifiable? perhaps we need to use an abstraction here. die()?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, it was that or an unusable opcode.

Choose a reason for hiding this comment

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

Good spot @rgrover ... it is legal (AFAIK, but definitely not recommended) to put RAM at 0x0, in which case this would set the initial SP to an invalid value (and cause the next reset exception to escalate to a fault of some kind... hard fault?).

@bremoran
Copy link
Contributor Author

bremoran commented Aug 6, 2015

Comments?

@rgrover
Copy link
Contributor

rgrover commented Aug 6, 2015

The nRF5x platform needs a soft-device specific critical section API; __disable_irq() is not an option. I believe critical section and atomic-ops may need to be target-specific.

@bremoran
Copy link
Contributor Author

bremoran commented Aug 6, 2015

@rgrover Is that problem duplicated on any other platforms? It might be more appropriate to add a linker override to the nRF5x platform, rather than making all atomic ops target-specific. On most platforms, they will be generic operations.

@rgrover
Copy link
Contributor

rgrover commented Aug 6, 2015

currently only the nRF5x requires platform-dependent atomics; but the same would be true for the forthcoming POSIX platform. Perhaps @hugovincent can share some thoughts. I believe we shouldn't base critical-section on disabling interrupts.

@rgrover
Copy link
Contributor

rgrover commented Aug 6, 2015

Should we introduce a platform_enter_critical(&state) [https://github.com/ARMmbed/mbed-6lowpan-eventloop-adaptor/blob/master/source/events.cpp#L32] to handle platform specific implementations?

@bogdanm
Copy link
Contributor

bogdanm commented Aug 9, 2015

@rgrover, that seems to be the way to go, yes.

@bremoran
Copy link
Contributor Author

Is this PR still relevant?

@bogdanm
Copy link
Contributor

bogdanm commented Aug 12, 2015

It is, but I'd say not for our feature freeze. We can deal with it later.

/* Generate a fault */
((void(*)(void))&invalid)();
}
interruptEnableCounter++;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This should probably use atomic_incr

@bremoran
Copy link
Contributor Author

We should check for a race between __get_PRIMASK and __disable_irq

#include "mbed-util/critical.h"

static volatile uint32_t interruptEnableCounter = 0;
static volatile uint32_t critical_primask = 0;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This variable is not required.

@0xc0170
Copy link
Contributor

0xc0170 commented Mar 2, 2016

I believe this one can be closed, resolved in #88

@0xc0170 0xc0170 closed this Mar 2, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants