Flush xnfree backlog after thread deletion in root context
PATCH 1/1 Flush xnfree backlog after thread deletion in root context
The lazy xnfree mechanism turned out to be too lazy: Just run some testsuite program and what /proc/xenomai/heap - it will not reach the level it has on freshly booted box.
The reason is that TCBs of threads that are released over the ROOT thread will only get purged after the next schedule-to-ROOT. And if there is no more Xenomai thread scheduling in the system, this won't happen. It can even leave your system useless if you ran into out-of-heap with allocating TCBs, and the remaining heap is now too small to start at least one thread again (happened to customer). Patch below fixes this by adding an xnfreesync to the related code path.
However, I wonder if we shouldn't better run all those deferred releases in Linux context with only O(1) critical path lengths. Why risking to pile up a large backlog of TCBs when releasing a lot of threads in a row? That may degrade system latency. What about pushing this into some VIRQ over the Linux domain, releasing the nklock once after each iteration?
Jan
ksrc/nucleus/pod.c +3 -0
@@ -1236,6 +1236,9 @@ void xnpod_delete_thread(xnthread_t *thrxnthread_cleanup_tcb (thread);xnarch_finalize_no_switch (xnthread_archtcb (thread)); + +if (xnthread_test_state (sched->runthread,XNROOT )) +xnfreesync (); } unlock_and_exit:
Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux
Quoted 8 lines · Jan Kiszka
@@ -1236,6 +1236,9 @@ void xnpod_delete_thread(xnthread_t *thr
xnthread_cleanup_tcb(thread); xnarch_finalize_no_switch(xnthread_archtcb(thread)); + + if (xnthread_test_state(sched->runthread, XNROOT)) + xnfreesync(); }
No, this does not look good. The point of deferring TCB freeing is that the TCB will be accessed shortly after it is freed.
IMHO, the right solution is to add a call to xnpod_schedule or even directly xnfreesyng in the right place (in skins code, after all threads have been freed)
Signature · 1 line
Gilles
Quoted 4 lines · Gilles Chanteperdrix
Quoted 3 lines · Jan Kiszka
@@ -1236,6 +1236,9 @@ void xnpod_delete_thread(xnthread_t *thr
xnthread_cleanup_tcb(thread);
Quoted 8 lines
Quoted 5 lines
xnarch_finalize_no_switch(xnthread_archtcb(thread)); + + if (xnthread_test_state(sched->runthread, XNROOT)) + xnfreesync(); }No, this does not look good. The point of deferring TCB freeing is that the TCB will be accessed shortly after it is freed.
By whom in this case? The thread was not active anymore. IIRC, the use-after-release issue was related to self-deletions.
Quoted 4 lines
IMHO, the right solution is to add a call to
xnpod_scheduleor even directly xnfreesyng in the right place (in skins code, after all threads have been freed)
Well, as I said, we should rather move all these syncs out of critical sections. So better avoid xnpod_schedule.
I need to think about this a bit more, I'm afraid. It is safe to delete the TCB once the terminating thread is scheduled away and its successor of about to leave (or left) xnpod_schedule, right?
Jan
Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux
Quoted 11 lines · Jan Kiszka
Quoted 10 lines · Gilles Chanteperdrix
Quoted 8 lines · Jan Kiszka
@@ -1236,6 +1236,9 @@ void xnpod_delete_thread(xnthread_t *thr
xnthread_cleanup_tcb(thread); xnarch_finalize_no_switch(xnthread_archtcb(thread)); + + if (xnthread_test_state(sched->runthread, XNROOT)) + xnfreesync(); }
Quoted 5 lines
Quoted 2 lines
No, this does not look good. The point of deferring TCB freeing is that the TCB will be accessed shortly after it is freed.
By whom in this case? The thread was not active anymore. IIRC, the use-after-release issue was related to self-deletions.
I do not remember the issue precisely, I know that it was related to thread deletion hooks. The XNARCH_WANT_UNLOCKED_CTXSW complicated the issue further.
Signature · 1 line
Gilles
Quoted 12 lines · Gilles Chanteperdrix
Quoted 11 lines · Jan Kiszka
Quoted 10 lines · Gilles Chanteperdrix
Quoted 8 lines · Jan Kiszka
@@ -1236,6 +1236,9 @@ void xnpod_delete_thread(xnthread_t *thr
xnthread_cleanup_tcb(thread); xnarch_finalize_no_switch(xnthread_archtcb(thread)); + + if (xnthread_test_state(sched->runthread, XNROOT)) + xnfreesync(); }
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
No, this does not look good. The point of deferring TCB freeing is that the TCB will be accessed shortly after it is freed.
By whom in this case? The thread was not active anymore. IIRC, the use-after-release issue was related to self-deletions.
I do not remember the issue precisely, I know that it was related to thread deletion hooks.
The point is that we have to run thread deletion hooks on behalf of the outgoing thread context; this is a strong requirement.
The XNARCH_WANT_UNLOCKED_CTXSW complicated the
Quoted 2 lines
issue further.
Signature · 1 line
Philippe.
Quoted 16 lines · Philippe Gerum
Quoted 15 lines · Gilles Chanteperdrix
Quoted 14 lines · Jan Kiszka
Quoted 12 lines · Gilles Chanteperdrix
Quoted 8 lines · Jan Kiszka
@@ -1236,6 +1236,9 @@ void xnpod_delete_thread(xnthread_t *thr
xnthread_cleanup_tcb(thread); xnarch_finalize_no_switch(xnthread_archtcb(thread)); + + if (xnthread_test_state(sched->runthread, XNROOT)) + xnfreesync(); }No, this does not look good. The point of deferring TCB freeing is that the TCB will be accessed shortly after it is freed.
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
By whom in this case? The thread was not active anymore. IIRC, the use-after-release issue was related to self-deletions.
I do not remember the issue precisely, I know that it was related to thread deletion hooks.
The point is that we have to run thread deletion hooks on behalf of the outgoing thread context; this is a strong requirement.
Yes, I remember.
Quoted 3 lines
The
XNARCH_WANT_UNLOCKED_CTXSWcomplicated theQuoted 1 line
issue further.
I now wonder when in this unlocked case do we schedule the tcb for deletion - should be _before_ the switch - and what then prevents that the tcb is flushed by some other CPU that happen to run xnfreesync while we are unlocked during that switch. Or does XNARCH_WANT_UNLOCKED_CTXSW imply !CONFIG_CMP?
Jan
Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux
Quoted 19 lines · Jan Kiszka
Quoted 18 lines · Philippe Gerum
Quoted 17 lines · Gilles Chanteperdrix
Quoted 16 lines · Jan Kiszka
Quoted 4 lines · Gilles Chanteperdrix
Quoted 3 lines · Jan Kiszka
@@ -1236,6 +1236,9 @@ void xnpod_delete_thread(xnthread_t *thr
xnthread_cleanup_tcb(thread);Quoted 8 lines
Quoted 5 lines
xnarch_finalize_no_switch(xnthread_archtcb(thread)); + + if (xnthread_test_state(sched->runthread, XNROOT)) + xnfreesync(); }No, this does not look good. The point of deferring TCB freeing is that the TCB will be accessed shortly after it is freed.
By whom in this case? The thread was not active anymore. IIRC, the use-after-release issue was related to self-deletions.
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
I do not remember the issue precisely, I know that it was related to thread deletion hooks.
The point is that we have to run thread deletion hooks on behalf of the outgoing thread context; this is a strong requirement.
Yes, I remember.
Ok. Now I remember. The point is that the tcb is scheduled for deletion by thread deletion hooks, and accessed shortly after by xnthread_cleanup_tcb and xnarch_finalize_no_switch. So basically, your initial patch looks Ok. However, you should add the same call to __xnpod_finalize_zombie.
Quoted 10 lines
Quoted 5 lines
The
XNARCH_WANT_UNLOCKED_CTXSWcomplicated theQuoted 1 line
issue further.
I now wonder when in this unlocked case do we schedule the tcb for deletion - should be _before_ the switch - and what then prevents that the tcb is flushed by some other CPU that happen to run xnfreesync while we are unlocked during that switch.
The XNSWLOCK bit.
Or does XNARCH_WANT_UNLOCKED_CTXSW
Quoted 1 line
imply !CONFIG_CMP?
No, it is supposed to work. The sched->zombie points to this zombie, which is finalized in xnpod_finish_unlocked_switch
Signature · 1 line
Gilles
Quoted 26 lines · Gilles Chanteperdrix
Quoted 25 lines · Jan Kiszka
Quoted 23 lines · Philippe Gerum
Quoted 12 lines · Gilles Chanteperdrix
Quoted 11 lines · Jan Kiszka
Quoted 10 lines · Gilles Chanteperdrix
Quoted 8 lines · Jan Kiszka
@@ -1236,6 +1236,9 @@ void xnpod_delete_thread(xnthread_t *thr
xnthread_cleanup_tcb(thread); xnarch_finalize_no_switch(xnthread_archtcb(thread)); + + if (xnthread_test_state(sched->runthread, XNROOT)) + xnfreesync(); }Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
No, this does not look good. The point of deferring TCB freeing is that the TCB will be accessed shortly after it is freed.
By whom in this case? The thread was not active anymore. IIRC, the use-after-release issue was related to self-deletions.
I do not remember the issue precisely, I know that it was related to thread deletion hooks.
The point is that we have to run thread deletion hooks on behalf of the outgoing thread context; this is a strong requirement.
Quoted 7 lines
Quoted 1 line
Yes, I remember.
Ok. Now I remember. The point is that the tcb is scheduled for deletion by thread deletion hooks, and accessed shortly after by
xnthread_cleanup_tcbandxnarch_finalize_no_switch. So basically, your initial patch looks Ok. However, you should add the same call to__xnpod_finalize_zombie.
That's for trunk only:
ksrc/nucleus/pod.c +6 -0
@@ -583,6 +583,9 @@ void __xnpod_finalize_zombie(xnsched_t *xnarch_finalize_no_switch (xnthread_archtcb (thread)); +if (xnthread_test_state (sched->runthread,XNROOT )) +xnfreesync (); + sched->zombie =NULL ; }
@@ -1231,6 +1234,9 @@ void xnpod_delete_thread(xnthread_t *thrxnthread_cleanup_tcb (thread);xnarch_finalize_no_switch (xnthread_archtcb (thread)); + +if (xnthread_test_state (sched->runthread,XNROOT )) +xnfreesync (); } unlock_and_exit:
Everyone fine when I apply both patches?
Quoted 11 lines
Quoted 10 lines
Quoted 5 lines
The
XNARCH_WANT_UNLOCKED_CTXSWcomplicated theQuoted 1 line
issue further.
I now wonder when in this unlocked case do we schedule the tcb for deletion - should be _before_ the switch - and what then prevents that the tcb is flushed by some other CPU that happen to run xnfreesync while we are unlocked during that switch.
Quoted 7 lines
The XNSWLOCK bit.
Or does
XNARCH_WANT_UNLOCKED_CTXSWQuoted 1 line
imply !CONFIG_CMP?
No, it is supposed to work. The
sched->zombiepoints to this zombie, which is finalized inxnpod_finish_unlocked_switch
OK. However, I would still prefer to get xnfreesync out of the critical paths. Is there anything which speaks against my VIRQ idea (except that it still has to be written :) )?
Jan
Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux
Quoted 8 lines · Jan Kiszka
Quoted 2 lines · Gilles Chanteperdrix
No, it is supposed to work. The
sched->zombiepoints to this zombie, which is finalized inxnpod_finish_unlocked_switchOK. However, I would still prefer to get xnfreesync out of the critical paths. Is there anything which speaks against my VIRQ idea (except that it still has to be written :) )?
Ok. Even though I am not sure how it works now, getting thread deletion to work with XNARCH_WANT_UNLOCKED_CTXSW was by far the hardest part of the work. I am not sure you can have the same control over what happens with a VIRQ.
Signature · 1 line
Gilles