You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
327 lines
6.4 KiB
327 lines
6.4 KiB
/* |
|
* 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; |
|
#ifdef CONFIG_OBJ_CORE_STATS |
|
obj_core->stats = NULL; |
|
#endif /* CONFIG_OBJ_CORE_STATS */ |
|
} |
|
|
|
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; |
|
} |
|
|
|
#ifdef CONFIG_OBJ_CORE_STATS |
|
int k_obj_core_stats_register(struct k_obj_core *obj_core, void *stats, |
|
size_t stats_len) |
|
{ |
|
k_spinlock_key_t key = k_spin_lock(&lock); |
|
|
|
if (obj_core->type->stats_desc == NULL) { |
|
|
|
/* Object type not configured for statistics. */ |
|
|
|
k_spin_unlock(&lock, key); |
|
return -ENOTSUP; |
|
} |
|
|
|
if (obj_core->type->stats_desc->raw_size != stats_len) { |
|
|
|
/* Buffer size mismatch */ |
|
|
|
k_spin_unlock(&lock, key); |
|
return -EINVAL; |
|
} |
|
|
|
obj_core->stats = stats; |
|
k_spin_unlock(&lock, key); |
|
|
|
return 0; |
|
} |
|
|
|
int k_obj_core_stats_deregister(struct k_obj_core *obj_core) |
|
{ |
|
k_spinlock_key_t key = k_spin_lock(&lock); |
|
|
|
if (obj_core->type->stats_desc == NULL) { |
|
|
|
/* Object type not configured for statistics. */ |
|
|
|
k_spin_unlock(&lock, key); |
|
return -ENOTSUP; |
|
} |
|
|
|
obj_core->stats = NULL; |
|
k_spin_unlock(&lock, key); |
|
|
|
return 0; |
|
} |
|
|
|
int k_obj_core_stats_raw(struct k_obj_core *obj_core, void *stats, |
|
size_t stats_len) |
|
{ |
|
int rv; |
|
struct k_obj_core_stats_desc *desc; |
|
|
|
k_spinlock_key_t key = k_spin_lock(&lock); |
|
|
|
desc = obj_core->type->stats_desc; |
|
if ((desc == NULL) || (desc->raw == NULL)) { |
|
|
|
/* The object type is not configured for this operation */ |
|
|
|
k_spin_unlock(&lock, key); |
|
return -ENOTSUP; |
|
} |
|
|
|
if ((desc->raw_size != stats_len) || (obj_core->stats == NULL)) { |
|
|
|
/* |
|
* Either the size of the stats buffer is wrong or |
|
* the kernel object was not registered for statistics. |
|
*/ |
|
|
|
k_spin_unlock(&lock, key); |
|
return -EINVAL; |
|
} |
|
|
|
rv = desc->raw(obj_core, stats); |
|
k_spin_unlock(&lock, key); |
|
|
|
return rv; |
|
} |
|
|
|
int k_obj_core_stats_query(struct k_obj_core *obj_core, void *stats, |
|
size_t stats_len) |
|
{ |
|
int rv; |
|
struct k_obj_core_stats_desc *desc; |
|
|
|
k_spinlock_key_t key = k_spin_lock(&lock); |
|
|
|
desc = obj_core->type->stats_desc; |
|
if ((desc == NULL) || (desc->query == NULL)) { |
|
|
|
/* The object type is not configured for this operation */ |
|
|
|
k_spin_unlock(&lock, key); |
|
return -ENOTSUP; |
|
} |
|
|
|
if ((desc->query_size != stats_len) || (obj_core->stats == NULL)) { |
|
|
|
/* |
|
* Either the size of the stats buffer is wrong or |
|
* the kernel object was not registered for statistics. |
|
*/ |
|
|
|
k_spin_unlock(&lock, key); |
|
return -EINVAL; |
|
} |
|
|
|
rv = desc->query(obj_core, stats); |
|
k_spin_unlock(&lock, key); |
|
|
|
return rv; |
|
} |
|
|
|
int k_obj_core_stats_reset(struct k_obj_core *obj_core) |
|
{ |
|
int rv; |
|
struct k_obj_core_stats_desc *desc; |
|
|
|
k_spinlock_key_t key = k_spin_lock(&lock); |
|
|
|
desc = obj_core->type->stats_desc; |
|
if ((desc == NULL) || (desc->reset == NULL)) { |
|
|
|
/* The object type is not configured for this operation */ |
|
|
|
k_spin_unlock(&lock, key); |
|
return -ENOTSUP; |
|
} |
|
|
|
if (obj_core->stats == NULL) { |
|
|
|
/* This kernel object is not configured for statistics */ |
|
|
|
k_spin_unlock(&lock, key); |
|
return -EINVAL; |
|
} |
|
|
|
rv = desc->reset(obj_core); |
|
k_spin_unlock(&lock, key); |
|
|
|
return rv; |
|
} |
|
|
|
int k_obj_core_stats_disable(struct k_obj_core *obj_core) |
|
{ |
|
int rv; |
|
struct k_obj_core_stats_desc *desc; |
|
|
|
k_spinlock_key_t key = k_spin_lock(&lock); |
|
|
|
desc = obj_core->type->stats_desc; |
|
if ((desc == NULL) || (desc->disable == NULL)) { |
|
|
|
/* The object type is not configured for this operation */ |
|
|
|
k_spin_unlock(&lock, key); |
|
return -ENOTSUP; |
|
} |
|
|
|
if (obj_core->stats == NULL) { |
|
|
|
/* This kernel object is not configured for statistics */ |
|
|
|
k_spin_unlock(&lock, key); |
|
return -EINVAL; |
|
} |
|
|
|
rv = desc->disable(obj_core); |
|
k_spin_unlock(&lock, key); |
|
|
|
return rv; |
|
} |
|
|
|
int k_obj_core_stats_enable(struct k_obj_core *obj_core) |
|
{ |
|
int rv; |
|
struct k_obj_core_stats_desc *desc; |
|
|
|
k_spinlock_key_t key = k_spin_lock(&lock); |
|
|
|
desc = obj_core->type->stats_desc; |
|
if ((desc == NULL) || (desc->enable == NULL)) { |
|
|
|
/* The object type is not configured for this operation */ |
|
|
|
k_spin_unlock(&lock, key); |
|
return -ENOTSUP; |
|
} |
|
|
|
if (obj_core->stats == NULL) { |
|
|
|
/* This kernel object is not configured for statistics */ |
|
|
|
k_spin_unlock(&lock, key); |
|
return -EINVAL; |
|
} |
|
|
|
rv = desc->enable(obj_core); |
|
k_spin_unlock(&lock, key); |
|
|
|
return rv; |
|
} |
|
#endif /* CONFIG_OBJ_CORE_STATS */
|
|
|