#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. NPOI 教程 - 2.1单元格合并

    来源:http://liyingchun343333.blog.163.com/blog/static/3579731620091018212990/ 合并单元格在制作表格时很有用,比如说表格的标题就 ...

  2. css-position

    值 描述 absolute 生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位. 元素的位置通过 "left", "top", " ...

  3. spring-事物-jdbc-hibernate

  4. Generate Time Data(普通日期主数据)

    Note: While using this option you need to replicate the standard table into SAP HANA that is T005T, ...

  5. Query Designer:公式冲突

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  6. DTP激活时报Overlapping

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  7. js设计模式总结-代理模式

    代理模式 解决哪一类问题 从字面意思上理解,代理模式解决对一个对象的直接访问,这种直接访问可能是"不方便"的,所谓"不方便"可能是直接访问成本比较大(在前端领域 ...

  8. 搞清css的单位 px,em,rem的区别

    前言:现在上大街一眼望去,基本上90%的人都拿着手机,走路,逛街,吃东西都不停着,所以对于我们这种前端开发的程序猿来说,让网页适应于移动端可以说是必须要满足的.所以最近也是一直在学习和实践.然后就接触 ...

  9. jxl读数据库数据生成xls 并下载

    1.所需jar jxl-2.6.10.jar jxls-core-1.0-RC-3.jar jxls-reader-1.0-RC-3.jar 2. excel修改行宽度封装 SheetColumn.j ...

  10. 切换npm源

    直接切换源: npm install --registry=https://registry.npm.taobao.org 另: (仅用于学习参考使用) 参考: http://www.xuebuyua ...