From f2734ab02267ff942ba4af53592793347ed7307f Mon Sep 17 00:00:00 2001 From: Andrew Boie Date: Wed, 11 Mar 2020 06:37:42 -0700 Subject: [PATCH] kernel: use a union for kobject data values Rather than stuffing various values in a uintptr_t based on type using casts, use a union for this instead. No functional difference, but the semantics of the data member are now much clearer to the casual observer since it is now formally defined by this union. Signed-off-by: Andrew Boie --- doc/reference/usermode/kernelobjects.rst | 5 ++--- include/kernel.h | 21 ++++++++++++++++++++- kernel/futex.c | 2 +- kernel/thread.c | 6 +++--- kernel/userspace.c | 8 ++++---- lib/os/mutex.c | 2 +- scripts/elf_helper.py | 4 ++-- scripts/gen_kobject_list.py | 14 +++++++++++++- 8 files changed, 46 insertions(+), 16 deletions(-) diff --git a/doc/reference/usermode/kernelobjects.rst b/doc/reference/usermode/kernelobjects.rst index f493d32ac4e..c12145042d9 100644 --- a/doc/reference/usermode/kernelobjects.rst +++ b/doc/reference/usermode/kernelobjects.rst @@ -128,9 +128,8 @@ includes: instance of :cpp:enum:`k_objects`. * A set of flags for that object. This is currently used to track initialization state and whether an object is public or not. -* An extra data field. This is currently used for thread stack objects - to denote how large the stack is, and for thread objects to indicate - the thread's index in kernel object permission bitfields. +* An extra data field. The semantics of this field vary by object type, see + the definition of :c:type:`union z_object_data`. Dynamic objects allocated at runtime are tracked in a runtime red/black tree which is used in parallel to the gperf table when validating object pointers. diff --git a/include/kernel.h b/include/kernel.h index 9d1d4e076e4..18758bfbd3b 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -135,6 +135,7 @@ struct k_poll_signal; struct k_mem_domain; struct k_mem_partition; struct k_futex; +struct z_futex_data; /** * @brief Kernel Object Types @@ -165,6 +166,24 @@ enum k_objects { */ #ifdef CONFIG_USERSPACE +/* Object extra data. Only some objects use this, determined by object type */ +union z_object_data { + /* Backing mutex for K_OBJ_SYS_MUTEX */ + struct k_mutex *mutex; + + /* Numerical thread ID for K_OBJ_THREAD */ + unsigned int thread_id; + + /* Stack buffer size for K_OBJ__THREAD_STACK_ELEMENT */ + size_t stack_size; + + /* Futex wait queue and spinlock for K_OBJ_FUTEX */ + struct z_futex_data *futex_data; + + /* All other objects */ + int unused; +}; + /* Table generated by gperf, these objects are retrieved via * z_object_find() */ struct _k_object { @@ -172,7 +191,7 @@ struct _k_object { u8_t perms[CONFIG_MAX_THREAD_BYTES]; u8_t type; u8_t flags; - uintptr_t data; + union z_object_data data; } __packed __aligned(4); struct _k_object_assignment { diff --git a/kernel/futex.c b/kernel/futex.c index c31fb0892ac..8507cd2d014 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -21,7 +21,7 @@ static struct z_futex_data *k_futex_find_data(struct k_futex *futex) return NULL; } - return (struct z_futex_data *)obj->data; + return obj->data.futex_data; } int z_impl_k_futex_wake(struct k_futex *futex, bool wake_all) diff --git a/kernel/thread.c b/kernel/thread.c index 751cc392e81..67c55309c69 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -664,9 +664,9 @@ k_tid_t z_vrfy_k_thread_create(struct k_thread *new_thread, /* Testing less-than-or-equal since additional room may have been * allocated for alignment constraints */ - Z_OOPS(Z_SYSCALL_VERIFY_MSG(total_size <= stack_object->data, - "stack size %zu is too big, max is %lu", - total_size, stack_object->data)); + Z_OOPS(Z_SYSCALL_VERIFY_MSG(total_size <= stack_object->data.stack_size, + "stack size %zu is too big, max is %zu", + total_size, stack_object->data.stack_size)); /* User threads may only create other user threads and they can't * be marked as essential diff --git a/kernel/userspace.c b/kernel/userspace.c index 240f4fbea45..d27781d2108 100644 --- a/kernel/userspace.c +++ b/kernel/userspace.c @@ -263,7 +263,7 @@ void *z_impl_k_object_alloc(enum k_objects otype) return NULL; } - dyn_obj->kobj.data = tidx; + dyn_obj->kobj.data.thread_id = tidx; } /* The allocating thread implicitly gets permission on kernel objects @@ -297,7 +297,7 @@ void k_object_free(void *obj) sys_dlist_remove(&dyn_obj->obj_list); if (dyn_obj->kobj.type == K_OBJ_THREAD) { - thread_idx_free(dyn_obj->kobj.data); + thread_idx_free(dyn_obj->kobj.data.thread_id); } } k_spin_unlock(&objfree_lock, key); @@ -340,7 +340,7 @@ void z_object_wordlist_foreach(_wordlist_cb_func_t func, void *context) } #endif /* CONFIG_DYNAMIC_OBJECTS */ -static int thread_index_get(struct k_thread *thread) +static unsigned int thread_index_get(struct k_thread *thread) { struct _k_object *ko; @@ -350,7 +350,7 @@ static int thread_index_get(struct k_thread *thread) return -1; } - return ko->data; + return ko->data.thread_id; } static void unref_check(struct _k_object *ko, uintptr_t index) diff --git a/lib/os/mutex.c b/lib/os/mutex.c index 84f207074ff..0e952e8e940 100644 --- a/lib/os/mutex.c +++ b/lib/os/mutex.c @@ -18,7 +18,7 @@ static struct k_mutex *get_k_mutex(struct sys_mutex *mutex) return NULL; } - return (struct k_mutex *)obj->data; + return obj->data.mutex; } static bool check_sys_mutex_addr(struct sys_mutex *addr) diff --git a/scripts/elf_helper.py b/scripts/elf_helper.py index 44b53162e2e..f5842d2f50f 100644 --- a/scripts/elf_helper.py +++ b/scripts/elf_helper.py @@ -71,10 +71,10 @@ class KobjectInstance: self.data = thread_counter thread_counter = thread_counter + 1 elif self.type_obj.name == "sys_mutex": - self.data = "(uintptr_t)(&kernel_mutexes[%d])" % sys_mutex_counter + self.data = "&kernel_mutexes[%d]" % sys_mutex_counter sys_mutex_counter += 1 elif self.type_obj.name == "k_futex": - self.data = "(uintptr_t)(&futex_data[%d])" % futex_counter + self.data = "&futex_data[%d]" % futex_counter futex_counter += 1 else: self.data = 0 diff --git a/scripts/gen_kobject_list.py b/scripts/gen_kobject_list.py index e565835844a..18954fa539d 100755 --- a/scripts/gen_kobject_list.py +++ b/scripts/gen_kobject_list.py @@ -144,6 +144,12 @@ void z_object_wordlist_foreach(_wordlist_cb_func_t func, void *context) #endif """ +metadata_names = { + "K_OBJ_THREAD" : "thread_id", + "K_OBJ__THREAD_STACK_ELEMENT" : "stack_size", + "K_OBJ_SYS_MUTEX" : "mutex", + "K_OBJ_FUTEX" : "futex_data" +} def write_gperf_table(fp, eh, objs, static_begin, static_end): fp.write(header) @@ -204,7 +210,13 @@ def write_gperf_table(fp, eh, objs, static_begin, static_end): if is_driver: flags += " | K_OBJ_FLAG_DRIVER" - fp.write("\", {}, %s, %s, %s\n" % (obj_type, flags, str(ko.data))) + if ko.type_name in metadata_names: + tname = metadata_names[ko.type_name] + else: + tname = "unused" + + fp.write("\", {}, %s, %s, { .%s = %s }\n" % (obj_type, flags, + tname, str(ko.data))) if obj_type == "K_OBJ_THREAD": idx = math.floor(ko.data / 8)