头文件
#include
定义并初始化
struct mutex mutex;
mutex_init(&cm_dev->mutex);
一 相关操作
mutex_lock:加锁
/**
* mutex_lock - acquire the mutex
* @lock: the mutex to be acquired
*
* Lock the mutex exclusively for this task. If the mutex is not
* available right now, it will sleep until it can get it.
*
* The mutex must later on be released by the same task that
* acquired it. Recursive locking is not allowed. The task
* may not exit without first unlocking the mutex. Also, kernel
* memory where the mutex resides must not be freed with
* the mutex still locked. The mutex must first be initialized
* (or statically defined) before it can be locked. memset()-ing
* the mutex to 0 is not allowed.
*
* ( The CONFIG_DEBUG_MUTEXES .config option turns on debugging
* checks that will enforce the restrictions and will also do
* deadlock debugging. )
*
* This function is similar to (but not equivalent to) down().
*/
void __sched mutex_lock(struct mutex *lock)
{
might_sleep();
/*
* The locking fastpath is the 1->0 transition from
* 'unlocked' into 'locked' state.
*/
__mutex_fastpath_lock(&lock->count, __mutex_lock_slowpath);
mutex_set_owner(lock);
}
mutex_trylock:尝试加锁
上锁失败返回0,成功返回1,本次实验中,循环判断上锁
while(mutex_trylock(&cm_dev->mutex) == 0){
msleep(1);
}
/**
* mutex_trylock - try to acquire the mutex, without waiting
* @lock: the mutex to be acquired
*
* Try to acquire the mutex atomically. Returns 1 if the mutex
* has been acquired successfully, and 0 on contention.
*
* NOTE: this function follows the spin_trylock() convention, so
* it is negated from the down_trylock() return values! Be careful
* about this when converting semaphore users to mutexes.
*
* This function must not be used in interrupt context. The
* mutex must be released by the same task that acquired it.
*/
int __sched mutex_trylock(struct mutex *lock)
{
int ret;
ret = __mutex_fastpath_trylock(&lock->count, __mutex_trylock_slowpath);
if (ret)
mutex_set_owner(lock);
return ret;
}
mutex_unlock:解锁
/**
* mutex_unlock - release the mutex
* @lock: the mutex to be released
*
* Unlock a mutex that has been locked by this task previously.
*
* This function must not be used in interrupt context. Unlocking
* of a not locked mutex is not allowed.
*
* This function is similar to (but not equivalent to) up().
*/
void __sched mutex_unlock(struct mutex *lock)
{
/*
* The unlocking fastpath is the 0->1 transition from 'locked'
* into 'unlocked' state:
*/
#ifndef CONFIG_DEBUG_MUTEXES
/*
* When debugging is enabled we must not clear the owner before time,
* the slow path will always be taken, and that clears the owner field
* after verifying that it was indeed current.
*/
mutex_clear_owner(lock);
#endif
__mutex_fastpath_unlock(&lock->count, __mutex_unlock_slowpath);
}
实例验证:
static int
cm_thread_1(void *arg)
{
int ret = 0;
int send_count = 0;
struct buf_node *pnode;
struct cm_dev_ *cm_dev = (struct cm_dev_ *)arg;
wait_queue_t wait = __WAITQUEUE_INITIALIZER(wait, current);
DEBUG_CM("");
while(mutex_trylock(&cm_dev->mutex) == 0){
msleep_interruptible(1);
}
add_wait_queue(&cm_dev->w_wait,&wait);
mutex_unlock(&cm_dev->mutex);
DEBUG_CM("");
while(1){
DEBUG_CM("");
if(kthread_should_stop()){
DEBUG_CM("exit thread");
break;
}
DEBUG_CM("");
while(mutex_trylock(&cm_dev->mutex) == 0){
msleep_interruptible(1);
}
while(cm_list_size(&cm_dev->ready_list) == 0){
mutex_unlock(&cm_dev->mutex);
DEBUG_CM("");
set_current_state(TASK_INTERRUPTIBLE);
schedule();
ret = signal_pending(current);
if(ret){
DEBUG_CM("ret = %d",ret);
while(mutex_trylock(&cm_dev->mutex) == 0){
msleep_interruptible(1);
}
continue;
}
//执行kthread_stop函数后,也会调度该线程,此时signal_pending也是0
if(kthread_should_stop()){
DEBUG_CM("exit thread");
goto end_thread_1;
}
while(mutex_trylock(&cm_dev->mutex) == 0){
msleep_interruptible(1);
}
}
mutex_unlock(&cm_dev->mutex);
++send_count;
DEBUG_CM("send a string:%d",send_count);
while(mutex_trylock(&cm_dev->mutex) == 0){
msleep_interruptible(1);
}
if(cm_list_size(&cm_dev->ready_list) > 0){
pnode = pop_list(&cm_dev->ready_list);
sprintf(pnode->buf,"send_count:%d",send_count);
list_add_tail(&pnode->node,&cm_dev->ok_list);
wake_up_interruptible(&cm_dev->r_wait);
}else{
DEBUG_CM("ready_list size == 0");
}
mutex_unlock(&cm_dev->mutex);
DEBUG_CM("");
}
end_thread_1:
remove_wait_queue(&cm_dev->w_wait,&wait);
return 0;
}
static int
cm_thread_2(void *arg)
{
int ret = 0;
int send_count = 0;
struct buf_node *pnode;
struct cm_dev_ *cm_dev = (struct cm_dev_ *)arg;
wait_queue_t wait = __WAITQUEUE_INITIALIZER(wait, current);
while(mutex_trylock(&cm_dev->mutex) == 0){
msleep_interruptible(1);
}
add_wait_queue(&cm_dev->r_wait,&wait);
mutex_unlock(&cm_dev->mutex);
while(1){
if(kthread_should_stop()){
DEBUG_CM("exit thread");
break;
}
while(mutex_trylock(&cm_dev->mutex) == 0){
msleep_interruptible(1);
}
while(cm_list_size(&cm_dev->ok_list) == 0){
mutex_unlock(&cm_dev->mutex);
set_current_state(TASK_INTERRUPTIBLE);
schedule();
ret = signal_pending(current);
if(ret){
DEBUG_CM("ret = %d",ret);
while(mutex_trylock(&cm_dev->mutex) == 0){
msleep_interruptible(1);
}
continue;
}
//执行kthread_stop函数后,也会调度该线程,此时signal_pending也是0
if(kthread_should_stop()){
DEBUG_CM("exit thread");
goto end_thread_2;
}
while(mutex_trylock(&cm_dev->mutex) == 0){
msleep_interruptible(1);
}
}
mutex_unlock(&cm_dev->mutex);
++send_count;
while(mutex_trylock(&cm_dev->mutex) == 0){
msleep_interruptible(1);
}
if(cm_list_size(&cm_dev->ok_list) > 0){
DEBUG_CM("send a string:%d",send_count);
pnode = pop_list(&cm_dev->ok_list);
DEBUG_CM("pnode->buf = %s",pnode->buf);
list_add_tail(&pnode->node,&cm_dev->ready_list);
wake_up_interruptible(&cm_dev->w_wait);
}else{
DEBUG_CM("ready_list size == 0");
}
mutex_unlock(&cm_dev->mutex);
}
end_thread_2:
remove_wait_queue(&cm_dev->r_wait,&wait);
return 0;
}
输出结果:截取一段
[ 26.240569] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_1:182:
[ 26.246527] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_1:136:
[ 26.252454] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_1:141:
[ 26.258418] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_2:240: send a string:94
[ 26.265775] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_2:242: pnode->buf = send_count:94
[ 26.283228] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_1:169: send a string:95
[ 26.290566] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_1:182:
[ 26.296521] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_1:136:
[ 26.302448] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_1:141:
[ 26.308411] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_2:240: send a string:95
[ 26.315763] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_2:242: pnode->buf = send_count:95
[ 26.333223] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_1:169: send a string:96
[ 26.340564] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_1:182:
[ 26.346525] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_1:136:
[ 26.352455] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_1:141:
[ 26.358419] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_2:240: send a string:96
[ 26.365777] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_2:242: pnode->buf = send_count:96
[ 26.383230] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_1:169: send a string:97
[ 26.390571] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_1:182:
[ 26.396525] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_1:136:
[ 26.402453] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_1:141:
[ 26.408418] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_2:240: send a string:97
[ 26.415775] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_2:242: pnode->buf = send_count:97
[ 26.433223] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_1:169: send a string:98
[ 26.440560] /big/csi_driver/csi_buf/csi_buf.c:cm_thread_1:182:
————————————————
版权声明:本文为CSDN博主「千册」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yueni_zhao/article/details/127416219