QEMU源码全解析39 —— Machine(9)

接前一篇文章:QEMU源码全解析38 —— Machine(8)

本文内容参考:

《趣谈Linux操作系统》 —— 刘超,极客时间

QEMU/KVM》源码解析与应用 —— 李强,机械工业出版社

特此致谢!

上一回经过层层展开探索,终于看到了MACHINE的定义,实际上它是一个函数,代码如下(include/hw/boards.h中):

static inline G_GNUC_UNUSED MachineState *MACHINE(const void *obj)
{
    return OBJECT_CHECK(MachineState, obj, TYPE_MACHINE);
}

OBJECT_CHECK是一个宏,在include/qom/object.h中定义,代码如下:

/**
 * OBJECT_CHECK:
 * @type: The C type to use for the return value.
 * @obj: A derivative of @type to cast.
 * @name: The QOM typename of @type
 *
 * A type safe version of @object_dynamic_cast_assert.  Typically each class
 * will define a macro based on this type to perform type safe dynamic_casts to
 * this object type.
 *
 * If an invalid object is passed to this function, a run time assert will be
 * generated.
 */
#define OBJECT_CHECK(type, obj, name) \
    ((type *)object_dynamic_cast_assert(OBJECT(obj), (name), \
                                        __FILE__, __LINE__, __func__))

因此,代入宏定义后,MACHINE函数的最终代码为:

static inline G_GNUC_UNUSED MachineState *MACHINE(const void *obj)
{
    return ((MachineState*)object_dynamic_cast_assert(OBJECT(obj), ("machine"), __FILE__, __LINE__, __func__));
}

object_dynamic_cast_assert函数在qom/object.c中,代码如下:

Object *object_dynamic_cast_assert(Object *obj, const char *typename,
                                   const char *file, int line, const char *func)
{
    trace_object_dynamic_cast_assert(obj ? obj->class->type->name : "(null)",
                                     typename, file, line, func);

#ifdef CONFIG_QOM_CAST_DEBUG
    int i;
    Object *inst;

    for (i = 0; obj && i < OBJECT_CLASS_CAST_CACHE; i++) {
        if (qatomic_read(&obj->class->object_cast_cache[i]) == typename) {
            goto out;
        }
    }

    inst = object_dynamic_cast(obj, typename);

    if (!inst && obj) {
        fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n",
                file, line, func, obj, typename);
        abort();
    }

    assert(obj == inst);

    if (obj && obj == inst) {
        for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
            qatomic_set(&obj->class->object_cast_cache[i - 1],
                       qatomic_read(&obj->class->object_cast_cache[i]));
        }
        qatomic_set(&obj->class->object_cast_cache[i - 1], typename);
    }

out:
#endif
    return obj;
}

Object前文已介绍过,是所有对象的祖先。这里为了便于理解,再给出其代码。在include/qemu/typedefs.h中定义,如下:

typedef struct Object Object;

struct Object在中定义,代码如下:

/**
 * struct Object:
 *
 * The base for all objects.  The first member of this object is a pointer to
 * a #ObjectClass.  Since C guarantees that the first member of a structure
 * always begins at byte 0 of that structure, as long as any sub-object places
 * its parent as the first member, we can cast directly to a #Object.
 *
 * As a result, #Object contains a reference to the objects type as its
 * first member.  This allows identification of the real type of the object at
 * run time.
 */
struct Object
{
    /* private: */
    ObjectClass *class;
    ObjectFree *free;
    GHashTable *properties;
    uint32_t ref;
    Object *parent;
};

实际上就是类型进行检查,确保传入的对象类型是machine类型。

本着“一张一弛”的原则,本回就到这里。下一回将结合实际调用MACHINE宏的地方,继续深入展开分析。

猜你喜欢

转载自blog.csdn.net/phmatthaus/article/details/132312389