forked from xuos/xiuos
198 lines
5.5 KiB
C
198 lines
5.5 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);
|
|
strcpy(p_name, name);
|
|
p_name[TRACER_NODE_NAME_LEN - 1] = '\0';
|
|
node->name = p_name;
|
|
}
|
|
if (node->type == TRACER_OWNER) {
|
|
doubleListNodeInit(&node->children_guard);
|
|
} else {
|
|
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.meta = &sys_tracer.root_node;
|
|
|
|
// init memory allocator
|
|
slab_init(&sys_tracer.node_allocator, sizeof(TracerNode));
|
|
slab_init(&sys_tracer.node_name_allocator, sizeof(char[TRACER_NODE_NAME_LEN]));
|
|
}
|
|
|
|
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
|
|
int len = path - cur_start;
|
|
if (len >= TRACER_NODE_NAME_LEN) {
|
|
strncpy(name, cur_start, TRACER_NODE_NAME_LEN);
|
|
name[TRACER_NODE_NAME_LEN - 1] = '\0';
|
|
} else {
|
|
strncpy(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->meta;
|
|
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->meta->name == NULL ? "NULL" : owner->meta->name, name == NULL ? "NULL" : name_buffer);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
target->meta = inner_node;
|
|
return true;
|
|
}
|
|
|
|
void* AchieveResource(TraceTag* tag)
|
|
{
|
|
assert(tag != NULL);
|
|
if (tag->meta == NULL || tag->meta->type == TRACER_OWNER) {
|
|
return NULL;
|
|
}
|
|
|
|
return tag->meta->p_resource;
|
|
}
|
|
|
|
bool CreateResourceTag(TraceTag* new_tag, TraceTag* owner, char* name, tracemeta_ac_type type, void* p_resource)
|
|
{
|
|
assert(new_tag != NULL && owner != NULL);
|
|
if (owner->meta == NULL) {
|
|
ERROR("Tracer: Empty owner\n");
|
|
return false;
|
|
}
|
|
assert(owner->meta->type == TRACER_OWNER);
|
|
if (tracer_find_node_onestep(owner->meta, 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->meta->children_guard);
|
|
new_node->parent = owner->meta;
|
|
|
|
new_tag->meta = new_node;
|
|
return true;
|
|
}
|
|
|
|
bool DeleteResource(TraceTag* target, TraceTag* owner)
|
|
{
|
|
assert(target != NULL && owner != NULL);
|
|
assert(owner->meta != NULL && owner->meta->type == TRACER_OWNER);
|
|
if (target->meta == NULL) {
|
|
ERROR("Tracer: Delete a empty resource\n");
|
|
return false;
|
|
}
|
|
|
|
assert(target->meta->parent == owner->meta);
|
|
doubleListDel(&target->meta->list_node);
|
|
// delete name
|
|
if (target->meta->name != NULL) {
|
|
slab_free(&sys_tracer.node_name_allocator, target->meta->name);
|
|
}
|
|
// delete all children
|
|
/// @attention currently donot allow multilevel resource deletion
|
|
if (target->meta->type == TRACER_OWNER) {
|
|
assert(IS_DOUBLE_LIST_EMPTY(&target->meta->children_guard));
|
|
}
|
|
slab_free(&sys_tracer.node_allocator, target->meta);
|
|
target->meta = NULL;
|
|
return true;
|
|
} |