Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upUpdate to be thread safe and add multi-core support (ie ESP32) #480
Comments
|
I haven't read this fully but it seems like the esp-idf supports the two threads... they could at least get two cores running and pin all the mongoose functions to one core. This could possible let a user add additional independent task to the 2nd core to start with? https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/freertos-smp.html |
|
Then again, this may go back to making mongoose thread safe as the first step and let users create their own task with less worry about threading and interacting with mongoose in those threads |
|
I'm also very interested in this. |
|
At very least it would be very helpfull to have thread-safe LOG() macro |
|
it is, actually. logging is thread-safe. the only problem is sometimes the task it's logging from doesn't have enough stack... *printf calls are quite expensive in terms of stack. |
|
@rojer Do you think the stack running out is the case in the following backtrace? I can't really tell.
i am using stack size of (MGOS_TASK_STACK_SIZE_BYTES / STACK_SIZE_UNIT) |
|
Ok, sorry. The problem was in directly calling |
|
No. I take that back. It actualy happens in " cs_log_print_prefix() " call... |
code around line 143. looks like you're trying to log from an ISR handler? this is not going to work. |
|
from ISR you can use mgos_cd_printf that will print to UART |
|
Just checked. I am not loging from ISR handler... |
|
But FreeRTOS scheduler does switch between tasks in ISR, so one task preempting others tasks is basicaly ISR for the other tasks. |
|
Now after some testing i am pretty sure that this problem happens when i call LOG(...) from freertos task other than main mongoose task. probability is increased when running on the same freertos priority as main mongoose task and 1000Hz tickrate, since context switches are more frequent that way due to time slicing. Perhaps then there is more chance that two tasks call LOG() at once. |
|
yet, somehow xPortCanYield() ends up being false. is the trace always the same as above? |
|
Yes |
|
I have GPIO ISR handler, which sends job to queue which is later handled by separate task. So it might be possible that after the GPIO ISR freertos scheduler immediately jumps to different task which is receiving the queue, because it gets unblocked by that ISR sending to queue. |
|
To be clear, in the ISR i am using this macro after sending job to the queue if queue gives me *pxHigherPriorityTaskWoken == true.
|
|
I think it would make sense for mongoose loging to use FreeRTOS stream buffers That way it would be possible to log to such buffer from anywhere in code. Multiple tasks and ISRs. Stream buffer would then synchronize everything to make it thread safe. |
|
BTW what about |
|
Until it gets fixed, i came up with temporary workaround: #include "FreeRTOS.h"
#include "task.h"
#include "mgos_core_dump.h" //mgos_cd_printf() prototype
#include "common/cs_dbg.h"
#ifndef __FILENAME__
/// We don't want to log full paths, so we only use the filename
#define __FILENAME__ (strrchr("/" __FILE__, '/') + 1)
#endif //__FILENAME__
/**
* mgos macro `LOG()` is not thread safe, so we have this instead.
* unfortunately it can currently log only to UART...
*/
#define PQ_LOG(l, x) \
do { \
if(cs_log_level >= l) { \
mgos_cd_printf("%.24s:%d:%.16s:\t\t", __FILENAME__, __LINE__, pcTaskGetTaskName(NULL)); \
mgos_cd_printf x; \
mgos_cd_printf("\n"); \
} \
} while (0)(unfortunately this does not play very well with power management enabled #556 ) |
|
From what i read here espressif/esp-idf#4838 So perhaps we should try it and always use REF_TICK unless user specifies higher baudrate? |
|
BTW what is expected behaviour of LOG() in ISR? It should probably look like this: LOG mutex is unlocked, ISR can LOG() Even better version: There is dedicated buffer for ISRs to LOG into. It is dumped to LOG() as soon as it gets unlocked. What currently happens is No matter if LOG is locked or not, calling LOG() in ISR causes panic |
|
LOG is not meant to be used in ISR.
…On Tue 27 Oct 2020, 09:03 Tomas Mudrunka, ***@***.***> wrote:
BTW what is expected behaviour of LOG() in ISR? It should probably look
like this:
LOG mutex is unlocked, ISR can LOG()
LOG mutex is locked, ISR cannot LOG() and therefore should ignore the
LOG() call
What currently happens is
No matter if LOG is locked or not, calling LOG() in ISR causes panic
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#480 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAEBW2YJSWHBVCMK4KJDIH3SM2EHNANCNFSM4GX2J5MA>
.
|
Ok, that is not really important for me. Just saying it can be done if needed :-) |
|
I am still strugling to isolate the bug. Might |
|
O yeah! I got it. Happens when calling LOG() with ints disabled. At least in some cases...
|
|
i bet it can. |
|
Can you please add some asserts checking if we are in critical section, so this becomes immediately obvious when somebody runs to this limitation again? As well as puting big warning to LOG documentation https://mongoose-os.com/docs/mongoose-os/api/core/cs_dbg.h.md //Isolated case of code causing the crash :-)
#include "mgos.h"
enum mgos_app_init_result mgos_app_init(void)
{
mgos_ints_disable();
LOG(LL_INFO,("Log from task %d", 456));
mgos_ints_enable();
return MGOS_APP_INIT_SUCCESS;
} |
|
well, there are a lot of things you shouldn't be doing with ints disabled, logging is just one fo them - in fact, the set of thinjgs you can safely do with ints disabled is very limited. i guess it's worth documenting somewhere, though |
|
Anyway. I am satisfied with this conclusion, it is no problem to move LOG() out of the critical section. if i only knew week ago... I might have save myself lots of headache :-) BTW what about stuff like MQTT? Can that be considered thread safe? Hopefully i will soon release my module implementing parallel event loops, works well, just needs bit of polishing... Stay tuned :) |
done in 5b937f0 |
Sounds interesting! I don't know if we're talking the exact same topic, but I was needing to play with the mgos_pwm _rgb code to implement hardware fading and reliable led blinking. Ended up doing the latter with
Interestingly before pinning to core 1 I was able to see the task getting sent to 1 or 2! |
Yes, that is an expected behaviour. FreeRTOS will run tasks on both cores as needed, when it is not disabled. |
Mongoose OS only currently supports running ESP32 on single core, basically leaving the second core completely unused.
Yes i've seen the thread at:
https://forum.mongoose-os.com/index.php?p=/discussion/comment/2356/#Comment_2356
And ticket #253
I opened this issue as technically this is an issue that only single core devices are supported, and multi-core devices that are supported ... only a single core is supported on them.
By closing ticket #253 does that mean that Cesanta has no plans for ever supporting multi-core devices?
While I understand that currently MOS is not thread safe, eventually over time one would assume that new devices will become available, many of them will have multi-core ... and even if it's not an ESP32, i'm sure you guys will want to add new devices ... but does that mean that even though support may be added, that they will be crippled by only supporting a single core?