热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Linux中的mutex机制[二]解锁和wwmutex

【解锁过程】mutex同spinlock一样,必须由持有lock的线程来释放这个lock

【解锁过程】

mutex同spinlock一样,必须由持有lock的线程来释放这个lock。如果当前没有其他线程在等待,那么"owner"的低3个bits为0,"owner"的值也就直接等于当前线程的"task_struct"指针的值,此时释放mutex要做的只是将"owner"的值设为0。

bool __mutex_unlock_fast(struct mutex *lock)
{
if (atomic_long_cmpxchg_release(&lock->owner, curr, 0UL) == curr)
return true;
...
}
如果有线程在等待,那么释放mutex时需要保留"owner"中作为标志位的低3个bits。

void __sched __mutex_unlock_slowpath(struct mutex *lock, ...)
{
// 释放mutex,同时获取记录状态的低3个标志位
unsigned long old
= atomic_long_cmpxchg_release(&lock->owner,
owner
, __owner_flags(owner));
...
spin_lock(&lock->wait_lock);
if (!list_empty(&lock->wait_list)) {
// 获取等待队列中的第一个线程
struct mutex_waiter *waiter = list_first_entry
(&lock->wait_list, struct mutex_waiter, list);

// 将该线程加入wake_q
struct task_struct *next = waiter->task;
wake_q_add(&wake_q, next);
}

spin_unlock(&lock->wait_lock);

// 唤醒该线程
wake_up_q(&wake_q);
}
获取"wait_list"队列头部的等待线程,并调用wake_up_q()唤醒该线程。

【死锁问题】

Linux内核中的mutex同spinlock一样,也存在AB-BA的死锁问题。前面讨论spinlock的AB-BA死锁时曾讲到,在这个时候,如果其中一方能主动让出自己持有的锁,「僵局」就可以迎刃而解。

2013年,Marten Lankhorst基于普通的mutex开发了一种新的机制。如下图所示,当检测到发生死锁时,Task-2主动unlock(B),那么Task-1就可以继续往下执行,Task-1执行完后释放lock B和lock A,那么Task-2也可以继续往下执行。

这种机制被命名为"ww-mutex",其中"ww"代表Wound-Wait,可理解为是主动让出mutex的一方在“受伤地等待”,不过一方受伤总比双方都死掉好。ww-mutex需要能够识别mutex获取路径的依赖,并制定一套选择哪个线程作为让出一方的规则。

struct ww_mutex {
struct mutex base;
struct ww_acquire_ctx *ctx;
};
此外,ww-mutex还支持按stamp,而不是FIFO的顺序选择等待队列中的waiter。这样可以避免上文所说的“较晚进入等待的spinner先于较早进入等待的waiter获得mutex”的情况,当一个线程发现有比它自己的stamp更早的waiter存在,它就不会成为spinner。

bool ww_mutex_spin_on_owner(...)
{
if (!waiter && (atomic_long_read(&lock->owner) & MUTEX_FLAG_WAITERS))
return false;
...
}
【spinlock和mutex】

Linux中的spinlock和mutex机制都介绍完了,下面通过对比来说明两者分别适合于什么样的应用场景。

spinlock的开销在于暂时获取不到锁时,对所在CPU的持续占有,而传统的mutex的开销则在于释放CPU和重新获取CPU所带来的上下文切换。不过,现在的mutex设计已经通过optimistic spinning糅合了spinlock的行为,在资源不足时是否主动让出CPU已经不再构成两者真正的区别。

两者语义上的差异(或者说spinlock和mutex能同时存在的原因)是在线程试图获取和持有spinlock期间,调度都是关闭的,因而要求临界区的执行时间必须较短。相比而言,使用mutex的限制条件更加宽松。如果支持的操作可能会导致睡眠,比如copy_from_user()或者kmalloc(GFP_KERNEL),则只能使用mutex。



推荐阅读
  • 主函数:CStringGetCPUIDString()Copyright(C)shangweixiao2011 ... [详细]
  • 面试题总结_2019年全网最热门的123个Java并发面试题总结
    面试题总结_2019年全网最热门的123个Java并发面试题总结 ... [详细]
  • 普通树(每个节点可以有任意数量的子节点)级序遍历 ... [详细]
  • 深入解析C语言中结构体的内存对齐机制及其优化方法
    为了提高CPU访问效率,C语言中的结构体成员在内存中遵循特定的对齐规则。本文详细解析了这些对齐机制,并探讨了如何通过合理的布局和编译器选项来优化结构体的内存使用,从而提升程序性能。 ... [详细]
  • 本文探讨了如何通过编程手段在Linux系统中禁用硬件预取功能。基于Intel® Core™微架构的应用性能优化需求,文章详细介绍了相关配置方法和代码实现,旨在帮助开发人员有效控制硬件预取行为,提升应用程序的运行效率。 ... [详细]
  • 深入解析Android 4.4中的Fence机制及其应用
    在Android 4.4中,Fence机制是处理缓冲区交换和同步问题的关键技术。该机制广泛应用于生产者-消费者模式中,确保了不同组件之间高效、安全的数据传输。通过深入解析Fence机制的工作原理和应用场景,本文探讨了其在系统性能优化和资源管理中的重要作用。 ... [详细]
  • 在 Linux 环境下,多线程编程是实现高效并发处理的重要技术。本文通过具体的实战案例,详细分析了多线程编程的关键技术和常见问题。文章首先介绍了多线程的基本概念和创建方法,然后通过实例代码展示了如何使用 pthreads 库进行线程同步和通信。此外,还探讨了多线程程序中的性能优化技巧和调试方法,为开发者提供了宝贵的实践经验。 ... [详细]
  • ipsec 加密流程(二):ipsec初始化操作
    《openswan》专栏系列文章主要是记录openswan源码学习过程中的笔记。Author:叨陪鲤Email:vip_13031075266163.comDate:2020.1 ... [详细]
  • PBO(PixelBufferObject),将像素数据存储在显存中。优点:1、快速的像素数据传递,它采用了一种叫DMA(DirectM ... [详细]
  • 华为捐赠欧拉操作系统,承诺不推商用版
    华为近日宣布将欧拉开源操作系统捐赠给开放原子开源基金会,并承诺不会推出欧拉的商用发行版。此举旨在推动欧拉和鸿蒙操作系统的全场景融合与生态发展。 ... [详细]
  • 单片微机原理P3:80C51外部拓展系统
      外部拓展其实是个相对来说很好玩的章节,可以真正开始用单片机写程序了,比较重要的是外部存储器拓展,81C55拓展,矩阵键盘,动态显示,DAC和ADC。0.IO接口电路概念与存 ... [详细]
  • Java高并发与多线程(二):线程的实现方式详解
    本文将深入探讨Java中线程的三种主要实现方式,包括继承Thread类、实现Runnable接口和实现Callable接口,并分析它们之间的异同及其应用场景。 ... [详细]
  • 深入解析 Synchronized 锁的升级机制及其在并发编程中的应用
    深入解析 Synchronized 锁的升级机制及其在并发编程中的应用 ... [详细]
  • 性能测试中的关键监控指标与深入分析
    在软件性能测试中,关键监控指标的选取至关重要。主要目的包括:1. 评估系统的当前性能,确保其符合预期的性能标准;2. 发现软件性能瓶颈,定位潜在问题;3. 优化系统性能,提高用户体验。通过综合分析这些指标,可以全面了解系统的运行状态,为后续的性能改进提供科学依据。 ... [详细]
  • 在Linux系统中,通过命令行查询计算机硬件配置是一项重要的技能。本文介绍了多种实用的命令和技巧,帮助用户高效地获取硬件信息。例如,可以通过 `cat /proc/cpuinfo | grep "physical id"` 命令来查看物理CPU的数量。此外,文章还涵盖了其他关键硬件组件的查询方法,如内存、磁盘和网络设备等。这些命令不仅适用于系统管理员,也适合普通用户了解自己的系统配置。 ... [详细]
author-avatar
胖蚂蚁
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有