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:
parent
cd3e5b561d
commit
e58b65427e
3 changed files with 114 additions and 0 deletions
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue