1. What is the object?
-
The object type enumeration is defined as follows:
enum rt_object_class_type { RT_Object_Class_Thread = 0, /* The object is a thread */ RT_Object_Class_Semaphore, /* The object is a semaphore */ RT_Object_Class_Mutex, /* Objects are mutexes */ RT_Object_Class_Event, /* Objects are events */ RT_Object_Class_MailBox, /* The object is a mailbox */ RT_Object_Class_MessageQueue, /* The object is a message queue */ RT_Object_Class_MemHeap, /* The object is a memory heap */ RT_Object_Class_Mempool, /* The object is a memory pool */ RT_Object_Class_Device, /* The object is a device */ RT_Object_Class_Timer, /* The object is a timer */ RT_Object_Class_Module, /* The object is a module */ RT_Object_Class_Unknown, /* The object is unknown */ RT_Object_Class_Static = 0x80 /* Object is a static object */ };
-
Object data types are defined as follows:
struct rt_object { char name[RT_NAME_MAX]; /* The name of the kernel object */ rt_uint8_t type; /* Type of kernel object */ rt_uint8_t flag; /* The state of the kernel object */ rt_list_t list; /* List node of kernel object */ };
-
Adds an object member to a thread control block
In RT thread, each object will have a corresponding structure, which is called the control block of the object. For example, a thread will have a thread control block, in which the members of the object structure are placed at the beginning of the thread control block. The specific source code is as follows:
struct rt_thread { /* rt object */ char name[RT_NAME_MAX]; /* Object name */ rt_uint8_t type; /* object type */ rt_uint8_t flags; /* State of the object */ rt_list_t list; /* Object's list node */ rt_list_t tlist; /* Thread linked list node */ void *sp; /* Thread stack pointer */ void *entry; /* Thread entry address */ void *parameter; /* Thread parameters */ void *stack_addr; /* Thread stack start address */ rt_uint32_t stack_size; /* Thread stack size, in bytes */ };
-
What is a container
From the code point of view, the container is an array. Each element corresponds to different object types. Each new object will be attached to the linked list of corresponding elements. The source code of the definition part of the container is as follows:
static struct rt_object_information rt_object_container[RT_Object_Info_Unknown] = { /* Initialize object container - thread */ { RT_Object_Class_Thread, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Thread), sizeof(struct rt_thread) }, #ifdef RT_USING_SEMAPHORE /* Initialize object container - semaphore */ { RT_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Semaphore), sizeof(struct rt_semaphore) }, #endif #ifdef RT_USING_MUTEX /* Initialize object container - mutex */ { RT_Object_Class_Mutex, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Mutex), sizeof(struct rt_mutex) }, #endif . . . . . . . . . }
Type struct rt_object_information is defined as follows:
struct rt_object_information { enum rt_object_class_type type; /* object type */ rt_list_t object_list; /* Object list node header */ rt_size_t object_size; /* Object size */ };
The schematic diagram of the initial object container is shown in the figure below. The next and prev pointers in the node headers of all element linked lists point to themselves.
2. Interface implementation of container
-
Gets object information of the specified type
When the container is defined, the size is fixed and determined by RT_Object_Info_Unknown is determined by the enumeration value, but the member index value in the container is not fixed, that is, the fixed index cannot be used to obtain the information of the members in the container. Therefore, it is necessary to traverse the entire container object. If the object type is equal to the type specified by us, then the address of the container member is returned. The type of the address is struct rt_object_information, the specific source code is as follows:
struct rt_object_information * rt_object_get_information(enum rt_object_class_type type) { int index; for (index = 0; index < RT_Object_Class_Unknown; index++) { if (rt_object_container[index].type == type) { return &rt_object_container[index]; } } return RT_NULL; }
-
Object initialization
Each time you create an object, you need to initialize it. It is mainly divided into two parts. First, initialize the object related members in the object control block, and then insert the object into the object container. The specific source code is as follows:
/** * This function initializes the object and adds it to the object container * * @param object Object to initialize * @param type Type of object * @param name The name of the object. In the whole system, the name of the object must be unique */ void rt_object_init(struct rt_object *object, enum rt_object_class_type type, const char *name) { register rt_base_t temp; struct rt_object_information *information; /* Get the object information, that is, get the corresponding object list header pointer from the container */ information = rt_object_get_information(type); /* Set the object type to static */ object->type = type | RT_Object_Class_Static; /* Copy name */ rt_strncpy(object->name, name, RT_NAME_MAX); /* Off interrupt */ temp = rt_hw_interrupt_disable(); /* Insert the object into the corresponding list of the container. The list of different types of objects is different */ rt_list_insert_after(&(information->object_list), &(object->list)); /* Enable interrupt */ rt_hw_interrupt_enable(temp); }
-
Call object initialization function
The object initialization function is called in the thread initialization function. The specific source code is as follows:
rt_err_t rt_thread_init (struct rt_thread *thread, const char *name, void (*entry) (void *parameter), void *parameter, void *stack_start, rt_uint32_t stack_size) { /* * Thread object initialization * The four members at the beginning of the thread structure are rt_object_t member */ rt_object_init((rt_object_t)thread, RT_Object_Class_Thread, name); rt_list_init(&(thread->tlist)); thread->entry = (void *)entry; thread->parameter = parameter; thread->stack_addr = stack_start; thread->stack_size = stack_size; /* Initialize the thread stack and return the thread stack pointer */ thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter, (void *)((char *)thread->stack_addr + thread->stack_size - 4)); return RT_EOK; }
If two threads are created, after thread initialization, the thread will hang itself to the object chain list of the container through its own list node. The schematic diagram in the container is shown in the following figure: