lock
#ifndef lock_h
#define lock_h #include <stdint.h>
#include <string.h>
#include "mydef.h"
#include "now.h"
#define debug_lock 1 typedef struct {
intptr_t lck;
uintptr_t tid;
uintptr_t nr;
#if debug_lock
const char* file;
uintptr_t line;
#endif
} lock_t; #define lock_initial {0}
#define lock_initial_locked {1, 0, 1}
static __attribute__((unused)) lock_t lock_val = lock_initial; #if (debug_lock == 2)
#define locktrace_begin() uintptr_t tms = now();
#define lock_backtrace(lkp) \
do { \
uintptr_t current = now(); \
if (tms == 0) { \
tms = current; \
} \
\
if (current > tms + 3000) { \
tms = current - 2000; \
logmsg("locktrace: %d %s:%d\n", (int) lkp->lck, lkp->file, (int) lkp->line); \
} \
} while (0)
#else
#define locktrace_begin() (void) 0
#define lock_backtrace(x) (void) 0
#endif #if debug_lock
#define log_lock(ptr, l, f) do {ptr->line = l; ptr->file = f;} while (0)
#define log_unlock(ptr) do {ptr->line = -1; ptr->file = "";} while (0)
#else
#define log_lock(ptr, l, f) (void) (0)
#define log_unlock(ptr) (void) (0)
#endif #ifdef __linux__
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif #define my_lock(lkp, re) \
do { \
lock_t* ptr = lkp; \
if (!__sync_bool_compare_and_swap(&ptr->lck, 0, 1)) { \
if (ptr->lck == 2) { \
syscall(__NR_futex, &ptr->lck, FUTEX_WAIT, 2, NULL, NULL, 0); \
} \
\
locktrace_begin(); \
while (0 != __sync_lock_test_and_set(&ptr->lck, 2)) { \
syscall(__NR_futex, &ptr->lck, FUTEX_WAIT, 2, NULL, NULL, 0); \
lock_backtrace(ptr); \
} \
} \
my_assert2(ptr->lck != 0, "lck = %d", ptr->lck); \
my_assert2(ptr->nr == 0, "lck = %d, nr = %d, %d@%s", ptr->lck, ptr->nr, ptr->line, ptr->file); \
log_lock(ptr, __LINE__, __FILE__); \
\
my_assert(ptr->tid == 0); \
if (re) { \
ptr->tid = systid(); \
} \
++ptr->nr; \
} while (0) #define unlock(lkp) \
do { \
lock_t* ptr = lkp; \
my_assert2(ptr->lck != 0, "lck = %d, nr = %d", ptr->lck, ptr->nr); \
--ptr->nr; \
wmb(); \
if (ptr->nr > 0) { \
my_assert2(ptr->tid != 0, "tid != 0, ptr->nr = %d, lck = %d, %d@%s", ptr->nr, ptr->lck, ptr->line, ptr->file); \
} else { \
ptr->tid = 0; \
/* wmb(); */ \
log_unlock(ptr); \
if (2 == __sync_lock_test_and_set(&ptr->lck, 0)) { \
while (-1 == syscall(__NR_futex, &ptr->lck, FUTEX_WAKE, 1, NULL, NULL, 0)); \
} \
} \
} while (0) #else
#define my_lock(lkp, re) \
do { \
lock_t* ptr = lkp; \
locktrace_begin(); \
while (!__sync_bool_compare_and_swap((void **) &ptr->lck, (void *) 0, (void *) 1)) { \
sched_yield(); \
lock_backtrace(ptr); \
} \
log_lock(ptr, __LINE__, __FILE__); \
\
my_assert(ptr->tid == 0); \
if (re) { \
ptr->tid = systid(); \
} \
++ptr->nr; \
} while (0) #define unlock(lkp) \
do { \
lock_t* ptr = lkp; \
my_assert(ptr->lck != 0); \
--ptr->nr; \
wmb(); \
if (ptr->nr > 0) { \
my_assert(ptr->tid != 0); \
} else { \
ptr->tid = 0; \
/* wmb(); */ \
log_unlock(ptr); \
ptr->lck = 0; \
} \
} while (0)
#endif #define lock(lkp) my_lock(lkp, 0) #define relock(lkp) \
do { \
lock_t* ptr = lkp; \
/* this rmb() is here to assure to see ptr->tid = 0 in unlock */ \
/* if thread exit after unlock(), then another thread is spwaned with same tid */ \
/* on another cpu core and then call lock_recursive. */ \
/* all the above happens so quickly that the other cpu core does not see ptr->tid = 0 */ \
/* it is so impossible to happen that I comment the "correct" implemention. */ \
/* rmb(); */ \
\
if (ptr->tid == systid()) { \
/* if true, it's same thread, event in another cpu core, no mb() is needed. */ \
++ptr->nr; \
} else { \
my_lock(lkp, 1); \
} \
} while (0) static __attribute__((unused)) inline intptr_t my_try_lock(lock_t* lkp, uintptr_t re, uintptr_t line, const char* file)
{
if (!__sync_bool_compare_and_swap((void **) &((lkp)->lck), (void *) 0, (void *) 1)) {
return -1;
}
log_lock(lkp, line, file); my_assert(lkp->tid == 0);
if (re) {
lkp->tid = systid();
}
++lkp->nr;
return 0;
} #define try_lock(lkp) my_try_lock(lkp, 0, __LINE__, __FILE__)
#define retry_lock(lkp) my_try_lock(lkp, 1, __LINE__, __FILE__) typedef struct {
intptr_t nr;
} rwlock_t; #define read_write_max 8000
#define rw_lock_initial {read_write_max}
static __attribute__((unused)) rwlock_t rw_lock_val = rw_lock_initial; #define read_write_lock(lckp, val) \
do { \
rwlock_t* lck = lckp; \
do { \
intptr_t n = __sync_sub_and_fetch(&lck->nr, val); \
if (n >= 0) { \
break; \
} \
__sync_add_and_fetch(&lck->nr, val); \
sched_yield(); \
} while (1); \
} while (0) #define read_write_unlock(lckp, val) \
do { \
rwlock_t* lck = lckp; \
__sync_add_and_fetch(&lck->nr, val); \
} while (0) #define read_lock(lckp) read_write_lock(lckp, 1)
#define write_lock(lckp) read_write_lock(lckp, read_write_max)
#define read_unlock(lckp) read_write_unlock(lckp, 1)
#define write_unlock(lckp) read_write_unlock(lckp, read_write_max) #endif
lock的更多相关文章
- C#各种同步方法 lock, Monitor,Mutex, Semaphore, Interlocked, ReaderWriterLock,AutoResetEvent, ManualResetEvent
看下组织结构: System.Object System.MarshalByRefObject System.Threading.WaitHandle System.Threading.Mutex S ...
- 多线程同步工具——Lock
本文原创,转载请注明出处. 参考文章: <"JUC锁"03之 公平锁(一)> <"JUC锁"03之 公平锁(二)> 锁分独占锁与共享锁, ...
- java 线程 Lock 锁使用Condition实现线程的等待(await)与通知(signal)
一.Condition 类 在前面我们学习与synchronized锁配合的线程等待(Object.wait)与线程通知(Object.notify),那么对于JDK1.5 的 java.util.c ...
- InnoDB:Lock & Transaction
InnoDB 是一个支持事务的Engine,要保证事务ACID,必然会用到Lock.就像在Java编程一下,要保证数据的线程安全性,必然会用到Lock.了解Lock,Transaction可以帮助sq ...
- 使用四元数解决万向节锁(Gimbal Lock)问题
问题 使用四元数可以解决万向节锁的问题,但是我在实际使用中出现问题:我设计了一个程序,显示一个三维物体,用户可以输入绕zyx三个轴进行旋转的指令,物体进行相应的转动. 由于用户输入的是绕三个轴旋转的角 ...
- 万向节锁(Gimbal Lock)的理解
[TOC] 结论 我直接抛出结论: Gimbal Lock 产生的原因不是欧拉角也不是旋转顺序,而是我們的思维方式和程序的执行逻辑没有对应,也就是说是我们的观念导致这个情况的发生. 他人解释 首先我们 ...
- 在多线程编程中lock(string){...}隐藏的机关
常见误用场景:在订单支付环节中,为了防止用户不小心多次点击支付按钮而导致的订单重复支付问题,我们用 lock(订单号) 来保证对该订单的操作同时只允许一个线程执行. 这样的想法很好,至少比 lock( ...
- 谈谈 Lock
上来先看MSDN关于lock的叙述: lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁. 下面的示例包含一个 lock 语句. lock 关键字可确保当一 ...
- LOCK TABLES和UNLOCK TABLES与Transactions的交互
LOCK TABLES对事务不安全,并且在试图锁定表之前隐式提交任何活动事务. UNLOCK TABLES只有在LOCK TABLES已经获取到表锁时,会隐式提交任何活动事务.对于下面的一组语句,UN ...
- SQL 性能调优中可参考的几类Lock Wait
在我们的系统出现性能问题时,往往避不开调查各种类型 Lock Wait,如Row Lock Wait.Page Lock Wait.Page IO Latch Wait等.从中找出可能的异常等待,为性 ...
随机推荐
- EPSON LQ610K 设置税控盘打印发票的格式
问题困扰 之前一直是手动调试发票打印格式,浪费发票纸张不说,而且还浪费时间.今天在Parrells Desktop里利用Bonjour设置打印机的时候,找到了EPSON网站有这方面的介绍,根据上面的提 ...
- CSS使用
CSS介绍 css是英文Cascading Style Sheets的缩写,称为层叠样式表,用于对页面进行美化. 语法:style = 'key1:value1;key2:value2;' 存在方式有 ...
- Linux启动过程详述
http://www.ibm.com/developerworks/cn/linux/kernel/startup/index.html Linux启动第1步:引导内核 Linux启动第2步:内核部分 ...
- gravity与layout_gravity的区别
android:gravivty 控件的内容显示位置 android:layout_gravity 控件在屏幕的布局位置,相对于容器或者父控件的位置
- 利用反卷积神经网络可视化CNN
http://blog.csdn.net/hjimce/article/details/51762046 http://arxiv.org/pdf/1311.2901.pdf Visualizing ...
- PCA9554
参考资料: 1. Texas Instruments PCA9554简介 2. PCA9554文档下载 3. PCA9554 Data Sheet 知识点: ● PCA9554是具有中断输出和配置寄存 ...
- css精灵
○ css 精灵(Sprites)技术利用photoshop将图片整合,然后用background-images,background-position,background-repeat技术,对图片 ...
- 调试多线程 & 查死锁的bug & gcore命令 & gdb对多线程的调试 & gcore & pstack & 调试常用命令
gdb thread apply all bt 如果你发现有那么几个栈停在 pthread_wait 或者类似调用上,大致就可以得出结论:就是它们几个儿女情长,耽误了整个进程. 注意gdb的版本要高于 ...
- CSS3的基础用法
CSS3的现状:1.浏览器支持程度差,需要添加私有前缀 2.移动端支持优于PC端 3.不断改进中 4.应用相对广泛 在CSS3中增加新增了许多灵活查找元素的方法,极大的提高了查找元素的效率和精准度.C ...
- VB发送后台按键和组合键
http://files.cnblogs.com/files/liuzhaoyzz/VB%E5%8F%91%E9%80%81%E5%90%8E%E5%8F%B0%E7%BB%84%E5%90%88%E ...