[En-Nut-Discussion] NutEnter|ExitCritical dilemma
Uwe Bonnes
bon at elektron.ikp.physik.tu-darmstadt.de
Thu Jan 18 13:52:40 CET 2018
Hello,
some 10 year later and the discussion about NutEnter|ExitCritical is still
going on. See also
http://lists.egnite.de/pipermail/en-nut-discussion/2008-February/
"confirmed!!! Re: NutOS 4.4.0 on ARM7: possibly bug in NutEnterCritical /
NutExitCritical"
I had also some input by private mail.
Let me state some premises:
===========================
1. Changing the API of an existing function was a NO-NO with Harald and we
should keep that habit!
2. In our common code (nut/dev, nut/os) a lot of NutEnterCritical /
NutExitCritical() usage is used to protect a single access to single 2 or 4
byte Variable that could also be changed by an interrupt. This is needed for
any 8-bit architecure, but not for 32-bit arch. I brought up the subject in
http://lists.egnite.de/pipermail/en-nut-discussion/2015-November/thread.html
but the discussion mostly got into esoteric problems.
Things like nut/os/thread.c:NutThreadRemoveQueue()
157 NutEnterCritical();
158 tqp = *tqpp;
159 NutExitCritical();
should get use a new macro that only expand to a critical section on 8-bit
archs and expand to nothing on 32-bit archs.
3. nut/arch/<32-bit arch>/os/thread|context.c NutThreadCreate()
has a code sequence
...
NutEnterCritical();
...
NutThreadAddPriQueue() {
...
NutEnterCritical();
...
NutExitCritical()
}
... more code needing interrupts off ..
NutExitCritical()
This is doomed for problems if you create thread during run time with much
interrupts going on. I have not yet met that problem as I create my threads
before I enter the "while(1){}" loop in main. But creating threads with a
lot of interrupts going on is a valid problem and must be handled.
4. Only in very rare cases should arch-specific code use critical section
with all interrupts disabled! Disable selected interrupts or use arch-
specific synchronization mechanisms instead.
5. os/msg.c is a heavy user of NutEnter|ExitCritical()
However there is no example code should the intended use. Any code pieces
showing the use is welcome!
What others do
=============
On Avr an ATOMIC_BLOCK() macro is provided.
http://www.nongnu.org/avr-libc/user-manual/group__util__atomic.html#gaaaea265b31dabcfb3098bec7685c39e4
This has been ported to cortex:
https://www.mikrocontroller.net/attachment/294497/cm_atomic.h
Possible solutions:
==================
For 1: Tag NutEnter|ExitCritical() as deprecated, but keep it untouched.
Changing syntax and scope as Dusan proposed violated premise 1.
For 2: Add NutEnter|ExitCriticalAccess() macro, resolving to nothing on
32-bit archs and to a valid critical section on 8-bit.
This removes unneeded code for 32-bit archs.
For 3: We should consider the ATOMIC_BLOCK solution.
Otherwise what about a solution like:
int irq_state;
irq_state = NutEnterCriticalNest()
<protected code>
NutExitCriticalNest(irq_state)
Some new macro/function is needed to not violate premise 1.
Solutions 1 and 2 can be implemented probably with not to much hassle. But
solution 3 will break for architecture where there is no active user and
probably also for the message queue implemenation in os/msg.c as there is no
code to test.
Can people with out-of sync active trees live with such a solution so maybe
we get the trees in sync again? Comments?
Cheers
--
Uwe Bonnes bon at elektron.ikp.physik.tu-darmstadt.de
Institut fuer Kernphysik Schlossgartenstrasse 9 64289 Darmstadt
--------- Tel. 06151 1623569 ------- Fax. 06151 1623305 ---------
More information about the En-Nut-Discussion
mailing list