Skip to content
Permalink
Browse files

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>
  • Loading branch information...
dcpleung authored and andrewboie committed Aug 8, 2018
1 parent cd3e5b5 commit e58b65427efdf57cf0aca547d603844436168872
Showing with 114 additions and 0 deletions.
  1. +7 −0 include/linker/kobject.ld
  2. +84 −0 kernel/userspace.c
  3. +23 −0 scripts/gen_kobject_list.py
@@ -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 @@
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)

0 comments on commit e58b654

Please sign in to comment.
You can’t perform that action at this time.