arm linux启动流程四

3180阅读 0评论2014-08-18 wangbaolin719
分类:LINUX


  1. 一、概述
  2. debug_objects_early_init()函数用于内核的对象调试。依赖配置CONFIG_DEBUG_OBJECTS。

  3. 二、相关结构体
  4. struct debug_bucket {
  5.     struct hlist_head    list;    //挂载的是当前debug_obj对象
  6.     raw_spinlock_t        lock;
  7. };

  8. struct debug_obj {
  9.     struct hlist_node node;    //链接跟踪器列表中的对象
  10.     enum debug_obj_state state;    //跟踪的对象状态
  11.     unsigned int astate;    //当前active状态
  12.     void *object;//对实际对象的指针
  13.     struct debug_obj_descr *descr;    //用于调试的描述符结构体指针
  14. };

  15. enum debug_obj_state {
  16.     ODEBUG_STATE_NONE,
  17.     ODEBUG_STATE_INIT,
  18.     ODEBUG_STATE_INACTIVE,
  19.     ODEBUG_STATE_ACTIVE,
  20.     ODEBUG_STATE_DESTROYED,
  21.     ODEBUG_STATE_NOTAVAILABLE,
  22.     ODEBUG_STATE_MAX,
  23. };

  24. struct debug_obj_descr {
  25.     const char *name;
  26.     void *(*debug_hint) (void *addr);
  27.     int (*fixup_init) (void *addr, enum debug_obj_state state);
  28.     int (*fixup_activate) (void *addr, enum debug_obj_state state);
  29.     int (*fixup_destroy) (void *addr, enum debug_obj_state state);
  30.     int (*fixup_free) (void *addr, enum debug_obj_state state);
  31.     int (*fixup_assert_init)(void *addr, enum debug_obj_state state);
  32. };

  33. 二、代码
  34. //../lib/debugobjects.c
  35. static struct debug_bucket    obj_hash[ODEBUG_HASH_SIZE];
  36. static HLIST_HEAD(obj_pool);
  37. static struct debug_obj        obj_static_pool[ODEBUG_POOL_SIZE] __initdata;
  38. void __init debug_objects_early_init(void)
  39. {
  40.     int i;
  41.     
  42.     //初始化spin lock
  43.     for (i = 0; i < ODEBUG_HASH_SIZE; i++)
  44.         raw_spin_lock_init(&obj_hash[i].lock);

  45.     //将obj_static_pool数组都挂入obj_pool链表头
  46.     for (i = 0; i < ODEBUG_POOL_SIZE; i++)
  47.         hlist_add_head(&obj_static_pool[i].node, &obj_pool);
  48. }

  49. start_kernel后面在slab机制创建后,还会有debug初始化操作:
  50. void __init debug_objects_mem_init(void)
  51. {
  52.     if (!debug_objects_enabled)
  53.         return;
  54.     
  55.     //创建debug_obj的slab高速缓存
  56.     obj_cache = kmem_cache_create("debug_objects_cache",sizeof (struct debug_obj), 0,SLAB_DEBUG_OBJECTS, NULL);

  57.     //obj_cache创建成功则调用debug_objects_replace_static_objects函数
  58.     if (!obj_cache || debug_objects_replace_static_objects()) {
  59.         debug_objects_enabled = 0;
  60.         if (obj_cache)
  61.             kmem_cache_destroy(obj_cache);
  62.         pr_warn("out of memory.\n");
  63.     } else
  64.     debug_objects_selftest();    //debug_obj对象自测
  65. }

  66. static int __init debug_objects_replace_static_objects(void)
  67. {
  68.     struct debug_bucket *db = obj_hash;
  69.     struct hlist_node *tmp;
  70.      struct debug_obj *obj, *new;
  71.     HLIST_HEAD(objects);
  72.     int i, cnt = 0;
  73.     
  74.     //从高速缓存中分配debug_obj对象挂载到全局链表objects
  75.     for (i = 0; i < ODEBUG_POOL_SIZE; i++) {
  76.         obj = kmem_cache_zalloc(obj_cache, GFP_KERNEL);
  77.         if (!obj)
  78.             goto free;
  79.         hlist_add_head(&obj->node, &objects);
  80.     }
  81.  
  82.     //此时只有一个cpu在运行,关中断即进入临界区。是为了防止lockdep hell of lock ordering
  83.     local_irq_disable();
  84.  
  85.     //从obj_pool中移除静态的debug_obj对象
  86.     hlist_for_each_entry_safe(obj, tmp, &obj_pool, node)
  87.         hlist_del(&obj->node);

  88.     //将刚分配的动态debug_obj对象链入obj_pool
  89.     hlist_move_list(&objects, &obj_pool);
  90.  
  91.     for (i = 0; i < ODEBUG_HASH_SIZE; i++, db++) {
  92.         //将obj_hash中的debug_bucket对象上的list节点挂载的debug_obj对象链入objects链表
  93.         hlist_move_list(&db->list, &objects);
  94.         
  95.         //然后遍历objects链表中的debug_obj对象
  96.         hlist_for_each_entry(obj, &objects, node) {
  97.             //从obj_pool取出一个debug_obj对象
  98.             new = hlist_entry(obj_pool.first, typeof(*obj), node);
  99.             //将该debug_obj对象从obj_pool链表删除
  100.             hlist_del(&new->node);    
  101.             //拷贝debug_obj对象
  102.             *new = *obj;
  103.             //将该新debug_obj对象链入到objects链表中的debug_bucket对象上的list节点
  104.             hlist_add_head(&new->node, &db->list);
  105.             cnt++;
  106.         }
  107.     }
  108.     local_irq_enable();
  109.         
  110.     pr_debug("%d of %d active objects replaced\n",cnt, obj_pool_used);
  111.     return 0;
  112. free:
  113.     hlist_for_each_entry_safe(obj, tmp, &objects, node) {
  114.         hlist_del(&obj->node);
  115.         kmem_cache_free(obj_cache, obj);
  116.     }
  117.     return -ENOMEM;
  118. }

  119. 三、debug使用
  120. 1. 定义自己用于调试的描述符结构体指针
  121. static __initdata struct debug_obj_descr descr_type_test = {
  122.     .name = "selftest",
  123.     .fixup_init = fixup_init,
  124.     .fixup_activate = fixup_activate,
  125.     .fixup_destroy = fixup_destroy,
  126.     .fixup_free = fixup_free,
  127. };

  128. 2. 初始化
  129. void debug_object_init(void *addr, struct debug_obj_descr *descr)
  130. {
  131.     if (!debug_objects_enabled)
  132.         return;
  133.         
  134.     __debug_object_init(addr, descr, 0);
  135. }

  136. static void __debug_object_init(void *addr, struct debug_obj_descr *descr, int onstack)
  137. {
  138.     enum debug_obj_state state;
  139.     struct debug_bucket *db;
  140.     struct debug_obj *obj;
  141.     unsigned long flags;
  142.     
  143.     //检测obj_pool是否需要添加新的debug_obj对象    
  144.     fill_pool();
  145.     
  146.     //根据要debug的地址通过hash算法得到debug_bucket对象
  147.     db = get_bucket((unsigned long) addr);
  148.         
  149.     raw_spin_lock_irqsave(&db->lock, flags);
  150.     
  151.     //根据debug地址到obj_pool查找一个debug_obj对象
  152.     obj = lookup_object(addr, db);
  153.     //没找到则通过obj_pool分配一个debug_obj对象
  154.     if (!obj) {
  155.         obj = alloc_object(addr, db, descr);
  156.         if (!obj) {
  157.             debug_objects_enabled = 0;
  158.             raw_spin_unlock_irqrestore(&db->lock, flags);
  159.             debug_objects_oom();
  160.             return;
  161.         }
  162.         //安全检查
  163.         debug_object_is_on_stack(addr, onstack);
  164.     }
  165.     
  166.     //设置debug_obj对象状态,如果是通过alloc_object分配的对象,则状态为ODEBUG_STATE_NONE,然后通过下边设置为ODEBUG_STATE_INIT
  167.     switch (obj->state) {
  168.         case ODEBUG_STATE_NONE:
  169.         case ODEBUG_STATE_INIT:
  170.         case ODEBUG_STATE_INACTIVE:
  171.             obj->state = ODEBUG_STATE_INIT;
  172.             break;
  173.         
  174.         case ODEBUG_STATE_ACTIVE:
  175.             debug_print_object(obj, "init");
  176.             state = obj->state;
  177.             raw_spin_unlock_irqrestore(&db->lock, flags);
  178.             debug_object_fixup(descr->fixup_init, addr, state);
  179.             return;
  180.         
  181.         case ODEBUG_STATE_DESTROYED:
  182.             debug_print_object(obj, "init");
  183.             break;
  184.         default:
  185.             break;
  186.     }
  187.     
  188.     raw_spin_unlock_irqrestore(&db->lock, flags);
  189. }

  190. static void fill_pool(void)
  191. {
  192.     gfp_t gfp = GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN;
  193.     struct debug_obj *new;
  194.     unsigned long flags;
  195.     
  196.     //obj_pool中的空闲debug_obj对象足够则返回
  197.     if (likely(obj_pool_free >= ODEBUG_POOL_MIN_LEVEL))
  198.         return;
  199.     
  200.     //若没创建高速缓存则返回
  201.     if (unlikely(!obj_cache))
  202.         return;

  203.     //若空闲对象少于最低阀值,则创建新对象链入obj_pool链表中
  204.     while (obj_pool_free < ODEBUG_POOL_MIN_LEVEL) {    
  205.         new = kmem_cache_zalloc(obj_cache, gfp);
  206.         if (!new)
  207.             return;
  208.         
  209.         raw_spin_lock_irqsave(&pool_lock, flags);
  210.         hlist_add_head(&new->node, &obj_pool);
  211.         obj_pool_free++;
  212.         raw_spin_unlock_irqrestore(&pool_lock, flags);
  213.     }
  214. }

  215. static struct debug_bucket *get_bucket(unsigned long addr)
  216. {
  217.     unsigned long hash;
  218.         
  219.     hash = hash_long((addr >> ODEBUG_CHUNK_SHIFT), ODEBUG_HASH_BITS);
  220.     return &obj_hash[hash];
  221. }

  222. static struct debug_obj *lookup_object(void *addr, struct debug_bucket *b)
  223. {
  224.     struct debug_obj *obj;
  225.     int cnt = 0;
  226.     
  227.     //遍历该debug_bucket对象上挂载的debug_obj对象
  228.     hlist_for_each_entry(obj, &b->list, node) {
  229.         cnt++;
  230.         //地址相等即找到相应的debug_obj对象
  231.         if (obj->object == addr)
  232.             return obj;
  233.     }
  234.     
  235.     //更新debug_bucket对象上挂载的debug_obj对象最大值
  236.     if (cnt > debug_objects_maxchain)
  237.         debug_objects_maxchain = cnt;
  238.         
  239.     return NULL;
  240. }

  241. static struct debug_obj *alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr)
  242. {
  243.     struct debug_obj *obj = NULL;
  244.         
  245.     raw_spin_lock(&pool_lock);
  246.     if (obj_pool.first) {
  247.         //从obj_pool链表中取出一个debug_obj对象
  248.         obj    = hlist_entry(obj_pool.first, typeof(*obj), node);
  249.         
  250.         //对该对象初始化
  251.         obj->object = addr;    //debug的地址
  252.         obj->descr = descr;//调试的描述符结构体
  253.         obj->state = ODEBUG_STATE_NONE;//设置状态
  254.         obj->astate = 0;
  255.         //从obj_pool链表中删除
  256.         hlist_del(&obj->node);
  257.         //链入debug_bucket对象的list节点
  258.         hlist_add_head(&obj->node, &b->list);
  259.         
  260.         //更新一些变量
  261.         obj_pool_used++;
  262.         if (obj_pool_used > obj_pool_max_used)
  263.             obj_pool_max_used = obj_pool_used;
  264.         
  265.         obj_pool_free--;
  266.         if (obj_pool_free < obj_pool_min_free)
  267.             obj_pool_min_free = obj_pool_free;
  268.     }
  269.     raw_spin_unlock(&pool_lock);
  270.         
  271.     return obj;
  272. }

  273. 3. 使能addr对应的debug_obj
  274. int debug_object_activate(void *addr, struct debug_obj_descr *descr)
  275. {
  276.     enum debug_obj_state state;
  277.     struct debug_bucket *db;
  278.     struct debug_obj *obj;
  279.     unsigned long flags;
  280.     int ret;
  281.     struct debug_obj o = {    .object = addr,
  282.                             .state = ODEBUG_STATE_NOTAVAILABLE,
  283.                             .descr = descr };
  284.     
  285.     //没有使能debug功能则返回    
  286.     if (!debug_objects_enabled)
  287.         return 0;
  288.     //根据要debug的地址通过hash算法得到debug_bucket对象
  289.     db = get_bucket((unsigned long) addr);    
  290.     raw_spin_lock_irqsave(&db->lock, flags);

  291.     //根据debug地址到obj_pool查找一个debug_obj对象        
  292.     obj = lookup_object(addr, db);

  293.     //将debug_obj对象状态设置为ODEBUG_STATE_ACTIVE
  294.     if (obj) {
  295.         switch (obj->state) {
  296.         case ODEBUG_STATE_INIT:
  297.         case ODEBUG_STATE_INACTIVE:
  298.             obj->state = ODEBUG_STATE_ACTIVE;
  299.             ret = 0;
  300.             break;
  301.         
  302.         case ODEBUG_STATE_ACTIVE:
  303.             debug_print_object(obj, "activate");
  304.             state = obj->state;
  305.             raw_spin_unlock_irqrestore(&db->lock, flags);
  306.             ret = debug_object_fixup(descr->fixup_activate, addr, state);
  307.             return ret ? -EINVAL : 0;
  308.         
  309.         case ODEBUG_STATE_DESTROYED:
  310.             debug_print_object(obj, "activate");
  311.             ret = -EINVAL;
  312.             break;
  313.         default:
  314.             ret = 0;
  315.             break;
  316.         }
  317.         raw_spin_unlock_irqrestore(&db->lock, flags);
  318.         return ret;
  319.     }

  320.     raw_spin_unlock_irqrestore(&db->lock, flags);

  321.     if (debug_object_fixup(descr->fixup_activate, addr,ODEBUG_STATE_NOTAVAILABLE)) {
  322.         debug_print_object(&o, "activate");
  323.         return -EINVAL;
  324.     }
  325.     return 0;
  326. }


  327. 4. 用于检查addr对应的debug_obj对象的状态是否正确
  328. static int __init check_results(void *addr, enum debug_obj_state state, int fixups, int warnings)


上一篇:arm linux启动流程三
下一篇:arm linux启动流程五