userspace: improve dynamic object allocation
We now have a low-level function z_dynamic_object_create() which is not a system call and is used for installing kernel objects that are not supported by k_object_alloc(). Checking for valid object type enumeration values moved completely to the implementation function. A few debug messages and comments were improved. Futexes and sys_mutexes are now properly excluded from dynamic generation. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
parent
9f63a0a0a0
commit
be919d3bf7
4 changed files with 100 additions and 35 deletions
|
@ -352,6 +352,27 @@ void k_object_access_all_grant(void *object);
|
|||
__syscall void *k_object_alloc(enum k_objects otype);
|
||||
|
||||
#ifdef CONFIG_DYNAMIC_OBJECTS
|
||||
/**
|
||||
* Allocate memory and install as a generic kernel object
|
||||
*
|
||||
* This is a low-level function to allocate some memory, and register that
|
||||
* allocated memory in the kernel object lookup tables with type K_OBJ_ANY.
|
||||
* Initialization state and thread permissions will be cleared. The
|
||||
* returned z_object's data value will be uninitialized.
|
||||
*
|
||||
* Most users will want to use k_object_alloc() instead.
|
||||
*
|
||||
* Memory allocated will be drawn from the calling thread's reasource pool
|
||||
* and may be freed later by passing the actual object pointer (found
|
||||
* in the returned z_object's 'name' member) to k_object_free().
|
||||
*
|
||||
* @param size Size of the allocated object
|
||||
* @return NULL on insufficient memory
|
||||
* @return A pointer to the associated z_object that is installed in the
|
||||
* kernel object tables
|
||||
*/
|
||||
struct z_object *z_dynamic_object_create(size_t size);
|
||||
|
||||
/**
|
||||
* Free a kernel object previously allocated with k_object_alloc()
|
||||
*
|
||||
|
@ -370,6 +391,14 @@ static inline void *z_impl_k_object_alloc(enum k_objects otype)
|
|||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct z_object *z_dynamic_object_create(size_t size)
|
||||
{
|
||||
ARG_UNUSED(size);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free an object
|
||||
*
|
||||
|
|
|
@ -72,6 +72,9 @@ const char *otype_to_str(enum k_objects otype)
|
|||
/* otype-to-str.h is generated automatically during build by
|
||||
* gen_kobject_list.py
|
||||
*/
|
||||
case K_OBJ_ANY:
|
||||
ret = "generic";
|
||||
break;
|
||||
#include <otype-to-str.h>
|
||||
default:
|
||||
ret = "?";
|
||||
|
@ -252,51 +255,81 @@ static void thread_idx_free(uintptr_t tidx)
|
|||
sys_bitfield_set_bit((mem_addr_t)_thread_idx_map, tidx);
|
||||
}
|
||||
|
||||
void *z_impl_k_object_alloc(enum k_objects otype)
|
||||
struct z_object *z_dynamic_object_create(size_t size)
|
||||
{
|
||||
struct dyn_obj *dyn_obj;
|
||||
uintptr_t tidx;
|
||||
|
||||
/* Stacks are not supported, we don't yet have mem pool APIs
|
||||
* to request memory that is aligned
|
||||
*/
|
||||
__ASSERT(otype > K_OBJ_ANY && otype < K_OBJ_LAST &&
|
||||
otype != K_OBJ_THREAD_STACK_ELEMENT,
|
||||
"bad object type requested");
|
||||
|
||||
dyn_obj = z_thread_malloc(sizeof(*dyn_obj) + obj_size_get(otype));
|
||||
dyn_obj = z_thread_malloc(sizeof(*dyn_obj) + size);
|
||||
if (dyn_obj == NULL) {
|
||||
LOG_WRN("could not allocate kernel object");
|
||||
LOG_ERR("could not allocate kernel object, out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dyn_obj->kobj.name = (char *)&dyn_obj->data;
|
||||
dyn_obj->kobj.type = otype;
|
||||
dyn_obj->kobj.flags = K_OBJ_FLAG_ALLOC;
|
||||
dyn_obj->kobj.name = &dyn_obj->data;
|
||||
dyn_obj->kobj.type = K_OBJ_ANY;
|
||||
dyn_obj->kobj.flags = 0;
|
||||
(void)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.thread_id = tidx;
|
||||
}
|
||||
|
||||
/* The allocating thread implicitly gets permission on kernel objects
|
||||
* that it allocates
|
||||
*/
|
||||
z_thread_perms_set(&dyn_obj->kobj, _current);
|
||||
|
||||
k_spinlock_key_t key = k_spin_lock(&lists_lock);
|
||||
|
||||
rb_insert(&obj_rb_tree, &dyn_obj->node);
|
||||
sys_dlist_append(&obj_list, &dyn_obj->obj_list);
|
||||
k_spin_unlock(&lists_lock, key);
|
||||
|
||||
return dyn_obj->kobj.name;
|
||||
return &dyn_obj->kobj;
|
||||
}
|
||||
|
||||
void *z_impl_k_object_alloc(enum k_objects otype)
|
||||
{
|
||||
struct z_object *zo;
|
||||
uintptr_t tidx;
|
||||
|
||||
if (otype <= K_OBJ_ANY || otype >= K_OBJ_LAST) {
|
||||
LOG_ERR("bad object type %d requested", otype);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (otype) {
|
||||
case K_OBJ_THREAD:
|
||||
if (!thread_idx_alloc(&tidx)) {
|
||||
LOG_ERR("out of free thread indexes");
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
/* The following are currently not allowed at all */
|
||||
case K_OBJ_FUTEX: /* Lives in user memory */
|
||||
case K_OBJ_SYS_MUTEX: /* Lives in user memory */
|
||||
case K_OBJ_THREAD_STACK_ELEMENT: /* No aligned allocator */
|
||||
case K_OBJ_NET_SOCKET: /* Indeterminate size */
|
||||
LOG_ERR("forbidden object type '%s' requested",
|
||||
otype_to_str(otype));
|
||||
return NULL;
|
||||
default:
|
||||
/* Remainder within bounds are permitted */
|
||||
break;
|
||||
}
|
||||
|
||||
zo = z_dynamic_object_create(obj_size_get(otype));
|
||||
if (zo == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
zo->type = otype;
|
||||
|
||||
if (otype == K_OBJ_THREAD) {
|
||||
zo->data.thread_id = tidx;
|
||||
}
|
||||
|
||||
/* The allocating thread implicitly gets permission on kernel objects
|
||||
* that it allocates
|
||||
*/
|
||||
z_thread_perms_set(zo, _current);
|
||||
|
||||
/* Activates reference counting logic for automatic disposal when
|
||||
* all permissions have been revoked
|
||||
*/
|
||||
zo->flags |= K_OBJ_FLAG_ALLOC;
|
||||
|
||||
return zo->name;
|
||||
}
|
||||
|
||||
void k_object_free(void *obj)
|
||||
|
@ -508,6 +541,12 @@ void z_dump_object_error(int retval, void *obj, struct z_object *ko,
|
|||
switch (retval) {
|
||||
case -EBADF:
|
||||
LOG_ERR("%p is not a valid %s", obj, otype_to_str(otype));
|
||||
if (ko == NULL) {
|
||||
LOG_ERR("address is not a known kernel object");
|
||||
} else {
|
||||
LOG_ERR("address is actually a %s",
|
||||
otype_to_str(ko->type));
|
||||
}
|
||||
break;
|
||||
case -EPERM:
|
||||
dump_permission_error(ko);
|
||||
|
|
|
@ -62,10 +62,6 @@ static inline void z_vrfy_k_object_release(void *object)
|
|||
|
||||
static inline void *z_vrfy_k_object_alloc(enum k_objects otype)
|
||||
{
|
||||
Z_OOPS(Z_SYSCALL_VERIFY_MSG(otype > K_OBJ_ANY && otype < K_OBJ_LAST &&
|
||||
otype != K_OBJ_THREAD_STACK_ELEMENT,
|
||||
"bad object type %d requested", otype));
|
||||
|
||||
return z_impl_k_object_alloc(otype);
|
||||
}
|
||||
#include <syscalls/k_object_alloc_mrsh.c>
|
||||
|
|
|
@ -79,7 +79,8 @@ from collections import OrderedDict
|
|||
# the object to be located in user-accessible memory.
|
||||
#
|
||||
# - The third items is a boolean indicating whether this item can be
|
||||
# dynamically allocated with k_object_alloc()
|
||||
# dynamically allocated with k_object_alloc(). Keep this in sync with
|
||||
# the switch statement in z_impl_k_object_alloc().
|
||||
#
|
||||
# Key names in all caps do not correspond to a specific data type but instead
|
||||
# indicate that objects of its type are of a family of compatible data
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue