-
Notifications
You must be signed in to change notification settings - Fork 2k
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
cpu/atmega_common: __exit_isr thread_yield #8988
Conversation
a0a1515
to
0087952
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good improvement! For consistency, I would prefer to let the enter/exit isr calls in the UART driver to remain in each ISR instead of the central IRQ handler.
} | ||
|
||
#ifdef UART_0_ISR | ||
ISR(UART_0_ISR, ISR_BLOCK) | ||
{ | ||
__enter_isr(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer the original design where enter isr is the first line of each ISR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this just a preference or are there any reasons. As i see there is no benefit in settings the __in_isr
flag as early as possible, as there is no chance that code could be invoked which could use this information.
Setting the flag prevents code in the callback to sleep or do other things which schould not be done in interrupts, so setting it before the callback should be sufficient, imho.
I change it as it is like this in all other interrupt handler and thought it would also increase consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personal preference. The consistency helps when reviewing the code and also reduces the risk of missing it if someone uses this periph driver as a template for some other driver for the same CPU.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gebart maybe we just have a language problem as consistency translates into two different meanings in german, depending of the context. Do you mean consistency in regard as it stays as it was or consistency as it is similar to other code of the atmegas?
RIOT/cpu/atmega_common/periph/gpio.c
Lines 264 to 274 in 22aa6b9
static inline void irq_handler(uint8_t pin_num) | |
{ | |
__enter_isr(); | |
config[pin_num].cb(config[pin_num].arg); | |
__exit_isr(); | |
} | |
ISR(INT0_vect, ISR_BLOCK) | |
{ | |
irq_handler(0); /**< predefined interrupt pin */ | |
} |
RIOT/cpu/atmega_common/periph/timer.c
Lines 169 to 189 in 22aa6b9
#ifdef TIMER_NUMOF | |
static inline void _isr(tim_t tim, int chan) | |
{ | |
__enter_isr(); | |
*ctx[tim].mask &= ~(1 << (chan + OCIE1A)); | |
ctx[tim].cb(ctx[tim].arg, chan); | |
if (sched_context_switch_request) { | |
thread_yield(); | |
} | |
__exit_isr(); | |
} | |
#endif | |
#ifdef TIMER_0 | |
ISR(TIMER_0_ISRA, ISR_BLOCK) | |
{ | |
_isr(0, 0); | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess you are right regarding consistency. I am not very engaged in the atmega development, sorry.
What I was trying to push for is to have a strict template for the ISR definitions which should be the same across all drivers for the CPU family, which you showed that this is. Consistency makes refactoring the driver code easier in the future. I am happy as long as this design matches the other periph drivers for the atmega.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please split out the uncrustify commit.
cpu/atmega_common/include/cpu.h
Outdated
@@ -75,20 +81,20 @@ void cpu_init(void); | |||
/** | |||
* @brief Print the last instruction's address | |||
*/ | |||
__attribute__((always_inline)) static inline void cpu_print_last_instruction(void) | |||
static inline void __attribute__((always_inline)) cpu_print_last_instruction(void) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unrelated
{ | ||
uint8_t hi; | ||
uint8_t lo; | ||
uint16_t ptr; | ||
|
||
__asm__ volatile( "in __tmp_reg__, __SP_H__ \n\t" | ||
__asm__ volatile ("in __tmp_reg__, __SP_H__ \n\t" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unrelated
cpu/atmega_common/include/cpu.h
Outdated
@@ -34,8 +34,10 @@ | |||
#include <stdint.h> | |||
|
|||
#include <avr/interrupt.h> | |||
#include "board.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this include actually used?
My concerns have been addressed. |
@kaspar030 can you approve it like this? |
@kaspar030 ping 😏 |
cpu/atmega_common/include/cpu.h
Outdated
*/ | ||
static inline void __exit_isr(void) | ||
static inline void __attribute__((always_inline)) __exit_isr(void) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why always inline?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As it will be executed in an ISR, i thought speed could matter.
And if optimization is off it won't
GCC does not inline any functions when not optimizing unless you specify the ‘always_inline’ attribute for the function, like this:
/* Prototype. */ inline void foo (const char) __attribute__((always_inline));
But as the statement is the attribute has to be after the function, i am not sure but, i think it does not matter.
This benchmark makes me think maybe inline
only is better.
cpu/atmega_common/include/cpu.h
Outdated
*/ | ||
static inline void __enter_isr(void) | ||
static inline void __attribute__((always_inline)) __enter_isr(void) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why always inline? Don't trust the compiler?
@gebart and @kaspar030 rebased onto #8904 and added neccessary changes. |
This looks okay to me, but note that it introduces a yield in the periph/gpio.c ISR where there previously was none. |
@ZetaR60 i think that is not fully correct, it request a thread yield if there was a But thinking further is it neccessary to duplicate the code?
|
Yes, you are right about my comment being erroneous. Sorry for the lazy thought process. There are problems with moving |
@ZetaR60 seems it was too late for my brain, of course moving Maybe we could agree on just putting the content of the I don`t imagine a situation where saving the context and running the scheduler is necessary if there was not a thread change request. Further thoughts, I think there should be a function like |
@Josar can you be a bit more precise which things you are referring to? Currently nothing is run at the end of an ISR if there was no attempt to yield within the callback, because sched_context_switch_request is not set. Are the other things you are mentioning proposed changes to core/thread.c ? Currently this PR is a refactor; perhaps discussion of changes of behavior should be moved to another PR specific to that change? There might be some improvements to be made in the way I rewrote context swapping, but that rewrite took a lot of testing to do properly. |
@ZetaR60 yes this PR should just be an refactorization.
|
Those sound like reasonable changes. They would involve changing behavior though, so the extensive testing done in #8904 probably ought to be re-checked in a PR that changes it. |
@ZetaR60 thinking further i think this can be optimized. After deciding that a context swap is allowed in an ISR there is no need of preventing an context swap in an ISR, the only thing which has to be taken care of is to return with As it is now we check for isr set the flag, return to caller, call next function, check for flag and do the swap.
and removing the if irq in the scheduler
first test shows expected results.
The question is are there platforms which can not switch the context in an ISR? |
@kYc0o would you mind having a look at this? |
@Josar This change to thread_yield_higher is a pretty major change in behavior. Could you create another PR for it? |
@kaspar030 maybe you could find some time? |
Code wise looks OK. there are some "unrelated" changes due to uncrustify, but I guess they're valid. I need to test though. Will report back when I test on my available boards. @ZetaR60 can you also test on the mega-xplained? I guess timers and peripherals basic testing is enough. |
I ran some tests, and got a couple failures:
I think we need a bit more extensive examination. @Josar I suggest rebasing on trunk and running tests side by side with your code and the exact same revision without your code. |
Rebased and fixed. PS: it would be nice to have a readme in each test with the expected output. |
Confirmed that the previously failed tests are now succeeding on mega-xplained. Also did another proofread of the changes, and they look fine. Let me know if I should run any other tests on mega-xplained. |
@kaspar030 any further remarks? |
@kaspar030 could you have a second look? |
@Josar You are being a bit aggressive with pinging Kaspar. I know things often move slowly, but I don't think repeating requests that much is going to help. |
Thank you @ZetaR60 for indicating this. Not ment to be agressiv at all. |
@Josar please squash. |
All the tests in #8988 (comment) passed on arduino-mega2560. |
c30bb2c
to
a8f37f4
Compare
I uncrustified the touched files, hope this is allright. |
cpu/atmega_common/periph/timer.c
Outdated
@@ -87,17 +88,21 @@ int timer_init(tim_t tim, unsigned long freq, timer_cb_t cb, void *arg) | |||
uint8_t pre = 0; | |||
|
|||
/* make sure given device is valid */ | |||
if (tim >= TIMER_NUMOF) { | |||
if (tim >= TIMER_NUMOF) | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this change the result of uncrustify ? Then I think there's an issue with the uncrustify configuration file. The opening curly brace should be on the same line as the if.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems my vscode config got messed up.
Perfect! Thanks for your contribution! |
As proposed by @gebart in #8979 this PR adds
thread_yield();
to__exit_isr
similar to #6171.This avoids duplicated code.
Additionaly code was uncrustified.