xiuos/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer.c

240 lines
6.9 KiB
C

/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file actracer.c
* @brief tracer implementation
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.25
*/
/*************************************************
File name: actracer.c
Description: tracer implementation
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
#include <stddef.h>
#include <string.h>
#include "actracer.h"
#include "assert.h"
static struct SysTracer sys_tracer;
static char root_name[TRACER_NODE_NAME_LEN] = "ROOT\0";
static void tracer_init_node(TracerNode* node, char* name, tracemeta_ac_type type, void* p_resource)
{
node->type = type;
node->parent = NULL;
if (name != NULL) {
char* p_name = (char*)slab_alloc(&sys_tracer.node_name_allocator);
if (!p_name) {
p_name = "BAD_NAME(NOMEM)";
} else {
strcpy(p_name, name);
p_name[TRACER_NODE_NAME_LEN - 1] = '\0';
node->name = p_name;
}
}
doubleListNodeInit(&node->children_guard);
node->p_resource = p_resource;
doubleListNodeInit(&node->list_node);
}
void sys_tracer_init()
{
// set sys_tracer resource identity
tracer_init_node(&sys_tracer.root_node, NULL, TRACER_OWNER, NULL);
sys_tracer.root_node.name = root_name;
sys_tracer.sys_tracer_tag.inner_node = &sys_tracer.root_node;
// init memory allocator
slab_init(&sys_tracer.node_allocator, sizeof(TracerNode), "TracerNodeAllocator");
slab_init(&sys_tracer.node_name_allocator, sizeof(char[TRACER_NODE_NAME_LEN]), "TracerNodeNameAllocator");
}
static char* parse_path(char* path, char* const name)
{
// Skip extra '/'
while (*path == '/') {
path++;
}
if (*path == '\0') {
return NULL;
}
// Start of current name
char* cur_start = path;
while (*path != '/' && *path != '\0') {
path++;
}
// Handle current name
size_t len = path - cur_start;
if (len >= TRACER_NODE_NAME_LEN) {
len = TRACER_NODE_NAME_LEN - 1;
}
memcpy(name, cur_start, len);
name[len] = '\0';
return path;
}
static TracerNode* tracer_find_node_onestep(TracerNode* const owner, const char* const name)
{
TracerNode* iter = NULL;
assert(owner->type == TRACER_OWNER);
DOUBLE_LIST_FOR_EACH_ENTRY(iter, &owner->children_guard, list_node)
{
if (iter->name == NULL) {
continue;
}
if (strcmp(name, iter->name) == 0) {
return iter;
}
}
return NULL;
}
TraceTag* const RequireRootTag()
{
return &sys_tracer.sys_tracer_tag;
}
bool AchieveResourceTag(TraceTag* target, TraceTag* owner, char* name)
{
static char name_buffer[TRACER_NODE_NAME_LEN];
TracerNode* inner_node = owner->inner_node;
assert(inner_node != NULL && inner_node->type == TRACER_OWNER);
while ((name = parse_path(name, name_buffer)) != NULL) {
if ((inner_node = tracer_find_node_onestep(inner_node, name_buffer)) == NULL) {
DEBUG("Tracer: No such object, owner: %s, child: %s\n", //
owner->inner_node->name == NULL ? "NULL" : owner->inner_node->name, name == NULL ? "NULL" : name_buffer);
return false;
}
}
target->inner_node = inner_node;
return true;
}
void* AchieveResource(TraceTag* tag)
{
assert(tag != NULL);
if (tag->inner_node == NULL || tag->inner_node->type == TRACER_OWNER) {
return NULL;
}
return tag->inner_node->p_resource;
}
bool CreateResourceTag(TraceTag* new_tag, TraceTag* owner, char* name, tracemeta_ac_type type, void* p_resource)
{
assert(owner != NULL);
if (owner->inner_node == NULL) {
ERROR("Tracer: Empty owner, node name: %s\n", name);
return false;
}
// assert(owner->inner_node->type == TRACER_OWNER);
if (type == TRACER_SERVER_IDENTITY_AC_RESOURCE && //
tracer_find_node_onestep(owner->inner_node, name) != NULL) {
return false;
}
TracerNode* new_node = (TracerNode*)slab_alloc(&sys_tracer.node_allocator);
if (new_node == NULL) {
ERROR("Tracer: No memory for new node\n");
return false;
}
tracer_init_node(new_node, name, type, p_resource);
// new node add to owner's children list
doubleListAddOnHead(&new_node->list_node, &owner->inner_node->children_guard);
new_node->parent = owner->inner_node;
if (new_tag != NULL) {
new_tag->inner_node = new_node;
}
return true;
}
bool DeleteResource(TraceTag* target, TraceTag* owner)
{
assert(target != NULL && owner != NULL);
assert(owner->inner_node != NULL && owner->inner_node->type == TRACER_OWNER);
if (target->inner_node == NULL) {
ERROR("Tracer: Delete a empty resource, owner: %s\n", owner->inner_node->name);
return false;
}
assert(target->inner_node->parent == owner->inner_node);
doubleListDel(&target->inner_node->list_node);
// delete name
if (target->inner_node->name != NULL) {
slab_free(&sys_tracer.node_name_allocator, target->inner_node->name);
}
// delete all children
if (target->inner_node->type == TRACER_OWNER) {
while (!IS_DOUBLE_LIST_EMPTY(&target->inner_node->children_guard)) {
TraceTag tmp_node = {
.inner_node = DOUBLE_LIST_ENTRY(target->inner_node->children_guard.next, TracerNode, list_node),
};
DeleteResource(&tmp_node, target);
}
}
slab_free(&sys_tracer.node_allocator, target->inner_node);
target->inner_node = NULL;
return true;
}
#define debug_print_blanks(n) \
for (int __i = 0; __i < n; __i++) { \
DEBUG_PRINTF(" "); \
}
void debug_list_tracetree_inner(TracerNode* cur_node, int nr_blanks)
{
debug_print_blanks(nr_blanks);
if (cur_node->name == NULL) {
DEBUG_PRINTF("[ANON %d] ", cur_node->type);
} else {
DEBUG_PRINTF("[%s %d] ", cur_node->name, cur_node->type);
}
TracerNode* tmp = NULL;
DOUBLE_LIST_FOR_EACH_ENTRY(tmp, &cur_node->children_guard, list_node)
{
if (tmp->name != NULL) {
DEBUG_PRINTF("%s ", tmp->name);
} else {
DEBUG_PRINTF("ANON ");
}
}
DEBUG_PRINTF("\n");
DOUBLE_LIST_FOR_EACH_ENTRY(tmp, &cur_node->children_guard, list_node)
{
debug_list_tracetree_inner(tmp, nr_blanks + 1);
}
}
void debug_list_tracetree()
{
TracerNode* ref_root = RequireRootTag()->inner_node;
debug_list_tracetree_inner(ref_root, 0);
}