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等.从中找出可能的异常等待,为性 ...
随机推荐
- SourceTree 免登录跳过初始设置 - 转
转自:http://www.cnblogs.com/xiofee/p/sourcetree_pass_initialization_setup.html 在SourceTree的配置目录新建(或修改) ...
- JS正则表达式大全
转自:http://wenku.baidu.com/link?url=3y930kC7F6D3wQdMjQ3fVDmiA9Wfebs_QK0UB3N3mFaEoKg4ytZORPopxufeYA6si ...
- 非常好的javascript 代码
与其他Javascript类库冲突解决方案 $(document).ready(function() { var $jq = jQuery.noConflict(); $jq('#id').show( ...
- 原创一看便知、Maven创建web项目
创建maven-项目 如果 pom.xml 文件报错 右击项目-->Maven-->update Project 详细步骤 上图中Next 2.继续Next 3.选maven-a ...
- Boost学习笔记(一) 什么是Boost
Boost库是一个功能强大.构造精巧,跨平台.开源并且完全免费的C++程序库
- Windows安装Scrapy遇坑解决办
PS: Windows真心不适合开发.且行且珍惜.... 坑: error: Setup script exited with error: Microsoft Visual C++ 9.0 is r ...
- 办公大楼3D指纹门禁系统解决方案
随着人们对工作.生活的自动化水平也提出了越来越高的要求.以大楼安保对出入大楼的外来人员进行登记放行或以铁锁.钥匙和卡为代表的出入管理方式已无法满足需求. 利用科技的手段,实现办公大楼的安全现代化.管理 ...
- SYSTick 定时器
CM3 内核的处理器,内部包含了一个 SysTick 定时器,(SysTick 的时钟源自 HCLK 的 8 分频,8个系统时钟周期systick跳一个,即8*1/72M=1/9 us)Sys ...
- php-sql-parser sql防注入脚本
<?php /** * SQL Parser from: http://code.google.com/p/php-sql-parser/ * License: New BSD */ class ...
- 搞清css的单位 px,em,rem的区别
前言:现在上大街一眼望去,基本上90%的人都拿着手机,走路,逛街,吃东西都不停着,所以对于我们这种前端开发的程序猿来说,让网页适应于移动端可以说是必须要满足的.所以最近也是一直在学习和实践.然后就接触 ...