Skip to content

Commit 5e002d9

Browse files
lvanassexiaoxiang781216
authored andcommitted
Doc: Migrate Kernel Threads with Custom Stacks
Migrate https://cwiki.apache.org/confluence/display/NUTTX/Kernel+Threads+with+Custom+Stacks to official wiki Signed-off-by: Ludovic Vanasse <[email protected]>
1 parent 9ee4566 commit 5e002d9

File tree

2 files changed

+135
-0
lines changed

2 files changed

+135
-0
lines changed

Documentation/guides/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,4 @@ Guides
4242
disabling_stackdumpdebug.rst
4343
include_files_board_h.rst
4444
specialstuff_in_nuttxheaderfiles.rst
45+
kernel_threads_with_custom_stacks.rst
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
=================================
2+
Kernel Threads with Custom Stacks
3+
=================================
4+
5+
.. warning::
6+
Migrated from:
7+
https://cwiki.apache.org/confluence/display/NUTTX/Kernel+Threads+with+Custom+Stacks
8+
9+
10+
Background
11+
==========
12+
13+
Under certain conditions, it may be necessary to create a kernel thread whose
14+
stack lives in some custom memory. This page provides and example of how that
15+
would be done:
16+
17+
Example
18+
=======
19+
20+
Here is the body of some function. It expects to have the following inputs:
21+
22+
1. ``taskname``: The name of the kernel thread to be started
23+
2. ``stacksize``: The size of the custom stack
24+
3. ``priority``: The priority of the kernel thread to be started
25+
4. ``entry_point``: The entry point of the kernel thread to be started
26+
5. ``argv``: An optional array of argument strings passed to the kernel thread
27+
28+
.. code-block:: c
29+
30+
/* Allocate a TCB for the new kernel thread. kmm_zalloc() is
31+
* used to that all fields of the new TCB will be zeroed.
32+
*/
33+
34+
tcb = (FAR struct task_tcb_s *)kmm_zalloc(sizeof(struct task_tcb_s));
35+
if (tcb == NULL)
36+
{
37+
return -ENOMEM;
38+
}
39+
40+
/* Indicate (1) that this is a kernel thread and that (2) a custom
41+
* stack will be used.
42+
*/
43+
44+
tcb->flags = TCB_FLAG_TTYPE_KERNEL | TCB_FLAG_CUSTOM_STACK;
45+
46+
/* Allocate the custom stack for the new kernel thread.
47+
*
48+
* Do whatever it takes to get a reference to the custom stack.
49+
* Here custom_alloc() is used as a placeholder for whatever
50+
* that may be.
51+
*/
52+
53+
stack = (FAR uint32_t *)custom_alloc(stacksize);
54+
if (stack == NULL)
55+
{
56+
kmm_free(tcb);
57+
return -ENOMEM;
58+
}
59+
60+
/* Initialize the TCB. This will initialize all remaining
61+
* fields of the TCB, associate the stack to the TCB, allocate
62+
* any additional resources needed by the kernel thread, and
63+
* place the TCB in a list of inactive tasks.
64+
*/
65+
66+
ret = task_init((FAR struct tcb_s *)tcb, progname, priority,
67+
stack, stacksize, entry_point, argv);
68+
if (ret < 0)
69+
{
70+
kmm_free(tcb);
71+
custom_free(stack);
72+
return ret;
73+
}
74+
75+
/* Then activate the kernel thread at the provided priority */
76+
77+
ret = task_activate((FAR struct tcb_s *)tcb);
78+
if (ret < 0)
79+
{
80+
/* nxtask_unit() will undo all of the operations of nxtask_init().
81+
* It also has the side-effect of freeing the TCB which it assumes
82+
* was allocated with one of the kmm_malloc()functions.
83+
*/
84+
85+
nxtask_uninit(tcb);
86+
custom_free(stack);
87+
return ret;
88+
}
89+
90+
return OK;
91+
92+
93+
Freeing the TCB
94+
===============
95+
96+
Prior to calling ``nxtask_init()``, the TCB can be freed using the kmm
97+
allocator, specifically the function ``kmm_free()``. However, after
98+
``nxtask_init()`` is called, additional resources will be associated with the
99+
TCB and you must then call ``nxtask_uninit()`` to free the TCB and all of its
100+
associated resources. ``kmm_free()`` will be used internally by
101+
``nxtask_uninit()`` to free the TCB. Note that in any event, the TCB must be
102+
allocated with one of the ``kmm_malloc()`` allocation functions.
103+
104+
You must never free the TCB after ``nxtask_activate()`` returns successfully.
105+
106+
Freeing the Custom Stack Memory
107+
===============================
108+
109+
The effect of the ``TCB_FLAG_CUSTOM_STACK`` flag is that the OS will not
110+
attempt to free the custom stack memory if the kernel thread exits, crashes,
111+
or is killed. Does this matter in your implementation? Could this result in
112+
some kind of memory leak? If any kind of clean-up is required by your
113+
application to free the custom stack memory, you will probably want to use
114+
an ``on_exit()`` or ``atexit()`` function to get a callback when the kernel
115+
thread is terminated.
116+
117+
If ``TCB_FLAG_CUSTOM_STACK`` were not set in the TCB flags, the OS would
118+
attempt to free the stack using ``kmm_free()`` which is probably not what you
119+
want in this case.
120+
121+
The actual logic is a slightly more complex and somewhat redundant:
122+
123+
* If ``TCB_FLAG_CUSTOM_STACK`` is set in the TCB flags, no attempt will be made
124+
to free the custom stack.
125+
* If ``TCB_FLAG_CUSTOM_STACK`` is not set in the TCB flags, the stack will be
126+
de-allocated for the kernel thread only if the stack lies in the kernel
127+
memory pool.
128+
129+
So in reality ``TCB_FLAG_CUSTOM_STACK`` may not be necessary. But the safest
130+
option is to include it in all cases where you do not expect the custom stack
131+
to be de-allocated.
132+
133+
You must not free the custom stack after ``nxtask_activate()`` returns
134+
successfully and until the kernel thread is terminated.

0 commit comments

Comments
 (0)