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);
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);
相关文章推荐
- ARM-linux的启动流程
- Android arm linux kernel启动流程(二)
- ARM-Linux内核移植之(一)——内核启动流程分析 .
- 对arm-linux整个启动流程的认识1
- linux启动流程导读(arm为例)<一>
- ARM- Linux开发环境的介绍:启动的流程
- Android arm linux kernel启动流程(二)
- ARM-Linux移植之(三)——init进程启动流程分析
- ARM linux启动的流程
- linux启动流程导读(arm为例)<二>
- 详解ARM-linux的启动流程[转帖]
- Android arm linux kernel启动流程(二)
- 详解ARM-linux的启动流程[转帖]
- ARM-Linux移植之(三)——init进程启动流程分析
- ARM-linux启动的流程
- ARM-linux的启动流程
- arm linux 启动流程之 进入内核
- Android arm linux kernel启动流程(一)
- linux启动流程导读(arm为例)<二>
- ARM-Linux移植之(三)——init进程启动流程分析