#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. 《利用python进行数据分析》读书笔记--第四章 numpy基础:数组和矢量计算

    http://www.cnblogs.com/batteryhp/p/5000104.html 第四章 Numpy基础:数组和矢量计算 第一部分:numpy的ndarray:一种多维数组对象 实话说, ...

  2. CentOS直接解压可用的memcached、nginx、keepalived

    Centos均基于x86_64版本,下面相关文件编译时使用用户组为www,用户为www 相关命令: groupadd -r www useradd -r -g www -M www memcached ...

  3. 基于Web的制造追溯系统DEMO

    写在前面 本文不贴任何代码,以图片为主,也许图片更直观,请各位园友谅解! 很久没有写过博客了,这是2016年的第一篇文章:最近主要是忙着完成公司的一个新项目,逛园子的时间都明显少了,只有下班回到家睡觉 ...

  4. 点餐系统Sprint1总结

    经过第一个阶段的冲刺,大家基本上都熟悉自己要做什么,并且把界面做了出来.通过这个阶段的冲刺,大家都学到了很多东西,团队更加默契,遇到不懂的都会提出来一起解决. 团队贡献分 148彭宏亮 20 150张 ...

  5. my.cnf

    skip-external-locking skip-name-resolve back_log= key_buffer_size=384M max_allowed_packet=4M thread_ ...

  6. 关于url中的#-----hash

    前言:不知道你们对url地址中的#一开始是怎么理解的,反正我以前一直都是默认那就是本页面中该id的位置.今天看了篇文章,才把这个真正透彻理解. 1,#涵义 #代表网页中的一个位置.其右面的字符,就是该 ...

  7. [bzoj2743][HEOI2012]采花(树状数组+离线)

    2743: [HEOI2012]采花 Time Limit: 15 Sec  Memory Limit: 128 MBSubmit: 1832  Solved: 954[Submit][Status] ...

  8. div+css常见浏览器兼容问题以及解决办法

    1.图片下方出现几像素的空白间隙问题说明:这个问题在ie6和ff(火狐)下经常见到,例如 <div><img src=""/></div>这个图 ...

  9. B/S网站中IE6兼容问题

    在HTML中定义的样式,部分样式在IE7以前的版本中的效果是不同的,所以需要在网页中定义让浏览器以IE8的模式启动. 在HEAD中定义标签meta如下: <meta http-equiv=&qu ...

  10. [SoapUI] 在SoapUI里获取Excel中多行数据并存入List

    ArrayList<ArrayList<String>> getCellValuesH( String filePath, String sheetName,int tr1,i ...