同步 -- 互斥锁

 本篇文章基于Linux-6.5源码

建议:搭配Linux源码观看更佳

struct mutex {
	atomic_long_t		owner;
	spinlock_t		wait_lock; //自旋锁,该自旋锁的作用是保护后面的等待队列的原子性
	struct list_head	wait_list; //等待队列
};

API接口

mutex_init

互斥锁初始化比较简单,就是把owner,wait_lock,wait_list这几个成员初始化一下

#define mutex_init(mutex)						\
do {									\
	static struct lock_class_key __key;				\
									\
	__mutex_init((mutex), #mutex, &__key);				\
} while (0)

void __mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key)
{
	atomic_long_set(&lock->owner, 0);//初始化锁的所有者
	spin_lock_init(&lock->wait_lock);//初始化自旋锁
	INIT_LIST_HEAD(&lock->wait_list);//初始化等待队列
}

mutex_lock

加锁:mutex_lock

void __sched mutex_lock(struct mutex *lock)
{
	might_sleep();
    //尝试直接加锁,如果不成功,则进入slowpath,
	if (!__mutex_trylock_fast(lock))
		__mutex_lock_slowpath(lock);
}
EXPORT_SYMBOL(mutex_lock);


static __always_inline bool __mutex_trylock_fast(struct mutex *lock)
{
	unsigned long curr = (unsigned long)current;//sp_el0,指向当前进程的task_struct
	unsigned long zero = 0UL;

	//判断owner是否为0,如果为0表示当前锁没有被占用,则把current写入owner返回true表示加锁成功
	if (atomic_long_try_cmpxchg_acquire(&lock->owner, &zero, curr))
		return true;
	//owner不为0,表示锁被占用了,返回false
	return false;
}

__mutex_lock_slowpath(慢加锁)中执行的过程大概是:

mutex_unlock

解锁:mutex_unlock

void __sched mutex_unlock(struct mutex *lock)
{
#ifndef CONFIG_DEBUG_LOCK_ALLOC
	if (__mutex_unlock_fast(lock))
		return;
#endif
	__mutex_unlock_slowpath(lock, _RET_IP_);
}
EXPORT_SYMBOL(mutex_unlock);

__mutex_unlock_fast(快解锁):比较lock->owner和curr是否一致,一致则直接把0写到lock->owner中,表示解锁。

__mutex_unlock_slowpath:等待队列的第一个对象出列,表示下一个将要获得锁的任务。把下一个任务的task_struct地址写入到mutex lock的owner变量中(相当于下一个任务获得了互斥锁),唤醒下一个任务继续执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值