linux - spin lock实现分析

news2024/12/24 21:23:52

linux - spin lock实现分析

  • spinlock
  • 1 spinlock的数据结构
  • 2 spinlock的接口
    • 2.1 spin_lock_init
    • 2.2 spin_lock
    • 2.3 spin_unlock
    • 2.4 spin_lock_irq
    • 2.5 spin_unlock_irq
    • 2.6 spin_lock_irqsave
    • 2.7 spin_unlock_irqrestore
    • 2.8 spin_lock_bh
    • 2.9 spin_unlock_bh

spinlock

在这里插入图片描述

1 spinlock的数据结构

  • u16 owner;
  • u16 next;
typedef struct {                                                                                                                                                                                           
        union {
                u32 slock;
                struct __raw_tickets {
#ifdef __ARMEB__
                        u16 next;
                        u16 owner;
#else
                        u16 owner;
                        u16 next;
#endif
                } tickets;
        };
} arch_spinlock_t;

#define __ARCH_SPIN_LOCK_UNLOCKED       { { 0 } }

typedef struct {
        u32 lock;
} arch_rwlock_t;

typedef struct raw_spinlock {
        arch_spinlock_t raw_lock;
#ifdef CONFIG_DEBUG_SPINLOCK
        unsigned int magic, owner_cpu;
        void *owner;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
        struct lockdep_map dep_map;
#endif
} raw_spinlock_t;

/* Non PREEMPT_RT kernels map spinlock to raw_spinlock */
typedef struct spinlock {
        union {
                struct raw_spinlock rlock;

#ifdef CONFIG_DEBUG_LOCK_ALLOC
# define LOCK_PADSIZE (offsetof(struct raw_spinlock, dep_map))
                struct {
                        u8 __padding[LOCK_PADSIZE];
                        struct lockdep_map dep_map;
                };
#endif                                                                                                                                                                                                     
        };
} spinlock_t;

2 spinlock的接口

2.1 spin_lock_init

#define __ARCH_SPIN_LOCK_UNLOCKED       { { 0 } }

#define ___SPIN_LOCK_INITIALIZER(lockname)      \                                                                                                                                                          
        {                                       \
        .raw_lock = __ARCH_SPIN_LOCK_UNLOCKED,  \
        SPIN_DEBUG_INIT(lockname)               \
        SPIN_DEP_MAP_INIT(lockname) }

#define __SPIN_LOCK_INITIALIZER(lockname) \
        { { .rlock = ___SPIN_LOCK_INITIALIZER(lockname) } }

#define __SPIN_LOCK_UNLOCKED(lockname) \
        (spinlock_t) __SPIN_LOCK_INITIALIZER(lockname)

#define DEFINE_SPINLOCK(x)      spinlock_t x = __SPIN_LOCK_UNLOCKED(x)

# define spin_lock_init(_lock)                  \                                                                                                                                                          
do {                                            \
        spinlock_check(_lock);                  \
        *(_lock) = __SPIN_LOCK_UNLOCKED(_lock); \
} while (0)


        spin_lock_init(&lo->lo_lock);                                                                                                                                                                      
        spin_lock_init(&lo->lo_work_lock);

2.2 spin_lock

在这里插入图片描述
在这里插入图片描述

/*
 * ARMv6 ticket-based spin-locking.
 *
 * A memory barrier is required after we get a lock, and before we 
 * release it, because V6 CPUs are assumed to have weakly ordered
 * memory.
 */     
 
static inline void arch_spin_lock(arch_spinlock_t *lock)
{
        unsigned long tmp;
        u32 newval;
        arch_spinlock_t lockval;

        prefetchw(&lock->slock);
        __asm__ __volatile__(
"1:     ldrex   %0, [%3]\n"
"       add     %1, %0, %4\n"
"       strex   %2, %1, [%3]\n"
"       teq     %2, #0\n"
"       bne     1b"
        : "=&r" (lockval), "=&r" (newval), "=&r" (tmp)                                                                                                                                                     
        : "r" (&lock->slock), "I" (1 << TICKET_SHIFT)
        : "cc");

        while (lockval.tickets.next != lockval.tickets.owner) {
                wfe();
                lockval.tickets.owner = READ_ONCE(lock->tickets.owner);
        }

        smp_mb();
}

static inline void __raw_spin_lock(raw_spinlock_t *lock)
{
        preempt_disable();
        spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
        LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);                                                                                                                                       
}

#define raw_spin_lock(lock)     _raw_spin_lock(lock)

static __always_inline void spin_lock(spinlock_t *lock)
{                                                                                                                                                                                                          
        raw_spin_lock(&lock->rlock);
}

2.3 spin_unlock

在这里插入图片描述
在这里插入图片描述

#define SEV             __ALT_SMP_ASM(WASM(sev), WASM(nop))

static inline void dsb_sev(void)
{                                                                                                                                                                                                          

        dsb(ishst);
        __asm__(SEV);
}

static inline void arch_spin_unlock(arch_spinlock_t *lock)
{                                                                                                                                                                                                          
        smp_mb();
        lock->tickets.owner++;
        dsb_sev();
}

static inline void do_raw_spin_unlock(raw_spinlock_t *lock) __releases(lock)
{
        mmiowb_spin_unlock();
        arch_spin_unlock(&lock->raw_lock);                                                                                                                                                                 
        __release(lock);
}

static inline void __raw_spin_unlock(raw_spinlock_t *lock)
{                                                                                                                                                                                                          
        spin_release(&lock->dep_map, _RET_IP_);
        do_raw_spin_unlock(lock);
        preempt_enable();
}

#define _raw_spin_unlock(lock) __raw_spin_unlock(lock)

#define raw_spin_unlock(lock)           _raw_spin_unlock(lock)

static __always_inline void spin_unlock(spinlock_t *lock)
{
        raw_spin_unlock(&lock->rlock);
}

2.4 spin_lock_irq

在这里插入图片描述

static inline void arch_local_irq_disable(void)
{
        if (system_has_prio_mask_debugging()) {
                u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1);

                WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF);
        }

        asm volatile(ALTERNATIVE(                                                                                                                                                                          
                "msr    daifset, #3             // arch_local_irq_disable",
                __msr_s(SYS_ICC_PMR_EL1, "%0"),
                ARM64_HAS_IRQ_PRIO_MASKING)
                :
                : "r" ((unsigned long) GIC_PRIO_IRQOFF)
                : "memory");
}

static inline void __raw_spin_lock_irq(raw_spinlock_t *lock)
{
        local_irq_disable();                                                                                                                                                                               
        preempt_disable();
        spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
        LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
}

2.5 spin_unlock_irq

在这里插入图片描述

static inline void arch_local_irq_enable(void)                                                                                                                                                             
{
        if (system_has_prio_mask_debugging()) {
                u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1);

                WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF);
        }

        asm volatile(ALTERNATIVE(
                "msr    daifclr, #3             // arch_local_irq_enable",
                __msr_s(SYS_ICC_PMR_EL1, "%0"),
                ARM64_HAS_IRQ_PRIO_MASKING)
                :
                : "r" ((unsigned long) GIC_PRIO_IRQON)
                : "memory");

        pmr_sync();
}

static inline void __raw_spin_unlock_irq(raw_spinlock_t *lock)
{                                                                                                                                                                                                          
        spin_release(&lock->dep_map, _RET_IP_);
        do_raw_spin_unlock(lock);
        local_irq_enable();
        preempt_enable();
}

2.6 spin_lock_irqsave

/*
 * Save the current interrupt enable state.
 */
static inline unsigned long arch_local_save_flags(void)
{
        unsigned long flags;

        asm volatile(ALTERNATIVE(
                "mrs    %0, daif",
                __mrs_s("%0", SYS_ICC_PMR_EL1),
                ARM64_HAS_IRQ_PRIO_MASKING)
                : "=&r" (flags)
                :
                : "memory");

        return flags;
}

static inline unsigned long __raw_spin_lock_irqsave(raw_spinlock_t *lock)
{
        unsigned long flags;
                                                                                                                                                                                                           
        local_irq_save(flags);
        preempt_disable();
        spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
        /*
         * On lockdep we dont want the hand-coded irq-enable of
         * do_raw_spin_lock_flags() code, because lockdep assumes
         * that interrupts are not re-enabled during lock-acquire:
         */
#ifdef CONFIG_LOCKDEP
        LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
#else
        do_raw_spin_lock_flags(lock, &flags);
#endif
        return flags;
}

#define spin_lock_irqsave(lock, flags)                          \
do {                                                            \
        raw_spin_lock_irqsave(spinlock_check(lock), flags);     \
} while (0)

2.7 spin_unlock_irqrestore

/*
 * restore saved IRQ state
 */                                                                                                                                                                                                        
static inline void arch_local_irq_restore(unsigned long flags)
{
        asm volatile(ALTERNATIVE(
                "msr    daif, %0",
                __msr_s(SYS_ICC_PMR_EL1, "%0"),
                ARM64_HAS_IRQ_PRIO_MASKING)
                :
                : "r" (flags)
                : "memory");

        pmr_sync();
}

static inline void __raw_spin_unlock_irqrestore(raw_spinlock_t *lock,
                                            unsigned long flags)
{
        spin_release(&lock->dep_map, _RET_IP_);
        do_raw_spin_unlock(lock);
        local_irq_restore(flags);
        preempt_enable();
}

static __always_inline void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)                                                                                                                  
{
        raw_spin_unlock_irqrestore(&lock->rlock, flags);
}

2.8 spin_lock_bh

在这里插入图片描述

#define SOFTIRQ_LOCK_OFFSET (SOFTIRQ_DISABLE_OFFSET + PREEMPT_LOCK_OFFSET)

static inline void __raw_spin_lock_bh(raw_spinlock_t *lock)
{
        __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
        spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
        LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
}

static __always_inline void spin_lock_bh(spinlock_t *lock)                                                                                                                                                 
{
        raw_spin_lock_bh(&lock->rlock);
}

2.9 spin_unlock_bh

在这里插入图片描述

#define SOFTIRQ_LOCK_OFFSET (SOFTIRQ_DISABLE_OFFSET + PREEMPT_LOCK_OFFSET)

static inline void __raw_spin_unlock_bh(raw_spinlock_t *lock)
{
        spin_release(&lock->dep_map, _RET_IP_);                                                                                                                                                            
        do_raw_spin_unlock(lock);
        __local_bh_enable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
}

static __always_inline void spin_unlock_bh(spinlock_t *lock)
{
        raw_spin_unlock_bh(&lock->rlock);                                                                                                                                                                  
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/702152.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第四十三章 开发Productions - ObjectScript Productions - 使用记录映射器 - 编辑记录映射字段和组合

文章目录 第四十三章 开发Productions - ObjectScript Productions - 使用记录映射器 - 编辑记录映射字段和组合编辑记录映射字段和组合NameDatatypeAnnotationWidth (fixed-width record maps only)RequiredRepeating (delimited record maps only)IgnoreTrailing Data (fixed…

RabbitMQ快速上手(延迟队列)

安装 官网 参考文章&#xff1a; ​ https://blog.csdn.net/miaoye520/article/details/123207661 ​ https://blog.csdn.net/lvoelife/article/details/126658695 安装Erlang&#xff0c;并添加环境变量ERLANG_HOME&#xff0c;命令行运行erl 安装rabbitmq&#xff0c;rab…

Pastebin设计之旅:从零设计网络文本存储系统

项目简介&#xff1a;Pastebin是一个在线的文本存储平台&#xff0c;让用户可以存储和分享代码片段或者其他类型的文本。它支持多种编程和标记语言的语法高亮&#xff0c;用户可以选择让他们的"paste"公开或私有。无需注册就可以使用&#xff0c;但注册用户可以更方便…

森海塞尔重磅推出TC Bars智能音视频一体机, 为中小型协作空间缔造理想解决方案

森海塞尔重磅推出TC Bars智能音视频一体机&#xff0c; 为中小型协作空间缔造理想解决方案 全球音频行业先驱森海塞尔重磅推出首款内置摄像头的可扩展一体化会议设备 德国韦德马克&#xff0c;2023年6月13日——森海塞尔作为先进音频技术的首选&#xff0c;致力于使协作与学习…

力扣 617. 合并二叉树

题目来源&#xff1a; C题解1&#xff1a;使用队列实现层序遍历。基于root1&#xff0c;遇到可覆盖部分&#xff0c;直接将该节点指向对应节点&#xff0c;遇到重复部分&#xff0c;则修改root1该节点相应的值。 /*** Definition for a binary tree node.* struct TreeNode {*…

超市零售数据可视化分析(Plotly 指南)

CSDN 上不能插入 HTML&#xff0c;可以在 GitHub Page 上查看&#xff1a; https://paradiseeee.github.io/2022/07/30/超市零售数据可视化分析/ 项目首次发布于 Kesci 上 – 超市零售数据分析。感兴趣的可以直接上去 Fork 之后自己做。由于上面只能用 Jupyter Notebook&#x…

多旋翼无人机试验系统设计与实现

摘 要 世界的航空业的大门被20世纪莱特兄弟制造的“飞行者一号”开启&#xff0c;直至今日处于飞速发展的阶段。随着时代的进步&#xff0c;各种微电子、微传感、通信技术的飞速发展&#xff0c;让无人机在时代内成为一种新型的空中力量。除了军用方面的多种用途&#xff0c;无…

《Linux操作系统编程》第九章 数据查找和筛选工具 : 了解流编辑器sed和报表生成器awk的简单使用

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

uni-app滚动分页 兼容(App 小程序 H5)

因为手机端本身屏幕空间不大 所以大家一般都会选择用滚动分页 首先 我在根目录下创建了一个 api目录 下面创建了一个bookApi.js 其中写了一个请求函数 getBookList 根据当前页 page 和 每页展示多少条 pageSize 获取数据 那么 我的组件代码是这样的 <template><scro…

MacBook Pro Apple M2 Max安装MySQL-8.0.33

文章目录 下载安装程序安装数据库配环境变量查看数据库状态 系统&#xff1a;macOS Ventura 芯片&#xff1a;M2 数据库&#xff1a;MySQL 8.0.33 下载安装程序 官网地址&#xff1a;https://www.mysql.com/ 点击页签“DOWLOADS“后将页面拖到底部&#xff0c;点MySQL Commu…

U盘的文件系统为FAT32才可以同时在苹果电脑和windows电脑中正常使用

文章目录 1.驱动器F中的磁盘未被格式化。想现在格式化吗&#xff1f;2.U盘插到苹果电脑上后无法写入 1.驱动器F中的磁盘未被格式化。想现在格式化吗&#xff1f; 我之前U盘的文件系统为exFAT&#xff0c;插入Windows Server 2003系统的电脑中&#xff0c;打开时弹出上面的提示框…

2023上半年软考系统分析师科目一整理-14

2023上半年软考系统分析师科目一整理-14 计算机系统性能评估中&#xff0c;( A )通常采用加法指令的运算速度来衡量计算机的速度。(D )首先计算出处理部件每个计算单元的有效计算率&#xff0c;再按不同字长加以调整&#xff0c;得出该计算单元的理论性能&#xff0c;所有组成该…

JavaFX学习:Observable Collections(观察集合)

JavaFX中的观察集合&#xff08;Observable Collections&#xff09;继承自Java的集合&#xff08;Collections&#xff09;。Java集合提供了List、Map、Set三种集合接口。JavaFX在Java集合基础上派生出可以监听集合内容变化的三种集合接口。接口如下&#xff1a; ObservableL…

【算法与数据结构】剑指 Offer 05、LeetCode替换空格

文章目录 一、题目二、双指针法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、双指针法 思路分析&#xff1a;这道题使用双指针法就能不用额外的辅助空间。首先计算字符串中的空格数量&#xff0c;然后重设…

函数模板和类模板 知识点总结 C++程序设计与算法笔记总结(七) 北京大学 郭炜

函数模板 交换两个整型变量的值的Swap函数&#xff1a; void Swap(int & x,int & y) { int tmp x; x y; y tmp; } 交换两个double型变量的值的Swap函数: void Swap(double & x,double & y) { double tmp x; x y; y tmp; }用函数模板解决&#xff1a; …

MAYA动力学曲线带动骨骼

例子 2 自由下落了 对比测试 尖端 太麻烦&#xff0c;使用风 nucleus1.windDirectionZ10*sin(time) 把球合成一个 删除一个解算器&#xff0c;就不动了

Redis 性能管理/优化 双一致性问题 缓存雪崩/击穿/穿透

---------------------- Redis 性能管理 ---------------------------------------- ----- 查看Redis内存使用 ----- info memoryredis-cli -a abc123 info memory ----- 内存碎片率 ----- used_memory_rss&#xff1a;是Redis向操作系统申请的内存。used_memory&#xff1a;是…

从有序顺序表中删除所有其值重复的元素(用不同的负数代替),使所有元素的值均不同。

题目要求&#xff1a;从有序顺序表中删除所有其值重复的元素&#xff08;用不同的负数代替&#xff09;&#xff0c;使所有元素的值均不同。 0&#xff1a;有序顺序表 1&#xff1a;删除所有其值重复的元素 2&#xff1a;用不同的负数代替 3&#xff1a;顺序表中所有元素的值均…

Maven中依赖使用范围

IDEA中help中show Log in Explorer可以查看idea日志 依赖使用范围 构建包含的流程&#xff1a;编译 &#xff0c;测试 &#xff0c;运行 &#xff0c;打包 &#xff0c;安装 &#xff0c;部署 comile test package install deploy 使用标签 1&#xff1a;compile 缺省值 伴随者…

OpenStack(T版)——块存储(Cinder)服务介绍与安装

文章目录 OpenStack(T版)——块存储(Cinder)服务介绍与安装安装和配置(controller)准备(1)创建数据库(2)加载admin user的环境变量(3)创建Identity服务凭据(4)创建Cinder 块存储服务组件的API endpoint 安装和配置Cinder块存储服务组件(1)安装软件包(2)编辑/etc/cinder/cinder.…