当前位置: 首页 > news >正文

RISCV——Spinlock锁的理解

目录

1. 原子操作

2. 锁是干嘛的

3. 锁的实现


1. 原子操作

        gcc从4.1.2开始提供了__sync_*系列的build-in函数,用于提供加减和逻辑运算的原子操作,主要接口的其声明如下:

  • type __sync_fetch_and_add (type *ptr, type value, ...): 将value加到ptr上,结果更新到ptr,并返回操作之前*ptr的值
  • type __sync_fetch_and_sub (type *ptr, type value, ...):从ptr减去value,结果更新到ptr,并返回操作之前*ptr的值
  • type __sync_fetch_and_or (type *ptr, type value, ...): 将ptr与value相或,结果更新到ptr, 并返回操作之前*ptr的值
  • type __sync_fetch_and_and (type *ptr, type value, ...): 将ptr与value相与,结果更新到ptr,并返回操作之前ptr的值
  • +type __sync_fetch_and_xor (type *ptr, type value, ...):将ptr与value异或,结果更新到ptr,并返回操作之前ptr的值
  • type __sync_fetch_and_nand (type *ptr, type value, ...): 将ptr取反后,与value相与,结果更新到ptr,并返回操作之前ptr的值
  • +type __sync_add_and_fetch (type *ptr, type value, ...):将value加到ptr上,结果更新到ptr,并返回操作之后新ptr的值
  • type __sync_sub_and_fetch (type *ptr, type value, ...):从ptr减去value,结果更新到ptr,并返回操作之后新*ptr的值
  • type __sync_or_and_fetch (type *ptr, type value, ...):将ptr与value相或, 结果更新到ptr,并返回操作之后新*ptr的值
  • type __sync_and_and_fetch (type *ptr, type value, ...):将ptr与value相与,结果更新到ptr,并返回操作之后新*ptr的值
  • type __sync_xor_and_fetch (type *ptr, type value, ...):将ptr与value异或,结果更新到ptr,并返回操作之后新ptr的值
  • +type __sync_nand_and_fetch (type *ptr, type value, ...):将ptr取反后,与value相与,结果更新到ptr,并返回操作之后新ptr的值
  • bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...):比较*ptr与oldval的值,如果两者相等,则将newval更新到*ptr并返回true
  • type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...):比较ptr与oldval的值,如果两者相等,则将newval更新到ptr并返回操作之前*ptr的值
  • __sync_synchronize (...):发出完整内存栅栏
  • +type __sync_lock_test_and_set (type *ptr, type value, ...): 将value写入ptr,对ptr加锁,并返回操作之前*ptr的值。即,try spinlock语义
  • void __sync_lock_release (type *ptr, ...):将0写入到ptr,并对ptr解锁。即,unlock spinlock语义

2. 锁是干嘛的

锁解决的问题:为了并行中的正确性(共享数据一致性)

        多核处理器,多个CPU如果同时访问一些共享资源,可能会导致数据不一致,即共享数据用锁设置成多CPU分时访问。

锁带来的问题:并行变串行,效率降低

3. 锁的实现

上锁:

__sync_lock_test_and_set

通过原子操作赋值,也就是锁只能一方获取。

解锁:

__sync_lock_release

通过原子操作清0。

        锁的操作均是原子操作,但是实现锁的功能,还需要内存屏蔽功能,保证临界区的执行可靠性。某些平台的部分代码:

#define SPINLOCK_INIT \{                 \0             \}#define CORELOCK_INIT          \{                          \.lock = SPINLOCK_INIT, \.count = 0,            \.core = -1             \}/* Defination of memory barrier macro */
#define mb()                          \{                                 \asm volatile("fence" ::       \: "memory"); \}#define atomic_set(ptr, val) (*(volatile typeof(*(ptr)) *)(ptr) = val)
#define atomic_read(ptr) (*(volatile typeof(*(ptr)) *)(ptr))
#define atomic_get(ptr) (*(volatile typeof(*(ptr)) *)(ptr))#ifndef __riscv_atomic
#error "atomic extension is required."
#endif
#define atomic_add(ptr, inc) __sync_fetch_and_add(ptr, inc)
#define atomic_sub(ptr, inc) __sync_fetch_and_sub(ptr, inc)
#define atomic_sub_return(ptr, inc) __sync_sub_and_fetch (ptr, inc)
#define atomic_or(ptr, inc) __sync_fetch_and_or(ptr, inc)
#define atomic_swap(ptr, swp) __sync_lock_test_and_set(ptr, swp)
#define atomic_cas(ptr, cmp, swp) __sync_val_compare_and_swap(ptr, cmp, swp)typedef struct _spinlock
{int lock;
} spinlock_t;typedef struct _semaphore
{spinlock_t lock;int count;int waiting;
} semaphore_t;typedef struct _corelock
{spinlock_t lock;int count;int core;
} corelock_t;static inline int spinlock_trylock(spinlock_t *lock)
{int res = atomic_swap(&lock->lock, -1);/* Use memory barrier to keep coherency */mb();return res;
}static inline void spinlock_lock(spinlock_t *lock)
{while(spinlock_trylock(lock));
}static inline void spinlock_unlock(spinlock_t *lock)
{/* Use memory barrier to keep coherency */mb();atomic_set(&lock->lock, 0);asm volatile("nop");
}

http://www.lryc.cn/news/302627.html

相关文章:

  • 阿里云幻兽帕鲁Windows 服务器怎么下载存档?
  • ArcGIS API for JavaScript 4.X 本地部署(js,字体)
  • 202427读书笔记|《猫的自信:治愈系生活哲学绘本》——吸猫指南书,感受猫咪的柔软慵懒与治愈
  • 数据结构链表力扣例题AC(2)——代码以及思路记录
  • C++面试宝典第30题:分发饼干
  • 文件包含+文件上传漏洞(图片马绕过)
  • 华为配置旁挂二层组网隧道转发示例
  • Postgresql源码(123)事务提交时三段资源释放分析ResourceOwnerRelease
  • 电脑文件误删除如何恢复?2024最新三种恢复方法
  • Netty应用——Google Protobuf强化篇(二十)
  • SpringAMQP开启“可靠性”机制
  • 戴尔Dell R740服务器开机冒烟亮黄灯故障维修
  • 【阅读笔记】空域保边降噪《Side Window Filtering》
  • vue3前端excel导出;组件表格,自定义表格导出;Vue3 + xlsx + xlsx-style
  • npm install一直卡在 sill idealTree buildDeps
  • spring boot rabbitmq常用配置
  • MySQL学习记录——십삼 视图及用户、权限管理
  • PyCharm 自动添加文件头注释
  • 用HTML Canvas和JavaScript创建美丽的花朵动画效果
  • java----js常用的api
  • unity 使用VS Code 开发,VS Code配置注意事项
  • 领域驱动设计(Domain Driven Design)
  • CF778A String Game 题解
  • 【工具插件类教学】Unity运行时监控变量,属性,事件等的值和调用Runtime Monitoring
  • 实际生产中的一次非典型的基于jmeter的接口自动化实践
  • 新能源汽车软件开发设计规范
  • Linux:grep进阶(11)
  • 【实战】二、Jest难点进阶(一) —— 前端要学的测试课 从Jest入门到TDD BDD双实战(五)
  • 8.2 新特性 - 透明的读写分离
  • 关于三维GIS开发成长路线的一些思考