转载请注明出处: http://blog.csdn.net/luotuo44/article/details/38360525
Debug锁操作:
Libevent还支持对锁操作的一些检测,进而捕抓一些典型的锁错误。Libevent检查:
- 解锁自己(线程)没有持有的锁
- 在未解锁前,自己(线程)再次锁定一个非递归锁。
Libevent通过一些变量记录锁的使用情况,当检查到这些锁的错误使用时,就调用abort,退出运行。
开启调试功能:
用户只需在调用evthread_use_pthreads或者evthread_use_windows_threads之后,调用evthread_enable_lock_debuging()函数即可开启调试锁的功能。该函数有一个拼写错误。在2.1.2-alpha版本中会改正为evthread_enable_lock_debugging,为了后向兼容,两者都会支持的。
现在看一下Libevent是锁调试功能。
//evthread.c文件
void
evthread_enable_lock_debuging(void)
{
struct evthread_lock_callbacks cbs = {
EVTHREAD_LOCK_API_VERSION,
EVTHREAD_LOCKTYPE_RECURSIVE,
debug_lock_alloc,
debug_lock_free,
debug_lock_lock,
debug_lock_unlock
};
if (_evthread_lock_debugging_enabled)
return;
//把当前用户定制的锁操作复制到_original_lock_fns结构体变量中。
memcpy(&_original_lock_fns, &_evthread_lock_fns,
sizeof(struct evthread_lock_callbacks));
//将当前的锁操作设置成调试锁操作。但调试锁操作函数内部
//还是使用_original_lock_fns的锁操作函数
memcpy(&_evthread_lock_fns, &cbs,
sizeof(struct evthread_lock_callbacks));
memcpy(&_original_cond_fns, &_evthread_cond_fns,
sizeof(struct evthread_condition_callbacks));
_evthread_cond_fns.wait_condition = debug_cond_wait;
_evthread_lock_debugging_enabled = 1;
/* XXX return value should get checked. */
event_global_setup_locks_(0);
}
在上面代码的注释可以知道,虽然evthread_lock_fns的值被更新为debug_lock_alloc、debug_lock_lock和debug_lock_unlock。但实际上,使用的还是之前用户定制的线程锁操作函数,只是加多了一层抽象而已。如果看不懂这段话,可以看下面的代码,看完已经就会懂的了。
//evthread.c文件
static void *
debug_lock_alloc(unsigned locktype)
{
struct debug_lock *result = mm_malloc(sizeof(struct debug_lock));
if (!result)
return NULL;
//用户设置过自己的线程锁函数
if (_original_lock_fns.alloc) {
//用用户定制的线程锁函数分配一个线程锁
if (!(result->lock = _original_lock_fns.alloc(
locktype|EVTHREAD_LOCKTYPE_RECURSIVE))) {
mm_free(result);
return NULL;
}
} else {
result->lock = NULL;
}
result->locktype = locktype;
result->count = 0;
result->held_by = 0;
return result;
}
现在看看Libevent是怎么调试(更准确来说,应该是检测)锁的。锁的检测,需要用到debug_lock 结构体,它对锁的一些使用状态进行了记录。
debug递归锁:
//evth