Linux中RT-Mutex实现
创始人
2024-09-25 17:46:17
0

    本文主要梳理优先级继承的基本原理,优先级继承主要是用来解决优先级反转,可以简单理解为

一个进程在当前进程拥有的锁上阻塞时,会继承另一个进程的优先级。举个例子说明,进程A、

B、C,其中A优先级最高,B次之,C最小,那么当 A 在 C 拥有的锁上阻塞时,C 将继承 A 的优先

级。因此,如果 B 变为可运行状态,它将不会抢占 C,因为此时 C 具有 A 的高优先级。一旦 C 释

放锁,它将失去继承的优先级,然后 A 可以继续使用 C 拥有的资源。

在linux源码实现中,位置:kernel/locking/rtmutex.c,主要涉及到两个重要步骤:

1、优先级调整;

2、PI(优先级继承)链遍历

优先级调整

该部分实现任务调整的函数分别是rt_mutex_adjust_prio和rt_mutex_setprio,其中

rt_mutex_setprio在rt_mutex_adjust_prio中被调用,rt_mutex_setprio的实现则实在

kernel/sched/core.c中。

static void rt_mutex_adjust_prio(struct task_struct *p)   {       struct task_struct *pi_task = NULL;        lockdep_assert_held(&p->pi_lock); // 确保 pi_lock 被持有        // 检查是否有其他任务在等待该实时互斥锁       if (task_has_pi_waiters(p))           pi_task = task_top_pi_waiter(p)->task; // 获取优先级继承任务        // 调整优先级       rt_mutex_setprio(p, pi_task);   }   

        rt_mutex_adjust_prio检查任务的优先级以及等待任务拥有的所有互斥锁中最高优先级的进

程。然后调用rt_mutex_setprio来将任务的优先级调整为新的优先级。

总的来说rt_mutex_adjust_prio可以增加或降低任务的优先级。如果更高优先级的进程刚好在任务

拥有的互斥锁上阻塞,rt_mutex_adjust_prio将增加/提升任务的优先级。但是,如果由于某种原因

更高优先级的任务离开了互斥锁(超时或信号),则该函数将降低任务的优先级。

void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task) { 	int prio, oldprio, queued, running, queue_flag = 		DEQUEUE_SAVE | DEQUEUE_MOVE | DEQUEUE_NOCLOCK; 	const struct sched_class *prev_class; 	struct rq_flags rf; 	struct rq *rq;  	trace_android_rvh_rtmutex_prepare_setprio(p, pi_task);//记录优先级变化 	/* XXX used to be waiter->prio, not waiter->task->prio */ 	prio = __rt_effective_prio(pi_task, p->normal_prio);//获取到任务的优先级  	if (p->pi_top_task == pi_task && prio == p->prio && !dl_prio(prio)) 		return;  	rq = __task_rq_lock(p, &rf); 	update_rq_clock(rq);  	p->pi_top_task = pi_task;  	if (prio == p->prio && !dl_prio(prio))//如果新的优先级和旧的优先级相同 		goto out_unlock;  	if (unlikely(p == rq->idle)) { //如果是空闲任务 		WARN_ON(p != rq->curr); 		WARN_ON(p->pi_blocked_on); 		goto out_unlock; 	}  	trace_sched_pi_setprio(p, pi_task); 	oldprio = p->prio;  	if (oldprio == prio) 		queue_flag &= ~DEQUEUE_MOVE;  	prev_class = p->sched_class; 	queued = task_on_rq_queued(p); 	running = task_current(rq, p); 	if (queued) 		dequeue_task(rq, p, queue_flag); 	if (running) 		put_prev_task(rq, p);  	if (dl_prio(prio)) { 		if (!dl_prio(p->normal_prio) || 		    (pi_task && dl_prio(pi_task->prio) && 		     dl_entity_preempt(&pi_task->dl, &p->dl))) { 			p->dl.pi_se = pi_task->dl.pi_se; 			queue_flag |= ENQUEUE_REPLENISH; 		} else { 			p->dl.pi_se = &p->dl; 		} 	} else if (rt_prio(prio)) { 		if (dl_prio(oldprio)) 			p->dl.pi_se = &p->dl; 		if (oldprio < prio) 			queue_flag |= ENQUEUE_HEAD; 	} else { 		if (dl_prio(oldprio)) 			p->dl.pi_se = &p->dl; 		if (rt_prio(oldprio)) 			p->rt.timeout = 0; 	}  	__setscheduler_prio(p, prio);  	if (queued) 		enqueue_task(rq, p, queue_flag); 	if (running) 		set_next_task(rq, p);  	check_class_changed(rq, p, prev_class, oldprio); out_unlock: 	/* Avoid rq from going away on us: */ 	preempt_disable();  	rq_unpin_lock(rq, &rf); 	__balance_callbacks(rq); 	raw_spin_unlock(&rq->lock);  	preempt_enable(); }

        rt_mutex_setprio函数通过允许高优先级任务抢占持有它们所需资源的低优先级任务,维护系

统的响应性,即执行优先级继承和实时调度的原则。

PI(优先级继承)链遍历

        PI链遍历由函数rt_mutex_adjust_prio_chain实现,该函数源码较长,本文不进行贴出,对主

要步骤进程阐述:

1、深度检查:

使用变量 depth 跟踪锁的深度。如果超过最大深度(max_lock_depth),则报告死锁并返回错误代码 -EDEADLK。

2、自旋锁保护:

使用自旋锁 (raw_spin_lock_irq) 保护对任务结构体 task 的访问,确保在调整优先级时不会被其他任务打断。

3、等待者检查:

检查当前任务在互斥锁上的阻塞状态 pi_blocked_on。
验证原始等待者 orig_waiter 是否为实时真实等待者,并确保其约束条件满足。

4、锁的重试:

尝试获取锁(raw_spin_trylock),如果失败,则释放自旋锁并让 CPU 空闲,然后重试。

5、处理优先级调整:

如果当前持有者和 next_lock 一致,则判断是否需要返回死锁或进行重排。
如果不需要进行重排,则获取持有者的任务并继续处理。

6、优先级的入队与出队:

调整优先级队列。如果当前任务是锁的顶层等待者,进行相应的优先级调整;如果不是,则进行入队和出队操作。

7、锁的状态更新:

更新当前任务状态以处理后续的锁请求。
 

最后,清理任务结构体,释放锁,并返回处理结果。

相关内容

热门资讯

玩家必看秘籍“来来舟山麻将辅助... 来来舟山麻将辅助开挂教程视频分享装挂详细步骤在当今的网络游戏中,来来舟山麻将辅助作为一种经典的娱乐方...
教程辅助“浙江宝宝游戏辅助工具... 【亲,浙江宝宝游戏辅助工具 这款游戏可以开挂的,确实是有挂的,很多玩家在这款浙江宝宝游戏辅助工具中打...
十分钟辅助“多乐小程序辅助器免... 多乐小程序辅助器免费是一款专注玩家量身打造的游戏记牌类型软件,在多乐小程序辅助器免费这款游戏中我们可...
大神推荐“多乐游戏辅助脚本下载... 您好:这款多乐游戏辅助脚本下载游戏是可以开挂的,确实是有挂的,很多玩家在这款多乐游戏辅助脚本下载游戏...
教程辅助“陕西奇迹打锅子破解”... 较多好评“微乐万能挂官网”开挂(透视)辅助教程 了解更多开挂安装加(136704302)微信号是一款...
四分钟辅助“海贝之城有辅助吗”... 您好:海贝之城有辅助吗这款游戏可以开挂的,确实是有挂的,很多玩家在这款游戏中打牌都会发现很多用户的牌...
研究成果“闲逸辅助神器免费”附... 大家好,今天小编来为大家解答闲逸辅助神器免费这个问题咨询软件客服可以免费测试直接加微信(136704...
教程辅助“潮汕掌上娱脚本”开挂... 教程辅助“潮汕掌上娱脚本”开挂(透视)辅助安装-知乎;无需打开直接搜索加(薇:136704302)咨...
八分钟辅助“潮汕来物局有透视软... 八分钟辅助“潮汕来物局有透视软件吗”开挂(透视)辅助插件存在挂教程-哔哩哔哩1、下载安装好潮汕来物局...
技术分享“陕麻圈延安划水辅助”... 陕麻圈延安划水辅助是一款可以让一直输的玩家,快速成为一个“必胜”的ai辅助神器,有需要的用户可以加我...