XWOS Object
Categories:
4 minute read
Overview
All XWOS kernel objects inherit from struct xwos_object.
struct xwos_object {
xwsq_t tik;
xwsq_t magic;
atomic_xwsq_t refcnt;
xwobj_gc_f gcfunc;
};
tik: The object’s tag, a unique integer assigned by the system. This tag serves as the object’s identity ID;magic: The constant0x58574F53U, used to determine whether a memory address is an XWOS object;refcnt: XWOS objects use reference counting to manage their lifecycle. When the object’s reference count drops to0,gcfunc()is called for garbage collection;gcfunc: Garbage collection function.
Following object-oriented thinking, struct xwos_object should be the first member of the subclass object structure. struct xwos_object * can then be forcefully cast to a pointer to the subclass object.
Object Descriptor
When using an object pointer to access an object, a situation may occur: The object has already been released, and even the released memory has been reused to construct a new object, but the holder of the object pointer is unaware of this situation. This leads to various pointer issues. To solve this type of problem, XWOS introduces the object descriptor. The object descriptor is composed of a pointer to the object and a tag:
typedef struct {
struct xwos_object * obj;
xwsq_t tik;
} xwobj_d;
When referencing an object through the object descriptor, first check the value of obj->magic to see if it is 0x58574F53U, which confirms that the pointer obj points to a valid XWOS object.
Then compare the tags obj->tik and tik to see if they are equal, which confirms the object’s identity.
Since the object’s tik is globally unique, when the object is released, its tik will be destructed to 0 by the destructor.
When the memory address is reconstructed into a new object, its tik will definitely differ from the tik in the object descriptor.
Correspondingly, when struct xwos_object is inherited by a subclass, the subclass should also have a corresponding object descriptor.
For example, a thread object has a thread object descriptor, a mutex object has a mutex object descriptor, etc.
Object Lifecycle
XWOS objects use reference counting to manage their lifecycle. The lifecycle of an XWOS object is divided into three stages:
- Construction Stage: After the object is constructed via
xwos_object_construct(), it enters the construction stage. At this point, the object’s reference count is 0. If there is derivation and inheritance, constructors need to be called in order from base class to subclass. - Application Stage: An object in the construction stage enters the application stage after being activated via
xwos_object_activate(). If there is derivation and inheritance, activation functions need to be called in order from base class to subclass. In this stage, the object’s reference count is >= 1, and the object can begin to be used. - Release Stage: When the object’s reference count drops from >= 1 to 0, the object enters the release stage. In this stage, the object’s
gcfunc()is called to release the object. The user needs to provide the definition ofgcfunc(). Insidegcfunc(), the object’s destructorxwos_object_destruct()must also be called. If there is derivation and inheritance, destructors need to be called in order from subclass to base class. At this point, the object lifecycle ends.
Object Lifecycle Management
XWOS provides two sets of CAPI for object lifecycle management:
-
Access lifecycle management CAPI using object pointer: requires ensuring that the object is definitely valid when calling the CAPI, and there is no case of released-then-reallocated as another object.
xwos_object_grab(): Increase reference count.xwos_object_put(): Decrease reference count. When the reference count drops to 0, the garbage collection function is called to release the object.xwos_object_rawput(): Decrease reference count. The garbage collection function is not called when the reference count is 0.
-
Access lifecycle management CAPI using object descriptor: used when the user cannot guarantee that the object is definitely valid or cannot guarantee that the object has not become another object.
xwos_object_acquire(): Determine that the object is valid and legitimate through the object descriptor, then increase the reference count.xwos_object_release(): Determine that the object is valid and legitimate through the object descriptor, then decrease the reference count. When the reference count drops to 0, the garbage collection function is called to release the object.
Limitations
Frequent management of object lifecycles affects CPU execution efficiency, because reference counting operations are atomic operations, and atomic operations affect CPU performance. The stronger the CPU performance, the greater the impact. Therefore, except when necessary, the CAPI of various XWOS kernel objects is designed to directly use the object pointer as a parameter and does not automatically manage the object’s lifecycle. The validity of the object, the legitimacy of its identity, and the lifecycle need to be manually managed by the user.
Typically, in simple MCU RTOS applications, these objects are created and never released, so there is no need to worry about the lifecycle. In fact, the object lifecycle CAPI is primarily designed for high-level languages, such as the Lua virtual machine, to implement automatic management of object lifecycles.