定时器问题请教高手
zx77 2002-12-16 04:25:58 各位高手,我现在遇到一个让人迷惑的问题。(Kernel version 2.2.19)
我的程序结构是这样的:
1. 有一个HashTable,其节点上有一个timer_list结构,还有一个id号以及一些我用的属性。
2. 有一个通用的delete函数,它做如下操作:
a. 先cli关中断。
b. 如果timer_list不为空,则调用del_timer将其删除。
c. 用一个全局变量记录下id(这是我后来为了debug而加上的)。
d. 将id清空为0。
e. 将该节点从HashTable中去掉。
f. restore_flags开中断。
g. 调用kfree_s释放该节点。
3. 在新建节点时,用add_timer设置timer_list,定时器函数为delete函数。也就是说,delete将在timer_bh里运行。
4. 在net_bh中,有些特殊的时候,我也会直接调用delete函数来删除节点。由于考虑到net_bh和timer_bh应该是不会重入的,所以我认为这没有问题。
5. 实际运行中,当系统在大负荷运行下,有时会出现死机,通过LKCD的分析,发现,都死在delete函数的kfree_s处,而节点的数据都没错,唯一奇怪的是在进入delete函数时,id已经为0了,说明以前被删除过。但从代码中我实在是分析不出有什么问题了。
希望高手能解答。谢谢!
void node_delete(struct node *pnode)
{
unsigned long flags;
save_flags(flags);
cli();
if (pnode->timer_set) {
del_timer(&pnode->timer);
pnode->timer_set = 0;
}
// this is for LKCD dump debug
global_debug = pnode->id;
pnode->id = 0;
// now I unlink the node from HashTable
...
restore_flags(flags);
// do some other things
...
kfree_s(pnode, sizeof(struct node));
}
struct node * node_insert(...)
{
__u32 key = NODE_KEY(...);
struct node *pnode;
unsigned long flags;
if ((pnode = (struct node *)kmalloc(sizeof(struct node), GFP_ATOMIC)) == NULL) {
return NULL;
}
memset(pnode, 0, sizeof(struct node));
// now i set some basic properties
...
init_timer(&pnode->timer); // timer is a member of struct node, its type is timer_list
set_node_timer(pnode, MY_TIMEOUT);
save_flags(flags);
cli();
// link this into HashTable
...
// gen unique id of node, based on 1, 0 means invalid
...
restore_flags(flags);
return pnode;
}
inline void set_node_timer(struct node *pnode, unsigned long when)
{
unsigned long flags;
if (NULL == pnode) {
return;
}
save_flags(flags);
cli();
if (pnode->timer_set) {
del_timer(&pnode->timer);
}
pnode->timer.expires = jiffies + when;
pnode->timer.data = (unsigned long) pnode;
pnode->timer.function = (node_expire) node_delete;
pnode->timer_set = 1;
add_timer(pnode->timer);
restore_flags(flags);
}
// myfun() is called by net_bh in some cases
void myfun()
{
// some other operations
if (some_case) {
node_delete(pnode);
// I found someone says that del_timer may not success in 2.2.x
// so if it's real, that my process may die, but I didn't so sure
// does anyone know something else?
// ref to http://www.uwsg.iu.edu/hypermail/linux/kernel/0005.3/0269.html
}
// other operations...
}