microkernel: add task pointer list

Due to similar padding issue as pipe, the list of task object
may not be used directly. As mentioned before, some compiler/linker
may pad the large struct. For example, compiling under gcc and
march=i686 pads the struct to 32-byte alignment (march=atom to
64-byte alignment). This causes issue with sizeof() and pointer
arithmetic because they have no idea about the padding.
When the stars align in a certain way, these task structs may be
corrupted. So add a task pointer list and use it for task
manipulation. The task list remains as it is beneficial to group
them together to take advantage of cache locality.

Change-Id: I0e86bfe05742040f4540d7854c1ac14e76162776
Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
Daniel Leung 2015-09-16 09:35:22 -07:00 committed by Anas Nashif
commit 8253b90cfc
5 changed files with 37 additions and 6 deletions

View file

@ -203,6 +203,16 @@ SECTIONS
_k_task_list_end = .; _k_task_list_end = .;
} GROUP_LINK_IN(RAMABLE_REGION) } GROUP_LINK_IN(RAMABLE_REGION)
SECTION_PROLOGUE (_k_task_ptr, (OPTIONAL),)
{
_k_task_ptr_start = .;
*(._k_task_ptr.public.*)
*(._k_task_ptr.private.*)
*(._k_task_ptr.idle.*)
KEEP(*(SORT_BY_NAME("._k_task_ptr*")))
_k_task_ptr_end = .;
} GROUP_LINK_IN(RAMABLE_REGION)
SECTION_PROLOGUE (_k_pipe_ptr, (OPTIONAL),) SECTION_PROLOGUE (_k_pipe_ptr, (OPTIONAL),)
{ {
_k_pipe_ptr_start = .; _k_pipe_ptr_start = .;

View file

@ -174,6 +174,16 @@ SECTIONS
_k_task_list_end = .; _k_task_list_end = .;
} GROUP_LINK_IN(RAM) } GROUP_LINK_IN(RAM)
SECTION_PROLOGUE (_k_task_ptr, (OPTIONAL),)
{
_k_task_ptr_start = .;
*(._k_task_ptr.public.*)
*(._k_task_ptr.private.*)
*(._k_task_ptr.idle.*)
KEEP(*(SORT_BY_NAME("._k_task_ptr*")))
_k_task_ptr_end = .;
} GROUP_LINK_IN(RAM)
SECTION_PROLOGUE (_k_pipe_ptr, (OPTIONAL),) SECTION_PROLOGUE (_k_pipe_ptr, (OPTIONAL),)
{ {
_k_pipe_ptr_start = .; _k_pipe_ptr_start = .;

View file

@ -338,7 +338,9 @@ extern void task_group_leave(uint32_t groups);
(ktask_t)&_k_task_obj_##name, \ (ktask_t)&_k_task_obj_##name, \
priority, 0x00000001, groups, \ priority, 0x00000001, groups, \
entry, &__stack_##name[0], stack_size, NULL); \ entry, &__stack_##name[0], stack_size, NULL); \
const ktask_t name = (ktask_t)&_k_task_obj_##name; const ktask_t name \
__section(_k_task_ptr, private, task) = \
(ktask_t)&_k_task_obj_##name;
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -42,8 +42,8 @@
#include <nano_private.h> #include <nano_private.h>
#include <start_task_arch.h> #include <start_task_arch.h>
extern struct k_task _k_task_list_start[]; extern ktask_t _k_task_ptr_start[];
extern struct k_task _k_task_list_end[]; extern ktask_t _k_task_ptr_end[];
ktask_t task_id_get(void) ktask_t task_id_get(void)
@ -342,6 +342,7 @@ void _k_task_group_op(struct k_args *A)
ktask_group_t grp = A->args.g1.group; ktask_group_t grp = A->args.g1.group;
int opt = A->args.g1.opt; int opt = A->args.g1.opt;
struct k_task *X; struct k_task *X;
ktask_t *task_id;
#ifdef CONFIG_TASK_DEBUG #ifdef CONFIG_TASK_DEBUG
if (opt == TASK_GROUP_BLOCK) if (opt == TASK_GROUP_BLOCK)
@ -350,7 +351,9 @@ void _k_task_group_op(struct k_args *A)
_k_debug_halt = 0; _k_debug_halt = 0;
#endif #endif
for (X = _k_task_list_start; X < _k_task_list_end; X++) { for (task_id = _k_task_ptr_start; task_id < _k_task_ptr_end;
task_id++) {
X = (struct k_task *)(*task_id);
if (X->group & grp) { if (X->group & grp) {
switch (opt) { switch (opt) {
case TASK_GROUP_START: case TASK_GROUP_START:

View file

@ -405,7 +405,10 @@ def kernel_main_c_tasks():
" {NULL, NULL, %d, (ktask_t)&%s,\n" % (prio, obj_name) + " {NULL, NULL, %d, (ktask_t)&%s,\n" % (prio, obj_name) +
" 0x00000001, %#010x,\n" % (group_bitmask) + " 0x00000001, %#010x,\n" % (group_bitmask) +
" %s, %s, %d,\n" % (entry, stack, size) + " %s, %s, %d,\n" % (entry, stack, size) +
" (taskabortfunction)NULL, NULL};\n") " (taskabortfunction)NULL, NULL};\n" +
"ktask_t _k_task_ptr_%s " % (name) +
" __section(_k_task_ptr, public, task) = " +
" (ktask_t)&%s;\n" % (obj_name))
kernel_main_c_out( kernel_main_c_out(
"struct k_task _k_task_idle " + "struct k_task _k_task_idle " +
@ -414,7 +417,10 @@ def kernel_main_c_tasks():
" 0x00000000, 0x00000000,\n" + " 0x00000000, 0x00000000,\n" +
" (taskstartfunction)NULL, main_task_stack,\n" " (taskstartfunction)NULL, main_task_stack,\n"
" CONFIG_MAIN_STACK_SIZE,\n" + " CONFIG_MAIN_STACK_SIZE,\n" +
" (taskabortfunction)NULL, NULL};\n") " (taskabortfunction)NULL, NULL};\n" +
"ktask_t _k_task_ptr_idle " +
" __section(_k_task_ptr, idle, task) = " +
" (ktask_t)&_k_task_idle;\n")
# currently scheduled task (idle task) # currently scheduled task (idle task)