kernel: threads: assign index no. to dynamically created threads

Kernel threads created at build time have unique indexes to map them
into various bitarrays. This patch extends these indexes to
dynamically created threads where the associated  kernel objects are
allocated at runtime.

Fixes: #9081

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
Daniel Leung 2018-08-08 11:23:16 -07:00 committed by Andrew Boie
commit e58b65427e
3 changed files with 114 additions and 0 deletions

View file

@ -25,6 +25,13 @@
{
*(".kobject_data.data*")
#ifndef LINKER_PASS2
#ifdef CONFIG_DYNAMIC_OBJECTS
PROVIDE(_thread_idx_map = .);
. += CONFIG_MAX_THREAD_BYTES;
#endif
#endif
/* This is also unpredictable in size, and has the same constraints.
* On XIP systems this will get put at the very end of ROM.
*/

View file

@ -20,6 +20,12 @@
#define MAX_THREAD_BITS (CONFIG_MAX_THREAD_BYTES * 8)
#ifdef CONFIG_DYNAMIC_OBJECTS
extern u8_t _thread_idx_map[CONFIG_MAX_THREAD_BYTES];
#endif
static void clear_perms_cb(struct _k_object *ko, void *ctx_ptr);
const char *otype_to_str(enum k_objects otype)
{
/* -fdata-sections doesn't work right except in very very recent
@ -123,10 +129,74 @@ static struct dyn_obj *dyn_object_find(void *obj)
return ret;
}
/**
* @internal
*
* @brief Allocate a new thread index for a new thread.
*
* This finds an unused thread index that can be assigned to a new
* thread. If too many threads have been allocated, the kernel will
* run out of indexes and this function will fail.
*
* Note that if an unused index is found, that index will be marked as
* used after return of this function.
*
* @param tidx The new thread index if successful
*
* @return 1 if successful, 0 if failed
**/
static int _thread_idx_alloc(u32_t *tidx)
{
int i;
int idx;
int base;
base = 0;
for (i = 0; i < CONFIG_MAX_THREAD_BYTES; i++) {
idx = find_lsb_set(_thread_idx_map[i]);
if (idx) {
*tidx = base + (idx - 1);
sys_bitfield_clear_bit((mem_addr_t)_thread_idx_map,
*tidx);
/* Clear permission from all objects */
_k_object_wordlist_foreach(clear_perms_cb,
(void *)*tidx);
return 1;
}
base += 8;
}
return 0;
}
/**
* @internal
*
* @brief Free a thread index.
*
* This frees a thread index so it can be used by another
* thread.
*
* @param tidx The thread index to be freed
**/
static void _thread_idx_free(u32_t tidx)
{
/* To prevent leaked permission when index is recycled */
_k_object_wordlist_foreach(clear_perms_cb, (void *)tidx);
sys_bitfield_set_bit((mem_addr_t)_thread_idx_map, tidx);
}
void *_impl_k_object_alloc(enum k_objects otype)
{
struct dyn_obj *dyn_obj;
int key;
u32_t tidx;
/* Stacks are not supported, we don't yet have mem pool APIs
* to request memory that is aligned
@ -146,6 +216,16 @@ void *_impl_k_object_alloc(enum k_objects otype)
dyn_obj->kobj.flags = K_OBJ_FLAG_ALLOC;
memset(dyn_obj->kobj.perms, 0, CONFIG_MAX_THREAD_BYTES);
/* Need to grab a new thread index for k_thread */
if (otype == K_OBJ_THREAD) {
if (!_thread_idx_alloc(&tidx)) {
k_free(dyn_obj);
return NULL;
}
dyn_obj->kobj.data = tidx;
}
/* The allocating thread implicitly gets permission on kernel objects
* that it allocates
*/
@ -174,6 +254,10 @@ void k_object_free(void *obj)
if (dyn_obj) {
rb_remove(&obj_rb_tree, &dyn_obj->node);
sys_dlist_remove(&dyn_obj->obj_list);
if (dyn_obj->kobj.type == K_OBJ_THREAD) {
_thread_idx_free(dyn_obj->kobj.data);
}
}
irq_unlock(key);

View file

@ -6,6 +6,7 @@
import sys
import argparse
import math
import pprint
import os
import struct
@ -98,6 +99,14 @@ void _k_object_wordlist_foreach(_wordlist_cb_func_t func, void *context)
def write_gperf_table(fp, eh, objs, static_begin, static_end):
fp.write(header)
# Setup variables for mapping thread indexes
syms = eh.get_symbols()
thread_max_bytes = syms["CONFIG_MAX_THREAD_BYTES"]
thread_idx_map = {}
for i in range(0, thread_max_bytes):
thread_idx_map[i] = 0xFF
for obj_addr, ko in objs.items():
obj_type = ko.type_name
# pre-initialized objects fall within this memory range, they are
@ -117,8 +126,22 @@ def write_gperf_table(fp, eh, objs, static_begin, static_end):
"K_OBJ_FLAG_INITIALIZED" if initialized else "0",
ko.data))
if obj_type == "K_OBJ_THREAD":
idx = math.floor(ko.data / 8)
bit = ko.data % 8
thread_idx_map[idx] = thread_idx_map[idx] & ~(2**bit)
fp.write(footer)
# Generate the array of already mapped thread indexes
fp.write('\n')
fp.write('u8_t _thread_idx_map[%d] = {' % (thread_max_bytes))
for i in range(0, thread_max_bytes):
fp.write(' 0x%x, ' % (thread_idx_map[i]))
fp.write('};\n')
driver_macro_tpl = """
#define Z_SYSCALL_DRIVER_%(driver_upper)s(ptr, op) Z_SYSCALL_DRIVER_GEN(ptr, op, %(driver_lower)s, %(driver_upper)s)