Chinaunix首页 | 论坛 | 博客
  • 博客访问: 24465
  • 博文数量: 10
  • 博客积分: 1410
  • 博客等级: 上尉
  • 技术积分: 110
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-13 22:17
文章分类
文章存档

2011年(1)

2009年(9)

我的朋友
最近访客

分类: C/C++

2009-08-27 18:48:58

多线程程序中, 经常遇到线程死锁的问题。
出现死锁的状况,很多时候像盲人摸象般的加调试信息,看程序“已经跑在哪里”了。
但同时,也需要这个死锁能经常不断的出现,才能找到问题所在。

利用调试器提供的便利,我们可以找到更好地解决办法。
下面的过程中,逐鹿使用的是一个AXD调试器,对象程序是ARM的eCos程序,
其中几个线程不见动静(已经死锁)。
于是选择其中一个线程,定位该线程死锁的位置。


1. 找到该线程的stack位置

对照程序源代码,不难发现线程的thread handle变量名,在调试器的symbol窗口中查看变量的地址。
暂停程序运行,在memory窗口中,定位到该变量地址处,这个地址处保留有一个线程控制块结构,
类型为Cyg_HardwareThread。

class Cyg_HardwareThread
{
    CYG_ADDRESS        stack_base;     // pointer to base of stack area
    cyg_uint32         stack_size;     // size of stack area in bytes
    CYG_ADDRESS        stack_limit;    // movable stack limit
    CYG_ADDRESS        stack_ptr;      // pointer to saved state on stack
    cyg_thread_entry  *entry_point;   // main entry point (code pointer!)
    CYG_ADDRWORD       entry_data;     // entry point argument
    ....
};

从该结构看出,thread handle指向的地址, 加上偏移3 int (24 byte)的地方,
是一个 stack_ptr, 这个stack_ptr即是进程当前的栈顶指针.



2. 找到线程阻塞之前的sp, lr, pc寄存器.

在此利用AXD的查看memory窗口, 定位到stack_ptr的值指向的地址.
这个地址处, 实际上保存着 r0 - r12, sp, lr, pc 一共16个寄存器的内容.

因此sp, lr, pc 分别在 stack_prt指向的地址偏移 13 int, 14 int, 15 int处.
 sp     *( (int*)stack_ptr + 13 )
 lr     *( (int*)stack_ptr + 14 )
 pc     *( (int*)stack_ptr + 15 )



3. 察看线程阻塞之前的函数调用现场

有了sp, lr, pc, 接下来的事情就容易了.
查看当前寄存器窗口, 先记录下当前的 sp(r13), lr(r14) 和 pc的值,
将第2步找到的死锁线程的sp, lr, pc值填进去。
然后,打开BackTrace窗口。不出所料,线程的函数调用栈一目了然,
从哪里调进来,走到哪步不动,全部清清楚楚。
至此,我们圆满完成调试。

(如果还需要继续运行程序调试,继续之前别忘了将旧的sp,lr和pc重填回去,呵呵)


阅读(660) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:写个web server,有点小必要

给主人留下些什么吧!~~