您的位置:首页 > 运维架构 > Linux

arm linux启动流程四

2016-08-22 14:57 429 查看
一、概述

debug_objects_early_init()函数用于内核的对象调试。依赖配置CONFIG_DEBUG_OBJECTS。

二、相关结构体

struct debug_bucket {

    struct hlist_head    list;    //挂载的是当前debug_obj对象

    raw_spinlock_t        lock;

};

struct debug_obj {

    struct hlist_node node;    //链接跟踪器列表中的对象

    enum debug_obj_state state;    //跟踪的对象状态

    unsigned int astate;    //当前active状态

    void *object;//对实际对象的指针

    struct debug_obj_descr *descr;    //用于调试的描述符结构体指针

};

enum debug_obj_state {

    ODEBUG_STATE_NONE,

    ODEBUG_STATE_INIT,

    ODEBUG_STATE_INACTIVE,

    ODEBUG_STATE_ACTIVE,

    ODEBUG_STATE_DESTROYED,

    ODEBUG_STATE_NOTAVAILABLE,

    ODEBUG_STATE_MAX,

};

struct debug_obj_descr {

    const char *name;

    void *(*debug_hint) (void *addr);

    int (*fixup_init) (void *addr, enum
debug_obj_state state);

    int (*fixup_activate) (void *addr, enum
debug_obj_state state);

    int (*fixup_destroy) (void *addr, enum
debug_obj_state state);

    int (*fixup_free) (void *addr, enum
debug_obj_state state);

    int (*fixup_assert_init)(void *addr, enum
debug_obj_state state);

};

二、代码

//../lib/debugobjects.c

static struct debug_bucket    obj_hash[ODEBUG_HASH_SIZE];

static HLIST_HEAD(obj_pool);

static struct debug_obj        obj_static_pool[ODEBUG_POOL_SIZE] __initdata;

void __init debug_objects_early_init(void)

{

    int i;

    

    //初始化spin lock

    for (i = 0; i < ODEBUG_HASH_SIZE; i++)

        raw_spin_lock_init(&obj_hash[i].lock);

    //将obj_static_pool数组都挂入obj_pool链表头

    for (i = 0; i < ODEBUG_POOL_SIZE; i++)

        hlist_add_head(&obj_static_pool[i].node, &obj_pool);

}

start_kernel后面在slab机制创建后,还会有debug初始化操作:

void __init debug_objects_mem_init(void)

{

    if (!debug_objects_enabled)

        return;

    

    //创建debug_obj的slab高速缓存

    obj_cache = kmem_cache_create("debug_objects_cache",sizeof (struct
debug_obj), 0,SLAB_DEBUG_OBJECTS, NULL);

    //obj_cache创建成功则调用debug_objects_replace_static_objects函数

    if (!obj_cache || debug_objects_replace_static_objects()) {

        debug_objects_enabled = 0;

        if (obj_cache)

            kmem_cache_destroy(obj_cache);

        pr_warn("out of memory.\n");

    } else

    debug_objects_selftest();    //debug_obj对象自测

}

static int __init debug_objects_replace_static_objects(void)

{

    struct debug_bucket *db = obj_hash;

    struct hlist_node *tmp;

     struct debug_obj *obj, *new;

    HLIST_HEAD(objects);

    int i, cnt = 0;

    

    //从高速缓存中分配debug_obj对象挂载到全局链表objects

    for (i = 0; i < ODEBUG_POOL_SIZE; i++) {

        obj = kmem_cache_zalloc(obj_cache, GFP_KERNEL);

        if (!obj)

            goto free;

        hlist_add_head(&obj->node, &objects);

    }

 

    //此时只有一个cpu在运行,关中断即进入临界区。是为了防止lockdep hell of lock ordering

    local_irq_disable();

 

    //从obj_pool中移除静态的debug_obj对象

    hlist_for_each_entry_safe(obj, tmp, &obj_pool, node)

        hlist_del(&obj->node);

    //将刚分配的动态debug_obj对象链入obj_pool

    hlist_move_list(&objects, &obj_pool);

 

    for (i = 0; i < ODEBUG_HASH_SIZE; i++, db++) {

        //将obj_hash中的debug_bucket对象上的list节点挂载的debug_obj对象链入objects链表

        hlist_move_list(&db->list, &objects);

        

        //然后遍历objects链表中的debug_obj对象

        hlist_for_each_entry(obj, &objects, node) {

            //从obj_pool取出一个debug_obj对象

            new = hlist_entry(obj_pool.first, typeof(*obj), node);

            //将该debug_obj对象从obj_pool链表删除

            hlist_del(&new->node);    

            //拷贝debug_obj对象

            *new = *obj;

            //将该新debug_obj对象链入到objects链表中的debug_bucket对象上的list节点

            hlist_add_head(&new->node, &db->list);

            cnt++;

        }

    }

    local_irq_enable();

        

    pr_debug("%d of %d active objects replaced\n",cnt, obj_pool_used);

    return 0;

free:

    hlist_for_each_entry_safe(obj, tmp, &objects, node) {

        hlist_del(&obj->node);

        kmem_cache_free(obj_cache, obj);

    }

    return -ENOMEM;

}

三、debug使用

1. 定义自己用于调试的描述符结构体指针

static __initdata struct debug_obj_descr descr_type_test = {

    .name = "selftest",

    .fixup_init = fixup_init,

    .fixup_activate = fixup_activate,

    .fixup_destroy = fixup_destroy,

    .fixup_free = fixup_free,

};

2. 初始化

void debug_object_init(void *addr, struct debug_obj_descr *descr)

{

    if (!debug_objects_enabled)

        return;

        

    __debug_object_init(addr, descr, 0);

}

static void __debug_object_init(void *addr, struct debug_obj_descr *descr, int onstack)

{

    enum debug_obj_state state;

    struct debug_bucket *db;

    struct debug_obj *obj;

    unsigned long flags;

    

    //检测obj_pool是否需要添加新的debug_obj对象    

    fill_pool();

    

    //根据要debug的地址通过hash算法得到debug_bucket对象

    db = get_bucket((unsigned long) addr);

        

    raw_spin_lock_irqsave(&db->lock, flags);

    

    //根据debug地址到obj_pool查找一个debug_obj对象

    obj = lookup_object(addr, db);

    //没找到则通过obj_pool分配一个debug_obj对象

    if (!obj) {

        obj = alloc_object(addr, db, descr);

        if (!obj) {

            debug_objects_enabled = 0;

            raw_spin_unlock_irqrestore(&db->lock, flags);

            debug_objects_oom();

            return;

        }

        //安全检查

        debug_object_is_on_stack(addr, onstack);

    }

    

    //设置debug_obj对象状态,如果是通过alloc_object分配的对象,则状态为ODEBUG_STATE_NONE,然后通过下边设置为ODEBUG_STATE_INIT

    switch (obj->state) {

        case ODEBUG_STATE_NONE:

        case ODEBUG_STATE_INIT:

        case ODEBUG_STATE_INACTIVE:

            obj->state = ODEBUG_STATE_INIT;

            break;

        

        case ODEBUG_STATE_ACTIVE:

            debug_print_object(obj, "init");

            state = obj->state;

            raw_spin_unlock_irqrestore(&db->lock, flags);

            debug_object_fixup(descr->fixup_init, addr, state);

            return;

        

        case ODEBUG_STATE_DESTROYED:

            debug_print_object(obj, "init");

            break;

        default:

            break;

    }

     

    raw_spin_unlock_irqrestore(&db->lock, flags);

}

static void fill_pool(void)

{

    gfp_t gfp = GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN;

    struct debug_obj *new;

    unsigned long flags;

    

    //obj_pool中的空闲debug_obj对象足够则返回

    if (likely(obj_pool_free >= ODEBUG_POOL_MIN_LEVEL))

        return;

    

    //若没创建高速缓存则返回 

    if (unlikely(!obj_cache))

        return;

    //若空闲对象少于最低阀值,则创建新对象链入obj_pool链表中

    while (obj_pool_free < ODEBUG_POOL_MIN_LEVEL) {    

        new = kmem_cache_zalloc(obj_cache, gfp);

        if (!new)

            return;

        

        raw_spin_lock_irqsave(&pool_lock, flags);

        hlist_add_head(&new->node, &obj_pool);

        obj_pool_free++;

        raw_spin_unlock_irqrestore(&pool_lock, flags);

    }

}

static struct debug_bucket *get_bucket(unsigned long addr)

{

    unsigned long hash;

        

    hash = hash_long((addr >> ODEBUG_CHUNK_SHIFT), ODEBUG_HASH_BITS);

    return &obj_hash[hash];

}

static struct debug_obj *lookup_object(void *addr, struct
debug_bucket *b)

{

    struct debug_obj *obj;

    int cnt = 0;

    

    //遍历该debug_bucket对象上挂载的debug_obj对象

    hlist_for_each_entry(obj, &b->list, node) {

        cnt++;

        //地址相等即找到相应的debug_obj对象

        if (obj->object == addr)

            return obj;

    }

    

    //更新debug_bucket对象上挂载的debug_obj对象最大值

    if (cnt > debug_objects_maxchain)

        debug_objects_maxchain = cnt;

        

    return NULL;

}

static struct debug_obj *alloc_object(void *addr, struct
debug_bucket *b, struct debug_obj_descr *descr)

{

    struct debug_obj *obj = NULL;

        

    raw_spin_lock(&pool_lock);

    if (obj_pool.first) {

        //从obj_pool链表中取出一个debug_obj对象

        obj    = hlist_entry(obj_pool.first, typeof(*obj), node);

        

        //对该对象初始化

        obj->object = addr;    //debug的地址

        obj->descr = descr;//调试的描述符结构体

        obj->state = ODEBUG_STATE_NONE;//设置状态

        obj->astate = 0;

        //从obj_pool链表中删除

        hlist_del(&obj->node);

        //链入debug_bucket对象的list节点

        hlist_add_head(&obj->node, &b->list);

        

        //更新一些变量

        obj_pool_used++;

        if (obj_pool_used > obj_pool_max_used)

            obj_pool_max_used = obj_pool_used;

        

        obj_pool_free--;

        if (obj_pool_free < obj_pool_min_free)

            obj_pool_min_free = obj_pool_free;

    }

    raw_spin_unlock(&pool_lock);

        

    return obj;

}

3. 使能addr对应的debug_obj

int debug_object_activate(void *addr, struct
debug_obj_descr *descr)

{

    enum debug_obj_state state;

    struct debug_bucket *db;

    struct debug_obj *obj;

    unsigned long flags;

    int ret;

    struct debug_obj o = {    .object = addr,

                            .state = ODEBUG_STATE_NOTAVAILABLE,

                            .descr = descr };

    

    //没有使能debug功能则返回    

    if (!debug_objects_enabled)

        return 0;

    //根据要debug的地址通过hash算法得到debug_bucket对象

    db = get_bucket((unsigned long) addr);    

    raw_spin_lock_irqsave(&db->lock, flags);

    //根据debug地址到obj_pool查找一个debug_obj对象        

    obj = lookup_object(addr, db);

    //将debug_obj对象状态设置为ODEBUG_STATE_ACTIVE

    if (obj) {

        switch (obj->state) {

        case ODEBUG_STATE_INIT:

        case ODEBUG_STATE_INACTIVE:

            obj->state = ODEBUG_STATE_ACTIVE;

            ret = 0;

            break;

        

        case ODEBUG_STATE_ACTIVE:

            debug_print_object(obj, "activate");

            state = obj->state;

            raw_spin_unlock_irqrestore(&db->lock, flags);

            ret = debug_object_fixup(descr->fixup_activate, addr, state);

            return ret ? -EINVAL : 0;

        

        case ODEBUG_STATE_DESTROYED:

            debug_print_object(obj, "activate");

            ret = -EINVAL;

            break;

        default:

            ret = 0;

            break;

        }

        raw_spin_unlock_irqrestore(&db->lock, flags);

        return ret;

    }

    raw_spin_unlock_irqrestore(&db->lock, flags);

    if (debug_object_fixup(descr->fixup_activate, addr,ODEBUG_STATE_NOTAVAILABLE)) {

        debug_print_object(&o, "activate");

        return -EINVAL;

    }

    return 0;

}

4. 用于检查addr对应的debug_obj对象的状态是否正确

static int __init check_results(void *addr, enum
debug_obj_state state, int fixups, int warnings);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: