Apart from pinning the task that initialises the interrupt and the task that races with the interrupt to the same core, which works, I wondered if there is a more elegant solution?
In a single core situation it seems sufficient to have a critical section around the code in the task, and then the task and interrupt cannot race each other.
I would not of course want to let an interrupt wait to get a lock/mutex.
Avoiding race condition between interrupt on one core and task on the other core
Re: Avoiding race condition between interrupt on one core and task on the other core
There is a (it seems undocumented, will see about changing this) spinlock ("portmux") macro called:
You can use this to try and take a spinlock in a situation where you don't want to block (or don't want to block for too long).
Note that portmuxes spin with interrupts disabled in tasks as well, so it's never recommended to hold one for too long in either a task or an ISR (this means it may be OK to use the non-timeout variant in your ISR as well, provided you know you won't hold it for an overly long time.)
Code: Select all
/** @brief Acquire a portmux spinlock with a timeout
*
* @param mux Pointer to portmux to acquire.
* @param timeout_cycles Timeout to spin, in CPU cycles. Pass portMUX_NO_TIMEOUT to wait forever,
* portMUX_TRY_LOCK to try a single time to acquire the lock.
*
* @return true if mutex is successfully acquired, false on timeout.
*/
bool vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout_cycles);
Note that portmuxes spin with interrupts disabled in tasks as well, so it's never recommended to hold one for too long in either a task or an ISR (this means it may be OK to use the non-timeout variant in your ISR as well, provided you know you won't hold it for an overly long time.)
Re: Avoiding race condition between interrupt on one core and task on the other core
Interestingly, when I try this, I get an assert "coreID == mux->owner" failed when doing vPortCPUReleaseMutex with tasks distributed between the cores.
This suggests that it is not core safe?
On a side note, I'd also got caught out by a race between the cores when using the high resolution timer to do callbacks because the high resolution timer was on a different core.
This suggests that it is not core safe?
On a side note, I'd also got caught out by a race between the cores when using the high resolution timer to do callbacks because the high resolution timer was on a different core.
-
- Posts: 9764
- Joined: Thu Nov 26, 2015 4:08 am
Re: Avoiding race condition between interrupt on one core and task on the other core
You will get that if you try to release the mux on a different core than it was taken. Could that be something you're doing?
Re: Avoiding race condition between interrupt on one core and task on the other core
I think I mixed up the purpose of what ESP_Angus was suggesting. I added a critical section in my interrupt as well as my task and now can distribute the tasks freely between the cores.
Re: Avoiding race condition between interrupt on one core and task on the other core
I think I was mistaken again... and thought it was OK because of how tasks were allocated in that build but the problem reoccurred and only pinning tasks to the same core avoids the problem.
I am hoping the new CAN driver will behave and will not try further to work around the old one.
I am hoping the new CAN driver will behave and will not try further to work around the old one.
Who is online
Users browsing this forum: Majestic-12 [Bot] and 94 guests