mutex互斥锁 - linux内核锁(四)

头文件
#include <linux/mutex.h>
定义并初始化
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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值