Re: garbage collector + stack of startup task
Posted: Wed Sep 12, 2018 10:40 pm
Lol :p. I enjoy this.
Please see the new forum at
https://forum.micropython.org/
Lol :p. I enjoy this.
I have an idea how to help you debug your gc issuesBramPeeters wrote: ↑Wed Sep 12, 2018 10:57 pmI tried that (enabling verbose mode in mpportconfig I assume you mean) .
That is when i saw that if i moved the stack onto the heap there were only +- 5 sweep (=free) messages (and it kept working) versus +-20 sweeps (and it crashed after suspend/resuming) if it was still in static memory during the first call of gc.collect() (if i call it every 100ms).
So that triggered my whole 'the contents of the static stack seem to be ignored' idea and when i looked at the code i thought i found the explanation ('if you are a hammer everything looks like a nail' - wise ).
So I will have to look again into why these sweep results are so different between the 2 scenarios, but it is a good starting point. And in the meantime I've learned a lot more about the GC . And optimized the external memory parameters so that it is now much faster which was needed with my initial stack located on the heap in external sram:).
Post code.BramPeeters wrote: ↑Wed Sep 12, 2018 10:57 pm
So I will have to look again into why these sweep results are so different between the 2 scenarios, but it is a good starting point. And in the meantime I've learned a lot more about the GC .
It's only "scanned" i.e. treated as a root pointer if you tell the gc it's a root-pointer area OR something else points into it.
dhylands wrote: ↑Thu Sep 13, 2018 4:29 pmIf the stack is located in the heap, then the entire stack area will be scanned, including the currently unused portion of the stack, and its quite possible that old stale pointers may be holding onto memory.
When the stack is scanned "as a stack", then it will only look from the current stack pointer thru to the top of the stack (so it only scans the currently used portion of the stack).
I haven't looked into how the stacks are scanned when threading is being used, but I would have thought it would need to know the stack pointer for each thread's stack and only scan the active portion of the stack.
Code: Select all
void mp_thread_gc_others(void) {
mp_thread_mutex_lock(&thread_mutex, 1);
for (thread_t *th = thread; th != NULL; th = th->next) {
gc_collect_root((void**)&th, 1);
gc_collect_root(&th->arg, 1); // probably not needed
if (th->id == xTaskGetCurrentTaskHandle()) {
continue;
}
if (!th->ready) {
continue;
}
gc_collect_root(th->stack, th->stack_len); // probably not needed
}
mp_thread_mutex_unlock(&thread_mutex);
}
Well if your stack is allocated on the heap and you don't have a root-pointer (or some other object) pointing to it, then it will be released and your stack area will get used for regular allocations which will definitely crash things.
The feature I proposed would help debugging these type of issuesdhylands wrote:Well if your stack is allocated on the heap and you don't have a root-pointer (or some other object) pointing to it, then it will be released and your stack area will get used for regular allocations which will definitely crash things.
So my assumption was that if the stack is allocated on the heap, then you better have something pointing to it or you're going to be in a world of hurt when it gets used for something else
Code: Select all
void mp_thread_init(void)
{
mp_thread_mutex_init(&thread_mutex);
mp_thread_set_state(&mp_state_ctx.thread);
// create first entry in linked list of all threads
thread = &thread_entry0;
thread->id = xTaskGetCurrentTaskHandle();
thread->ready = 1;
thread->arg = NULL;
thread->stack = mpTaskStack;
thread->stack_len = MICROPY_TASK_STACK_LEN;
thread->next = NULL;
}
Code: Select all
void mp_thread_gc_others(void) {
mp_thread_mutex_lock(&thread_mutex, 1);
for (thread_t *th = thread; th != NULL; th = th->next) {
gc_collect_root((void**)&th, 1);
gc_collect_root(&th->arg, 1); // probably not needed
if (th->id == xTaskGetCurrentTaskHandle()) {
continue;
}
if (!th->ready) {
continue;
}
gc_collect_root(th->stack, th->stack_len); // probably not needed
}
mp_thread_mutex_unlock(&thread_mutex);
}
Code: Select all
gc_collect_root((void**)sp, ((uint32_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t));