#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的更多相关文章

  1. C#各种同步方法 lock, Monitor,Mutex, Semaphore, Interlocked, ReaderWriterLock,AutoResetEvent, ManualResetEvent

    看下组织结构: System.Object System.MarshalByRefObject System.Threading.WaitHandle System.Threading.Mutex S ...

  2. 多线程同步工具——Lock

    本文原创,转载请注明出处. 参考文章: <"JUC锁"03之 公平锁(一)> <"JUC锁"03之 公平锁(二)> 锁分独占锁与共享锁, ...

  3. java 线程 Lock 锁使用Condition实现线程的等待(await)与通知(signal)

    一.Condition 类 在前面我们学习与synchronized锁配合的线程等待(Object.wait)与线程通知(Object.notify),那么对于JDK1.5 的 java.util.c ...

  4. InnoDB:Lock & Transaction

    InnoDB 是一个支持事务的Engine,要保证事务ACID,必然会用到Lock.就像在Java编程一下,要保证数据的线程安全性,必然会用到Lock.了解Lock,Transaction可以帮助sq ...

  5. 使用四元数解决万向节锁(Gimbal Lock)问题

    问题 使用四元数可以解决万向节锁的问题,但是我在实际使用中出现问题:我设计了一个程序,显示一个三维物体,用户可以输入绕zyx三个轴进行旋转的指令,物体进行相应的转动. 由于用户输入的是绕三个轴旋转的角 ...

  6. 万向节锁(Gimbal Lock)的理解

    [TOC] 结论 我直接抛出结论: Gimbal Lock 产生的原因不是欧拉角也不是旋转顺序,而是我們的思维方式和程序的执行逻辑没有对应,也就是说是我们的观念导致这个情况的发生. 他人解释 首先我们 ...

  7. 在多线程编程中lock(string){...}隐藏的机关

    常见误用场景:在订单支付环节中,为了防止用户不小心多次点击支付按钮而导致的订单重复支付问题,我们用 lock(订单号) 来保证对该订单的操作同时只允许一个线程执行. 这样的想法很好,至少比 lock( ...

  8. 谈谈 Lock

    上来先看MSDN关于lock的叙述: lock  关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁.  下面的示例包含一个 lock 语句. lock  关键字可确保当一 ...

  9. LOCK TABLES和UNLOCK TABLES与Transactions的交互

    LOCK TABLES对事务不安全,并且在试图锁定表之前隐式提交任何活动事务. UNLOCK TABLES只有在LOCK TABLES已经获取到表锁时,会隐式提交任何活动事务.对于下面的一组语句,UN ...

  10. SQL 性能调优中可参考的几类Lock Wait

    在我们的系统出现性能问题时,往往避不开调查各种类型 Lock Wait,如Row Lock Wait.Page Lock Wait.Page IO Latch Wait等.从中找出可能的异常等待,为性 ...

随机推荐

  1. EPSON LQ610K 设置税控盘打印发票的格式

    问题困扰 之前一直是手动调试发票打印格式,浪费发票纸张不说,而且还浪费时间.今天在Parrells Desktop里利用Bonjour设置打印机的时候,找到了EPSON网站有这方面的介绍,根据上面的提 ...

  2. CSS使用

    CSS介绍 css是英文Cascading Style Sheets的缩写,称为层叠样式表,用于对页面进行美化. 语法:style = 'key1:value1;key2:value2;' 存在方式有 ...

  3. Linux启动过程详述

    http://www.ibm.com/developerworks/cn/linux/kernel/startup/index.html Linux启动第1步:引导内核 Linux启动第2步:内核部分 ...

  4. gravity与layout_gravity的区别

    android:gravivty 控件的内容显示位置 android:layout_gravity 控件在屏幕的布局位置,相对于容器或者父控件的位置

  5. 利用反卷积神经网络可视化CNN

    http://blog.csdn.net/hjimce/article/details/51762046 http://arxiv.org/pdf/1311.2901.pdf Visualizing ...

  6. PCA9554

    参考资料: 1. Texas Instruments PCA9554简介 2. PCA9554文档下载 3. PCA9554 Data Sheet 知识点: ● PCA9554是具有中断输出和配置寄存 ...

  7. css精灵

    ○ css 精灵(Sprites)技术利用photoshop将图片整合,然后用background-images,background-position,background-repeat技术,对图片 ...

  8. 调试多线程 & 查死锁的bug & gcore命令 & gdb对多线程的调试 & gcore & pstack & 调试常用命令

    gdb thread apply all bt 如果你发现有那么几个栈停在 pthread_wait 或者类似调用上,大致就可以得出结论:就是它们几个儿女情长,耽误了整个进程. 注意gdb的版本要高于 ...

  9. CSS3的基础用法

    CSS3的现状:1.浏览器支持程度差,需要添加私有前缀 2.移动端支持优于PC端 3.不断改进中 4.应用相对广泛 在CSS3中增加新增了许多灵活查找元素的方法,极大的提高了查找元素的效率和精准度.C ...

  10. 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 ...