kernel: Add initial obj_core infrastructure
Adds the initial object core infrastructure. Signed-off-by: Peter Mitsis <peter.mitsis@intel.com>
This commit is contained in:
parent
eb1e5a161d
commit
55db86e512
5 changed files with 357 additions and 0 deletions
223
include/zephyr/kernel/obj_core.h
Normal file
223
include/zephyr/kernel/obj_core.h
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __KERNEL_OBJ_CORE_H__
|
||||||
|
#define __KERNEL_OBJ_CORE_H__
|
||||||
|
|
||||||
|
#include <zephyr/sys/slist.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup obj_core_apis Object Core APIs
|
||||||
|
* @ingroup kernel_apis
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert kernel object pointer into its object core pointer
|
||||||
|
*/
|
||||||
|
#define K_OBJ_CORE(kobj) (&((kobj)->obj_core))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate new object type IDs based on a 4 letter string
|
||||||
|
*/
|
||||||
|
#define K_OBJ_TYPE_ID_GEN(s) ((s[0] << 24) | (s[1] << 16) | (s[2] << 8) | (s[3]))
|
||||||
|
|
||||||
|
/* Known kernel object types */
|
||||||
|
|
||||||
|
/** Condition variable object type */
|
||||||
|
#define K_OBJ_TYPE_CONDVAR_ID K_OBJ_TYPE_ID_GEN("COND")
|
||||||
|
/** CPU object type */
|
||||||
|
#define K_OBJ_TYPE_CPU_ID K_OBJ_TYPE_ID_GEN("CPU_")
|
||||||
|
/** Event object type */
|
||||||
|
#define K_OBJ_TYPE_EVENT_ID K_OBJ_TYPE_ID_GEN("EVNT")
|
||||||
|
/** FIFO object type */
|
||||||
|
#define K_OBJ_TYPE_FIFO_ID K_OBJ_TYPE_ID_GEN("FIFO")
|
||||||
|
/** Kernel object type */
|
||||||
|
#define K_OBJ_TYPE_KERNEL_ID K_OBJ_TYPE_ID_GEN("KRNL")
|
||||||
|
/** LIFO object type */
|
||||||
|
#define K_OBJ_TYPE_LIFO_ID K_OBJ_TYPE_ID_GEN("LIFO")
|
||||||
|
/** Memory block object type */
|
||||||
|
#define K_OBJ_TYPE_MEM_BLOCK_ID K_OBJ_TYPE_ID_GEN("MBLK")
|
||||||
|
/** Mailbox object type */
|
||||||
|
#define K_OBJ_TYPE_MBOX_ID K_OBJ_TYPE_ID_GEN("MBOX")
|
||||||
|
/** Memory slab object type */
|
||||||
|
#define K_OBJ_TYPE_MEM_SLAB_ID K_OBJ_TYPE_ID_GEN("SLAB")
|
||||||
|
/** Message queue object type */
|
||||||
|
#define K_OBJ_TYPE_MSGQ_ID K_OBJ_TYPE_ID_GEN("MSGQ")
|
||||||
|
/** Mutex object type */
|
||||||
|
#define K_OBJ_TYPE_MUTEX_ID K_OBJ_TYPE_ID_GEN("MUTX")
|
||||||
|
/** Pipe object type */
|
||||||
|
#define K_OBJ_TYPE_PIPE_ID K_OBJ_TYPE_ID_GEN("PIPE")
|
||||||
|
/** Semaphore object type */
|
||||||
|
#define K_OBJ_TYPE_SEM_ID K_OBJ_TYPE_ID_GEN("SEM4")
|
||||||
|
/** Stack object type */
|
||||||
|
#define K_OBJ_TYPE_STACK_ID K_OBJ_TYPE_ID_GEN("STCK")
|
||||||
|
/** Thread object type */
|
||||||
|
#define K_OBJ_TYPE_THREAD_ID K_OBJ_TYPE_ID_GEN("THRD")
|
||||||
|
/** Timer object type */
|
||||||
|
#define K_OBJ_TYPE_TIMER_ID K_OBJ_TYPE_ID_GEN("TIMR")
|
||||||
|
|
||||||
|
struct k_obj_type;
|
||||||
|
struct k_obj_core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @cond INTERNAL_HIDDEN
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_OBJ_CORE
|
||||||
|
#define K_OBJ_CORE_INIT(_objp, _obj_type) \
|
||||||
|
extern struct k_obj_type _obj_type; \
|
||||||
|
k_obj_core_init(_objp, &_obj_type)
|
||||||
|
|
||||||
|
#define K_OBJ_CORE_LINK(objp) k_obj_core_link(objp)
|
||||||
|
#else
|
||||||
|
#define K_OBJ_CORE_INIT(objp, type) do { } while (0)
|
||||||
|
#define K_OBJ_CORE_LINK(objp) do { } while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* INTERNAL_HIDDEN @endcond
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tools may use this list as an entry point to identify all registered
|
||||||
|
* object types and the object cores linked to them.
|
||||||
|
*/
|
||||||
|
extern sys_slist_t z_obj_type_list;
|
||||||
|
|
||||||
|
/** Object type structure */
|
||||||
|
struct k_obj_type {
|
||||||
|
sys_snode_t node; /**< Node within list of object types */
|
||||||
|
sys_slist_t list; /**< List of objects of this object type */
|
||||||
|
uint32_t id; /**< Unique type ID */
|
||||||
|
size_t obj_core_offset; /**< Offset to obj_core field */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Object core structure */
|
||||||
|
struct k_obj_core {
|
||||||
|
sys_snode_t node; /**< Object node within object type's list */
|
||||||
|
struct k_obj_type *type; /**< Object type to which object belongs */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize a specific object type
|
||||||
|
*
|
||||||
|
* Initializes a specific object type and links it into the object core
|
||||||
|
* framework.
|
||||||
|
*
|
||||||
|
* @param type Pointer to the object type to initialize
|
||||||
|
* @param id A means to identify the object type
|
||||||
|
* @param off Offset of object core within the structure
|
||||||
|
*
|
||||||
|
* @retval Pointer to initialized object type
|
||||||
|
*/
|
||||||
|
struct k_obj_type *z_obj_type_init(struct k_obj_type *type,
|
||||||
|
uint32_t id, size_t off);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Find a specific object type by ID
|
||||||
|
*
|
||||||
|
* Given an object type ID, this function searches for the object type that
|
||||||
|
* is associated with the specified type ID @a type_id.
|
||||||
|
*
|
||||||
|
* @param type_id Type ID associated with object type
|
||||||
|
*
|
||||||
|
* @retval NULL if object type not found
|
||||||
|
* @retval Pointer to object type if found
|
||||||
|
*/
|
||||||
|
struct k_obj_type *k_obj_type_find(uint32_t type_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Walk the object type's list of object cores
|
||||||
|
*
|
||||||
|
* This function takes a global spinlock and walks the object type's list
|
||||||
|
* of object cores and invokes the callback function on each element while
|
||||||
|
* holding that lock. Although this will ensure that the list is not modified,
|
||||||
|
* one can expect a significant penalty in terms of performance and latency.
|
||||||
|
*
|
||||||
|
* The callback function shall either return non-zero to stop further walking,
|
||||||
|
* or it shall return 0 to continue walking.
|
||||||
|
*
|
||||||
|
* @param type Pointer to the object type
|
||||||
|
* @param func Callback to invoke on each object core of the object type
|
||||||
|
* @param data Custom data passed to the callback
|
||||||
|
*
|
||||||
|
* @retval non-zero if walk is terminated by the callback; otherwise 0
|
||||||
|
*/
|
||||||
|
int k_obj_type_walk_locked(struct k_obj_type *type,
|
||||||
|
int (*func)(struct k_obj_core *, void *),
|
||||||
|
void *data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Walk the object type's list of object cores
|
||||||
|
*
|
||||||
|
* This function is similar to k_obj_type_walk_locked() except that it walks
|
||||||
|
* the list without obtaining the global spinlock. No synchronization is
|
||||||
|
* provided here. Mutation of the list of objects while this function is in
|
||||||
|
* progress must be prevented at the application layer, otherwise
|
||||||
|
* undefined/unreliable behavior, corruption and/or crashes may result.
|
||||||
|
*
|
||||||
|
* The callback function shall either return non-zero to stop further walking,
|
||||||
|
* or it shall return 0 to continue walking.
|
||||||
|
*
|
||||||
|
* @param type Pointer to the object type
|
||||||
|
* @param func Callback to invoke on each object core of the object type
|
||||||
|
* @param data Custom data passed to the callback
|
||||||
|
*
|
||||||
|
* @retval non-zero if walk is terminated by the callback; otherwise 0
|
||||||
|
*/
|
||||||
|
int k_obj_type_walk_unlocked(struct k_obj_type *type,
|
||||||
|
int (*func)(struct k_obj_core *, void *),
|
||||||
|
void *data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize the core of the kernel object
|
||||||
|
*
|
||||||
|
* Initializing the kernel object core associates it with the specified
|
||||||
|
* kernel object type.
|
||||||
|
*
|
||||||
|
* @param obj_core Pointer to the kernel object to initialize
|
||||||
|
* @param type Pointer to the kernel object type
|
||||||
|
*/
|
||||||
|
void k_obj_core_init(struct k_obj_core *obj_core, struct k_obj_type *type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Link the kernel object to the kernel object type list
|
||||||
|
*
|
||||||
|
* A kernel object can be optionally linked into the kernel object type's
|
||||||
|
* list of objects. A kernel object must have been initialized before it
|
||||||
|
* can be linked. Linked kernel objects can be traversed and have information
|
||||||
|
* extracted from them by system tools.
|
||||||
|
*
|
||||||
|
* @param obj_core Pointer to the kernel object
|
||||||
|
*/
|
||||||
|
void k_obj_core_link(struct k_obj_core *obj_core);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Automatically link the kernel object after initializing it
|
||||||
|
*
|
||||||
|
* A useful wrapper to both initialize the core of the kernel object and
|
||||||
|
* automatically link it into the kernel object type's list of objects.
|
||||||
|
*
|
||||||
|
* @param obj_core Pointer to the kernel object to initialize
|
||||||
|
* @param type Pointer to the kernel object type
|
||||||
|
*/
|
||||||
|
void k_obj_core_init_and_link(struct k_obj_core *obj_core,
|
||||||
|
struct k_obj_type *type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unlink the kernel object from the kernel object type list
|
||||||
|
*
|
||||||
|
* Kernel objects can be unlinked from their respective kernel object type
|
||||||
|
* lists. If on a list, it must be done at the end of the kernel object's life
|
||||||
|
* cycle.
|
||||||
|
*
|
||||||
|
* @param obj_core Pointer to the kernel object
|
||||||
|
*/
|
||||||
|
void k_obj_core_unlink(struct k_obj_core *obj_core);
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
#endif /* __KERNEL_OBJ_CORE_H__ */
|
|
@ -29,6 +29,7 @@
|
||||||
#include <zephyr/sys/slist.h>
|
#include <zephyr/sys/slist.h>
|
||||||
#include <zephyr/sys/sflist.h>
|
#include <zephyr/sys/sflist.h>
|
||||||
#include <zephyr/sys/util.h>
|
#include <zephyr/sys/util.h>
|
||||||
|
#include <zephyr/kernel/obj_core.h>
|
||||||
#include <zephyr/kernel_structs.h>
|
#include <zephyr/kernel_structs.h>
|
||||||
#include <zephyr/kernel/mempool_heap.h>
|
#include <zephyr/kernel/mempool_heap.h>
|
||||||
#include <zephyr/kernel_version.h>
|
#include <zephyr/kernel_version.h>
|
||||||
|
|
|
@ -107,6 +107,7 @@ target_sources_ifdef(CONFIG_POLL kernel PRIVATE poll.c)
|
||||||
target_sources_ifdef(CONFIG_EVENTS kernel PRIVATE events.c)
|
target_sources_ifdef(CONFIG_EVENTS kernel PRIVATE events.c)
|
||||||
target_sources_ifdef(CONFIG_PIPES kernel PRIVATE pipes.c)
|
target_sources_ifdef(CONFIG_PIPES kernel PRIVATE pipes.c)
|
||||||
target_sources_ifdef(CONFIG_SCHED_THREAD_USAGE kernel PRIVATE usage.c)
|
target_sources_ifdef(CONFIG_SCHED_THREAD_USAGE kernel PRIVATE usage.c)
|
||||||
|
target_sources_ifdef(CONFIG_OBJ_CORE kernel PRIVATE obj_core.c)
|
||||||
|
|
||||||
if(${CONFIG_KERNEL_MEM_POOL})
|
if(${CONFIG_KERNEL_MEM_POOL})
|
||||||
target_sources(kernel PRIVATE mempool.c)
|
target_sources(kernel PRIVATE mempool.c)
|
||||||
|
|
|
@ -494,6 +494,19 @@ endif # THREAD_RUNTIME_STATS
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
menuconfig OBJ_CORE
|
||||||
|
bool "Object core framework"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
This option enables the object core framework. This will link
|
||||||
|
participating kernel objects and their respective types together
|
||||||
|
in a way that allows them to both have common information stored
|
||||||
|
together and for that information to be easily retrieved by
|
||||||
|
automated means.
|
||||||
|
|
||||||
|
if OBJ_CORE
|
||||||
|
endif # OBJ_CORE
|
||||||
|
|
||||||
menu "Work Queue Options"
|
menu "Work Queue Options"
|
||||||
config SYSTEM_WORKQUEUE_STACK_SIZE
|
config SYSTEM_WORKQUEUE_STACK_SIZE
|
||||||
int "System workqueue stack size"
|
int "System workqueue stack size"
|
||||||
|
|
119
kernel/obj_core.c
Normal file
119
kernel/obj_core.c
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/kernel/obj_core.h>
|
||||||
|
|
||||||
|
static struct k_spinlock lock;
|
||||||
|
|
||||||
|
sys_slist_t z_obj_type_list = SYS_SLIST_STATIC_INIT(&z_obj_type_list);
|
||||||
|
|
||||||
|
struct k_obj_type *z_obj_type_init(struct k_obj_type *type,
|
||||||
|
uint32_t id, size_t off)
|
||||||
|
{
|
||||||
|
sys_slist_init(&type->list);
|
||||||
|
sys_slist_append(&z_obj_type_list, &type->node);
|
||||||
|
type->id = id;
|
||||||
|
type->obj_core_offset = off;
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void k_obj_core_init(struct k_obj_core *obj_core, struct k_obj_type *type)
|
||||||
|
{
|
||||||
|
obj_core->node.next = NULL;
|
||||||
|
obj_core->type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void k_obj_core_link(struct k_obj_core *obj_core)
|
||||||
|
{
|
||||||
|
k_spinlock_key_t key = k_spin_lock(&lock);
|
||||||
|
|
||||||
|
sys_slist_append(&obj_core->type->list, &obj_core->node);
|
||||||
|
|
||||||
|
k_spin_unlock(&lock, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void k_obj_core_init_and_link(struct k_obj_core *obj_core,
|
||||||
|
struct k_obj_type *type)
|
||||||
|
{
|
||||||
|
k_obj_core_init(obj_core, type);
|
||||||
|
k_obj_core_link(obj_core);
|
||||||
|
}
|
||||||
|
|
||||||
|
void k_obj_core_unlink(struct k_obj_core *obj_core)
|
||||||
|
{
|
||||||
|
k_spinlock_key_t key = k_spin_lock(&lock);
|
||||||
|
|
||||||
|
sys_slist_find_and_remove(&obj_core->type->list, &obj_core->node);
|
||||||
|
|
||||||
|
k_spin_unlock(&lock, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct k_obj_type *k_obj_type_find(uint32_t type_id)
|
||||||
|
{
|
||||||
|
struct k_obj_type *type;
|
||||||
|
struct k_obj_type *rv = NULL;
|
||||||
|
sys_snode_t *node;
|
||||||
|
|
||||||
|
k_spinlock_key_t key = k_spin_lock(&lock);
|
||||||
|
|
||||||
|
SYS_SLIST_FOR_EACH_NODE(&z_obj_type_list, node) {
|
||||||
|
type = CONTAINER_OF(node, struct k_obj_type, node);
|
||||||
|
if (type->id == type_id) {
|
||||||
|
rv = type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
k_spin_unlock(&lock, key);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
int k_obj_type_walk_locked(struct k_obj_type *type,
|
||||||
|
int (*func)(struct k_obj_core *, void *),
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
k_spinlock_key_t key;
|
||||||
|
struct k_obj_core *obj_core;
|
||||||
|
sys_snode_t *node;
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
key = k_spin_lock(&lock);
|
||||||
|
|
||||||
|
SYS_SLIST_FOR_EACH_NODE(&type->list, node) {
|
||||||
|
obj_core = CONTAINER_OF(node, struct k_obj_core, node);
|
||||||
|
status = func(obj_core, data);
|
||||||
|
if (status != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
k_spin_unlock(&lock, key);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int k_obj_type_walk_unlocked(struct k_obj_type *type,
|
||||||
|
int (*func)(struct k_obj_core *, void *),
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct k_obj_core *obj_core;
|
||||||
|
sys_snode_t *node;
|
||||||
|
sys_snode_t *next;
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
SYS_SLIST_FOR_EACH_NODE_SAFE(&type->list, node, next) {
|
||||||
|
obj_core = CONTAINER_OF(node, struct k_obj_core, node);
|
||||||
|
status = func(obj_core, data);
|
||||||
|
if (status != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue