linux - spin lock实现分析

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;
#elseu16 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_SPINLOCKunsigned int magic, owner_cpu;void *owner;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOCstruct 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_LOCKDEPLOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
#elsedo_raw_spin_lock_flags(lock, &flags);
#endifreturn 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.hqwc.cn/news/1009.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我心中的TOP1编程语言—JavaScript

作为一名研发工程师&#xff08;程序员&#xff09;&#xff0c;平时工作中肯定会接触或了解很多编程语言。每个人都会有自己工作中常用的语言&#xff0c;也会有偏爱的一些编程语言。而我心中的最爱&#xff0c;毫无疑问&#xff0c;就是 JavaScript。 JavaScript 是一门编程…

华为MateBook 16 2021款锐龙版R7(CREM-WFD9)(CREM-WFG9)原装出厂Win11系统工厂模式,恢复原厂系统

HUAWEI华为笔记本电脑&#xff0c;MateBook 16 2021款 锐龙版 R7(CREM-WFD9) (CREM-WFG9) 原厂Windows11系统&#xff0c;带F10恢复功能&#xff0c;原装OEM专用系统&#xff0c;恢复出厂状态 系统自带所有驱动、出厂主题壁纸LOGO、Office办公软件、华为电脑管家等预装程序 …

记录--不定高度展开收起动画 css/js 实现

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 不定高度展开收起动画 最近在做需求的时候&#xff0c;遇见了元素高度展开收起的动画需求&#xff0c;一开始是想到了使用 transition: all .3s; 来做动画效果&#xff0c;在固定高度的情况下&#xf…

【嵌入式模型转换】2. 算能盒子SE5 芯片板子BM1684 sophon-pipeline

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言1. 开始安装 前言 文章1&#xff0c;我们在SE5上实现了&#xff0c;SOC模式下的 C 和 python-sail的模型转换&#xff0c;文章连接&#xff1a; 【嵌入式模型转…

微服务实战项目-学成在线-课程发布模块

学成在线-课程发布模块 1 模块需求分析 1.1 模块介绍 课程信息编辑完毕即可发布课程&#xff0c;发布课程相当于一个确认操作&#xff0c;课程发布后学习者在网站可以搜索到课程&#xff0c;然后查看课程的详细信息&#xff0c;进一步选课、支付、在线学习。 下边是课程编辑…

观察者模式(二十)

相信自己&#xff0c;请一定要相信自己 上一章简单介绍了迭代器模式(十九), 如果没有看过, 请观看上一章 一. 观察者模式 引用 菜鸟教程里面 观察者模式介绍: https://www.runoob.com/design-pattern/observer-pattern.html 当对象间存在一对多关系时&#xff0c;则使用观察…

【MySQL】MySQL中SQL执行流程

文章目录 一、MySQL语句执行流程1.1、主要的原因有以下几点1.2、具体执行流程图如下 二、存储引擎三、MySQL的架构与内部模块四、崩溃恢复时如何判断事务是否需要提交 一、MySQL语句执行流程 连接器&#xff08;Connector&#xff09;&#xff1a; 当客户端发送一个连接请求时…

矩阵通引入AIGC,帮助企业挖掘用户线索

据CNNIC报告数据&#xff0c;截止2022年6月&#xff0c;我国网民规模达10.51亿&#xff0c;其中短视频用户规模为9.62亿&#xff0c;网络直播用户规模达7.16亿&#xff0c;占网民整体的68.1%。 庞大的用户体量为直播带货奠定了基础&#xff0c;给品牌商家提供了新流量阵地&…

自动刷新工具--可以自动编辑安居客房源信息

本工具可以自动刷新安居客的房源信息&#xff0c;不是爬虫&#xff0c;就是一款解放劳动力的RPA工具 使用方法&#xff1a; 1. 首先输入要自动刷新的房源id 2.点击 开始执行 如果需要免密登陆&#xff0c;需要在个人中心填上anjuke的账密 定时执行 声明&#xff1a;此工具只是…

我是怎么把win11一步一步变成Mac的

目录 【三指拖动】 【空格预览】 【切换Ctrl和Alt】 【使用Linux命令】 【其它】 之前很长一段时间在MacBook上面开发习惯了&#xff0c;然后因为一些原因现在换到了windows上面&#xff0c;不管是使用上还是系统上都很不习惯&#xff0c;因此做了一些改造&#xff0c;…

【Linux】应用层协议:HTTP和HTTPS

每个人都可以很喜欢每个人&#xff0c;但喜欢治不了病&#xff0c;喜欢买不了东西&#xff0c;喜欢不能当饭吃&#xff0c;喜欢很廉价… 文章目录 一、HTTP协议1.URL1.1 URL的组成1.2 urlencode && urldecode 2.HTTP协议格式2.1 http请求和响应的格式2.2 通过代码来进行…

Zookeeper集群的特点

一、Zookeeper集群的特点 Zookeeper:一个领导者 (Leader)&#xff0c;多个跟随者 (Follower) 组成的集群集群中只要有半数以上节点存活&#xff0c;Zookeeper集群就能正常服务。所以Zookeeper适合安装奇数台服务器全局数据一致:每个Server保存一份相同的数据副本&#xff0c;C…