mutex_init() / mutex_lock() / mutex_unlock()

2023-11-17

请求

1). 初始化互斥体 -- mutex_init();
2). 获得互斥体 -- mutex_lock();
3). 释放互斥体 -- mutex_unlock();

1.mutex_init(), 注意mutex使用之前都需要先init

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);
#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
        osq_lock_init(&lock->osq);
#endif

        debug_mutex_init(lock, name, key);
}
EXPORT_SYMBOL(__mutex_init);

/**
 * mutex_init - initialize the mutex
 * @mutex: the mutex to be initialized
 *
 * Initialize the mutex to unlocked state.
 *
 * It is not allowed to initialize an already locked mutex.
 */
#define mutex_init(mutex)                                               \
do {                                                                    \
        static struct lock_class_key __key;                             \
                                                                        \
        __mutex_init((mutex), #mutex, &__key);                          \
} while (0)

2.mutex_lock(), 注意看注释说明,
a). 如果mutex已经被其他task获取,那么目前的task先sleep直到获取;
b). mutex不能被嵌套获取;上一个task释放mutex之后,才能被其他的task获取;
c). mutex要先被初始化才能使用;mutex正在使用过程中,其内存不能被释放;

//------kernel4.4------
/**
 * 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);
}

//======kernel4.14======
/**
 * 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();
                
        if (!__mutex_trylock_fast(lock))
                __mutex_lock_slowpath(lock);
}
EXPORT_SYMBOL(mutex_lock);

3. mutex_unlock(), 释放互斥体
a). 释放之前获得的mutex;
b). mutex只有被获得,才能调用这个函数来释放;换言之,如果没有获得,就没有必要做释放的动作;

//======kernel 4.4======
/**
 * 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);
}

EXPORT_SYMBOL(mutex_unlock);

//=======kernel 4.14======
/**     
 * 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)
{
#ifndef CONFIG_DEBUG_LOCK_ALLOC
        if (__mutex_unlock_fast(lock))
                return;
#endif
        __mutex_unlock_slowpath(lock, _RET_IP_);
}       
EXPORT_SYMBOL(mutex_unlock);

 

如果lock只在interrupt handler里使用,则没有必要加。中断handler本身就是不可重入的,不存在竞争。 

static irqreturn_t xxxx_typec_interrupt(int irq, void *data)
{
        struct xxxx_typec *sc = data;
        u32 event;
        int ret;

        //mutex_lock(&sc->lock);
        ret = regmap_read(sc->regmap, XXXX_INT_MASK, &event);
        if (ret)
                goto unlock;

        event &= XXXX_EVENT_MASK;

        ret = regmap_read(sc->regmap, XXXX_STATUS, &sc->state);
        if (ret)
                goto clear_ints;

        sc->state &= XXXX_STATE_MASK;

        if (event & XXXX_ATTACH_INT) {
                ret = XXxx_typec_connect(sc, sc->state);
                if (ret)
                        dev_warn(sc->dev, "failed to register partner\n");
        } else if (event & XXXX_DETACH_INT) {
                xxxx_typec_disconnect(sc, sc->state);
        }

clear_ints:
        regmap_write(sc->regmap, XXXX_INT_CLR, event);
unlock:
        //mutex_unlock(&sc->lock);

        dev_info(sc->dev, "now works as DRP and is in %d state, event %d\n",
                sc->state, event);
        return IRQ_HANDLED;
}


static int xxxx_typec_probe(struct platform_device *pdev)
{
        struct xxxx_typec *sc;
        int ret;

        struct device *dev = &pdev->dev;
        struct device_node *node = pdev->dev.of_node;
        u32 value = 0;

        sc = devm_kzalloc(&pdev->dev, sizeof(*sc), GFP_KERNEL);
        if (!sc)
                return -ENOMEM;

        sc->edev = devm_extcon_dev_allocate(&pdev->dev, xxxx_typec_cable);
        if (IS_ERR(sc->edev)) {
                dev_err(&pdev->dev, "failed to allocate extcon device\n");
                return PTR_ERR();
        }

        ret = devm_extcon_dev_register(&pdev->dev, sc->edev);
        if (ret < 0) {
                dev_err(&pdev->dev, "can't register extcon device: %d\n", ret);
                return ret;
        }

        //mutex_init(&sc->lock);
        sc->dev = &pdev->dev;
        sc->irq = platform_get_irq(pdev, 0);
        ...
        ret = devm_request_threaded_irq(sc->dev, sc->irq, NULL,
                                        xxxx_typec_interrupt,
                                        IRQF_EARLY_RESUME | IRQF_ONESHOT,
                                        dev_name(sc->dev), sc);
        ...
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

mutex_init() / mutex_lock() / mutex_unlock() 的相关文章

  • 内核源码中版本号详解(KERNEL_VERSION & KERNEL_VERSION)

    1 内核源码中版本的定义 VERSION 2 主版本号 PATCHLEVEL 6 主版本号 SUBLEVEL 35 更次的版本号 EXTRAVERSION 7 更更次的版本号 NAME Yokohama 1 内核的版本信息定义在内核源码顶层
  • Kconfig内容(详细)总结附示例快速掌握

    目录 一 简介 二 内容解析 2 1 menuconfig 2 2 choice endchoice 2 3 comment 2 4 menu endmunu 2 5 if endif 2 6 source 2 7 mainmenu 2 8
  • CPU虚拟化技术

    基本概念 物理CPU数量 实际服务器插槽上的CPU个数 核 一块CPU上面能处理数据的芯片组的数量 超线程 在一个实体芯片组中提供两个逻辑线程 逻辑CPU数量 物理CPU数量 核 超线程 若支持超线程 该值为2 vCPU 虚机分配的CPU
  • 读《自己动手写操作系统》(于渊著)第一节

    最近开始看 自己动手写操作系统 虽然很早以前就读过一点点 但一直没有机会动手实践 本着光说不练假把式的原则 今天动手实践了开头的一部分 说得这么正经其实你就是看了一点点吧 囧 废话不多说 在这里做一个小小的总结 实验环境 操作系统 win7
  • 树莓派基于Linux内核驱动开发详解

    目录 一 驱动认知 1 1 为什么要学习写驱动 1 2 文件名与设备号 1 3 open函数打通上层到底层硬件的详细过程 二 基于框架编写驱动代码 2 1 编写上层应用代码 2 2 修改内核驱动框架代码 2 3 部分代码解读 2 3 1 s
  • 内核调试手段

    1 内核调试配置选项 内核拥有多项用于调试的功能 但是这些功能会造成额外的输出并导致性能下降 因此 内核通常都是禁止掉调试功能 内核调试相关的配置项主要集中在内核配置菜单 Kernel hacking 中 在使用下面的调试手段时 先确保内核
  • 为何 Linus 一个人就能写出这么强的系统,国人却做不出来?

    点上方蓝色 菜鸟学Python 选 星标 公众号 重磅干货 第一时间送到 转自 默然 Coldwings 知乎 www zhihu com question 63187737 他是谁 Linus 林纳斯 托瓦兹 Linus Torvalds
  • 编译内核的相关知识

    1 在PC端搭建环境 ubantu 2 树莓派等芯片带操作系统的启动过程 C51 STM32 裸机 用C直接操控底层寄存器实现相关业务 业务流程型的裸机代码 3 带有操作系统的 X86 intel windows 启动过程 电源 gt bi
  • Source Insight给Linux内核创建工程

    所有文档请关注公众号 一口Linux 后台回复 ubuntu linux驱动视频同步更新到 https live bilibili com 22719960 一 Source Insight安装 1 预先准备好 Source Insight
  • Linux的IO端口和IO内存

    Linux的IO端口和IO内存 分类 linux编程 2011 01 14 13 22 866人阅读 评论 1 收藏 举报 io linux linux内核 struct 平台 x86 CPU对外设端口物理地址的编址方式有两种 一种是IO映
  • 关于 Linux 之父,你可能不知道的 7 件事

    如果让你现在说出三个程序员的名字 Linus 很可能就在其中 作为世界上最著名的电脑程序员 黑客之一 Linus Benedict Torvalds 写出了 Linux 内核 1 0 版 发起了开源运动 开发了代码管理工具 Git 这三个成
  • Ubuntu16.04编译Linux内核

    本文介绍在Ubuntu中编译Linux内核并添加新的启动项信息 第一步 下载内核源码并解压 内核源码可以在官网下载 点击打开链接 笔者用的内核版本是4 14的 把下载好的内核源码放在 usr src kernel目录下 没有这个目录的话可以
  • uboot以tag方式给内核传参

    1 tag方式传参 1 struct tag tag是一个数据结构 在uboot和linux kernel中都有定义tag数据机构 而且定义是一样的 2 tag header和tag xxx tag header中有这个tag的size和类
  • qemu 启动自定义文件系统命令

    kvm qemu aarch64 bin qemu system aarch64 M virt smp 8 cpu cortex a76 m 4G nographic kernel out kernel arm64 Image append
  • __setup宏定义

    setup宏定义 struct obs kernel param const char str int setup func char int early define initconst section init rodata defin
  • Linux驱动开发入门(二)VS code驱动开发配置

    开发环境配置 安装 配置 安装 VS code是一款功能强大的开源编辑器 能够在各个平台安装使用 如Linux Widows Mac 而我们Linux驱动直接运行在Linux上 所以下载安装在Linux平台 示例机系统为Ubuntu 20
  • 深入解决Linux内存管理之page fault处理

    说明 Kernel版本 4 14 ARM64处理器 Contex A53 双核 使用工具 Source Insight 3 5 Visio 1 概述 内核实现只是在进程的地址空间建立好了vma区域 并没有实际的虚拟地址到物理地址的映射操作
  • Linux 内核开发学习

    Linux 内核 Linux 内核官网 传送门 Linux 内核源码下载 传送门 1 内核空间 现在来说一下内核空间以及用户空间 这是学习linux内核最基本的两个概念了 如果连这都不懂 那就好好学吧 我们先从这张图入手 32位操作系统的最
  • 基于树莓派博通BCM2835芯片手册导读写编简单引脚驱动代码编译和测试(树莓派)

    编写引脚驱动代码 这边写的是17引脚的驱动代码代码 IO口控制的代码在下面 这边只是简单的代码 驱动代码 include
  • 【Linux】向Linux 5.11.8内核加入新的系统调用

    目录 特殊声明 A mathcal A A 获取root权限

随机推荐

  • 【经验贴】新手项目经理如何接手并管好项目?

    最近有刷到这样一些求助帖 初入职场两三年的项目经理现在开始独立带项目 由于缺乏经验不知道从何下手 询问如何能快速接手并管好项目呢 这个话题也引起了大家的热议 今天就给大家分享一下一些实践经验 1 刚拿到项目时 应该做哪些准备 新接手项目时
  • Octave 计算数据 from 吴恩达的机器学习

    1 乘积 A C 2 点乘 A B 将矩阵A中的元素点乘B中的对应元素相乘 A 2 对矩阵A中的每一个元素平方 1 A 得到每一个元素的倒数 3 log A 对每个元素进行求对数运算 4 exp A 自然数e的幂次运算 就是以e为底 以这些
  • MySql8.0以上版本安装

    一 下载mysql8 0 1 官网地址 https www mysql com 2 进入下载页面 3 选择版本下载 二 安装mysql 1 配置环境变量 变量名 MYSQL HOME 变量值 mysql存放路径 例如 D mysql 8 0
  • postgresql 扩展pg_cron,pg_stat_statements安装配置

    一 概述 pg cron是基于cron的作业调度插件 语法与常规cron相同 但它可以直接从数据库执行PostgreSQL命令 pg stat statements模块提供一种方法追踪一个服务器所执行的所有 SQL 语句的执行统计信息 可以
  • 技术和商业角度刷脸支付都将成为未来趋势

    刷脸支付 我们作为消费者来说 最直观的感受就是我们的支付方式发生了变化 付钱更方便了 从最开始我们带着现金出门买东西 到后来二维码支付 一个手机扫遍天下 对于商家来说他不需要停下来手中在做的事情来收钱找零 而对于我们消费者来说也是非常的快捷
  • Python 内置数据类型 03----元组

    目 录 1 元组的简介 1 1 元组概念 1 2 元组创建方式 1 2 1 使用 直接创建 1 2 2 使用 tuple 函数创建 1 3 元组访问方式 2 处理元组的内置函数 2 1 len 函数 2 2 max 函数 2 3 min 函
  • 【编程测试题】数列还原

    数列还原 题目描述 牛牛的作业薄上有一个长度为 n 的排列 A 这个排列包含了从1到n的n个数 但是因为一些原因 其中有一些位置 不超过 10 个 看不清了 但是牛牛记得这个数列顺序对的数量是 k 顺序对是指满足 i lt j 且 A i
  • virtualbox网络常见问题,virtualbox linux 无法访问网络,virtual box 中 linux ping 不通,配置NAT ssh 无法连接

    问题1 在virtualbox 安装了 linux 发现无法访问网络 解决 不要去改 etc resolv conf 正确的做法是在virtual box配置NAT地址转发 补充一下 我发现mac每次加载虚拟机都要点开高级 然后点端口配置
  • python opencv数组转图片 并显示

    pred是数组类型 先转为8位 pred np array pred np uint8 cv2 imshow 123 pred cv2 waitKey 0
  • Basic Level 1025 反转链表 (25分)

    题目 给定一个常数 K 以及一个单链表 L 请编写程序将 L 中每 K 个结点反转 例如 给定 L 为 1 2 3 4 5 6 K 为 3 则输出应该为 3 2 1 6 5 4 如果 K 为 4 则输出应该为 4 3 2 1 5 6 即最后
  • vue项目 依赖打包 与 import和dependencies 的关系

    项目打包时 依赖与package json中的dependencies和devDependencies并无关 我曾这样认为了好久 原来他们之间的关系是这样的 项目打包的依赖来自于你import from xxx 如无特殊设置 import的
  • 信息安全无小事,手把手教你日志脱敏

    场景 我们开发的程序迟早有一天都会上线到生产环境运行 但是没有人能保证自己的代码100 不出BUG 别抬扛 真没BUG是代码写的少 当我们线上出BUG之后 最常见的定位问题方法就是排查日志文件 所以我们一般都会在开发程序时 在适当的位置输出
  • scikit-learn工具包中常用的特征选择方法介绍

    对于特征选择的作用在这里照搬 西瓜书 中的描述 常用的特征选择方法有以下三种 备注 以下代码采用Jupyter notebook编写 格式与传统稍有不同 1 过滤式特征选择 简单理解就是过滤式特征选择通过选择与响应变量 目标变量 相关性度量
  • typora 编辑器基本用法

    Markdown 由 Daring Fireball 创建 原始指南在 这里 但是 它的语法因不同的解析器或编辑器而异 Typora 正在使用 GitHub Flavored Markdown 1 段落换行 按 Shift Return 可
  • Unity3D碰撞后去掉相互之间的反弹力

    最近做一个小游戏的时候发现 小模型碰撞到墙壁之后会有一个小小的反弹力导致模型有一个微弱的回弹位移 这样给人一种不好的感觉 研究了一下 除了 rigidbody Freeze Rotation之外 在FixedUpdate 注意这里是物理特性
  • mysql 正序_请问mysql 中 怎么实现这种排序,按照状态排序正序,再按照开始时间排序正序,...

    展开全部 有两个思路 1 按照各自的活动状态先排序 插入到临时表 最后再union all所有结32313133353236313431303231363533e58685e5aeb931333363353862果集create tempo
  • calico分配网络使k8s节点指定固定网段

    文章目录 calico分配网络使k8s节点指定固定网段 1 配置calicoctl 1 1 下载calicoctl 1 2 配置calicoctl 1 3 测试calicoctl 2 配置ippool 3 添加ippool 4 创建pod测
  • vue3`

    1 ref是一个函数 响应式数据 使用前要引入 impor ref fro vue let name ref 张三 改变数据 name value 李四 vue3对不同对象处理不同 数据劫持才是响应式的根本 getset 处理对象用prox
  • SpringBoot生成二维码

    目录 Zxing原生方式 添加依赖 二维码生成工具类 添加Controller 添加测试页面 使用postman测试效果 Hutool的方式 添加依赖 创建QRCodeService 添加Controller 效果测试 我们使用两种方式 去
  • mutex_init() / mutex_lock() / mutex_unlock()

    请求 1 初始化互斥体 mutex init 2 获得互斥体 mutex lock 3 释放互斥体 mutex unlock 1 mutex init 注意mutex使用之前都需要先init void mutex init struct m