Under certain conditions, it may be necessary to create a kernel thread whose stack likes in some custom memory. This page provides and example of how that would be done:
Here is the body of some function. It expects to have the following inputs:
taskname: The name of the task to be startedstacksize: The size of the custom stackpriority: The priority of the task to be startedentry_point: The entry point of the task to be startedargv: An optional array of argument strings passed to the task/* Allocate a TCB for the new task. kmm_zalloc() is used so
* that all fields of the new TCB will be zeroed.
*/ tcb = (FAR struct task_tcb_s *)kmm_zalloc(sizeof(struct task_tcb_s)); if (tcb == NULL) { return -ENOMEM; }
/* Indicate (1) that this is a kernel thread and that (2) a custom
* stack will be used.
*/
tcb->flags = TCB_FLAG_TTYPE_KERNEL | TCB_FLAG_CUSTOM_STACK; /* Allocate the custom stack for the new task. * * Do whatever it takes to get a reference to the custom stack.
* Here custom_alloc() is used as a placeholder for whatever
* that may be. */ stack = (FAR uint32_t *)custom_alloc(stacksize); if (stack == NULL) { kmm_free(tcb); return -ENOMEM; } /* Initialize the TCB. This will initialize all remaining
* fields of the TCB, associate the stack to the TCB, allocate
* any additional resources needed by the task, and place the
* TCB in a list of inactive tasks.
*/ ret = task_init((FAR struct tcb_s *)tcb, progname, priority, stack, stacksize, entry_point, argv); if (ret < 0) {kmm_free(tcb); custom_free(stack);
return ret;
}
/* Then activate the task at the provided priority */
ret = task_activate((FAR struct tcb_s *)tcb);
if (ret < 0)
{
/* nxtask_unit() will undo all of the operations of nxtask_init().
* It also has the side-effect of freeing the TCB which it assumes
* was allocated with one of the kmm_malloc()functions.
*/
nxtask_uninit(tcb);
custom_free(stack);
return ret;
}
return OK;
The effect of the TCB_FLAG_CUSTOM_STACK flag is the the OS will not attempt to free the custom stack memory if the task exits, crashes, or is killed. Does this matter in your implementation? Could this result in some kind of memory leak? If any kind of clean-up is required by your application to free the custom stack memory, you will probably want to use an on_exit() or atexit() function to get a callback when the task is terminated.