1. #ifndef lock_h
  2. #define lock_h
  3.  
  4. #include <stdint.h>
  5. #include <string.h>
  6. #include "mydef.h"
  7. #include "now.h"
  8. #define debug_lock 1
  9.  
  10. typedef struct {
  11. intptr_t lck;
  12. uintptr_t tid;
  13. uintptr_t nr;
  14. #if debug_lock
  15. const char* file;
  16. uintptr_t line;
  17. #endif
  18. } lock_t;
  19.  
  20. #define lock_initial {0}
  21. #define lock_initial_locked {1, 0, 1}
  22. static __attribute__((unused)) lock_t lock_val = lock_initial;
  23.  
  24. #if (debug_lock == 2)
  25. #define locktrace_begin() uintptr_t tms = now();
  26. #define lock_backtrace(lkp) \
  27. do { \
  28. uintptr_t current = now(); \
  29. if (tms == 0) { \
  30. tms = current; \
  31. } \
  32. \
  33. if (current > tms + 3000) { \
  34. tms = current - 2000; \
  35. logmsg("locktrace: %d %s:%d\n", (int) lkp->lck, lkp->file, (int) lkp->line); \
  36. } \
  37. } while (0)
  38. #else
  39. #define locktrace_begin() (void) 0
  40. #define lock_backtrace(x) (void) 0
  41. #endif
  42.  
  43. #if debug_lock
  44. #define log_lock(ptr, l, f) do {ptr->line = l; ptr->file = f;} while (0)
  45. #define log_unlock(ptr) do {ptr->line = -1; ptr->file = "";} while (0)
  46. #else
  47. #define log_lock(ptr, l, f) (void) (0)
  48. #define log_unlock(ptr) (void) (0)
  49. #endif
  50.  
  51. #ifdef __linux__
  52. #ifndef _GNU_SOURCE
  53. #define _GNU_SOURCE
  54. #endif
  55.  
  56. #define my_lock(lkp, re) \
  57. do { \
  58. lock_t* ptr = lkp; \
  59. if (!__sync_bool_compare_and_swap(&ptr->lck, 0, 1)) { \
  60. if (ptr->lck == 2) { \
  61. syscall(__NR_futex, &ptr->lck, FUTEX_WAIT, 2, NULL, NULL, 0); \
  62. } \
  63. \
  64. locktrace_begin(); \
  65. while (0 != __sync_lock_test_and_set(&ptr->lck, 2)) { \
  66. syscall(__NR_futex, &ptr->lck, FUTEX_WAIT, 2, NULL, NULL, 0); \
  67. lock_backtrace(ptr); \
  68. } \
  69. } \
  70. my_assert2(ptr->lck != 0, "lck = %d", ptr->lck); \
  71. my_assert2(ptr->nr == 0, "lck = %d, nr = %d, %d@%s", ptr->lck, ptr->nr, ptr->line, ptr->file); \
  72. log_lock(ptr, __LINE__, __FILE__); \
  73. \
  74. my_assert(ptr->tid == 0); \
  75. if (re) { \
  76. ptr->tid = systid(); \
  77. } \
  78. ++ptr->nr; \
  79. } while (0)
  80.  
  81. #define unlock(lkp) \
  82. do { \
  83. lock_t* ptr = lkp; \
  84. my_assert2(ptr->lck != 0, "lck = %d, nr = %d", ptr->lck, ptr->nr); \
  85. --ptr->nr; \
  86. wmb(); \
  87. if (ptr->nr > 0) { \
  88. my_assert2(ptr->tid != 0, "tid != 0, ptr->nr = %d, lck = %d, %d@%s", ptr->nr, ptr->lck, ptr->line, ptr->file); \
  89. } else { \
  90. ptr->tid = 0; \
  91. /* wmb(); */ \
  92. log_unlock(ptr); \
  93. if (2 == __sync_lock_test_and_set(&ptr->lck, 0)) { \
  94. while (-1 == syscall(__NR_futex, &ptr->lck, FUTEX_WAKE, 1, NULL, NULL, 0)); \
  95. } \
  96. } \
  97. } while (0)
  98.  
  99. #else
  100. #define my_lock(lkp, re) \
  101. do { \
  102. lock_t* ptr = lkp; \
  103. locktrace_begin(); \
  104. while (!__sync_bool_compare_and_swap((void **) &ptr->lck, (void *) 0, (void *) 1)) { \
  105. sched_yield(); \
  106. lock_backtrace(ptr); \
  107. } \
  108. log_lock(ptr, __LINE__, __FILE__); \
  109. \
  110. my_assert(ptr->tid == 0); \
  111. if (re) { \
  112. ptr->tid = systid(); \
  113. } \
  114. ++ptr->nr; \
  115. } while (0)
  116.  
  117. #define unlock(lkp) \
  118. do { \
  119. lock_t* ptr = lkp; \
  120. my_assert(ptr->lck != 0); \
  121. --ptr->nr; \
  122. wmb(); \
  123. if (ptr->nr > 0) { \
  124. my_assert(ptr->tid != 0); \
  125. } else { \
  126. ptr->tid = 0; \
  127. /* wmb(); */ \
  128. log_unlock(ptr); \
  129. ptr->lck = 0; \
  130. } \
  131. } while (0)
  132. #endif
  133.  
  134. #define lock(lkp) my_lock(lkp, 0)
  135.  
  136. #define relock(lkp) \
  137. do { \
  138. lock_t* ptr = lkp; \
  139. /* this rmb() is here to assure to see ptr->tid = 0 in unlock */ \
  140. /* if thread exit after unlock(), then another thread is spwaned with same tid */ \
  141. /* on another cpu core and then call lock_recursive. */ \
  142. /* all the above happens so quickly that the other cpu core does not see ptr->tid = 0 */ \
  143. /* it is so impossible to happen that I comment the "correct" implemention. */ \
  144. /* rmb(); */ \
  145. \
  146. if (ptr->tid == systid()) { \
  147. /* if true, it's same thread, event in another cpu core, no mb() is needed. */ \
  148. ++ptr->nr; \
  149. } else { \
  150. my_lock(lkp, 1); \
  151. } \
  152. } while (0)
  153.  
  154. static __attribute__((unused)) inline intptr_t my_try_lock(lock_t* lkp, uintptr_t re, uintptr_t line, const char* file)
  155. {
  156. if (!__sync_bool_compare_and_swap((void **) &((lkp)->lck), (void *) 0, (void *) 1)) {
  157. return -1;
  158. }
  159. log_lock(lkp, line, file);
  160.  
  161. my_assert(lkp->tid == 0);
  162. if (re) {
  163. lkp->tid = systid();
  164. }
  165. ++lkp->nr;
  166. return 0;
  167. }
  168.  
  169. #define try_lock(lkp) my_try_lock(lkp, 0, __LINE__, __FILE__)
  170. #define retry_lock(lkp) my_try_lock(lkp, 1, __LINE__, __FILE__)
  171.  
  172. typedef struct {
  173. intptr_t nr;
  174. } rwlock_t;
  175.  
  176. #define read_write_max 8000
  177. #define rw_lock_initial {read_write_max}
  178. static __attribute__((unused)) rwlock_t rw_lock_val = rw_lock_initial;
  179.  
  180. #define read_write_lock(lckp, val) \
  181. do { \
  182. rwlock_t* lck = lckp; \
  183. do { \
  184. intptr_t n = __sync_sub_and_fetch(&lck->nr, val); \
  185. if (n >= 0) { \
  186. break; \
  187. } \
  188. __sync_add_and_fetch(&lck->nr, val); \
  189. sched_yield(); \
  190. } while (1); \
  191. } while (0)
  192.  
  193. #define read_write_unlock(lckp, val) \
  194. do { \
  195. rwlock_t* lck = lckp; \
  196. __sync_add_and_fetch(&lck->nr, val); \
  197. } while (0)
  198.  
  199. #define read_lock(lckp) read_write_lock(lckp, 1)
  200. #define write_lock(lckp) read_write_lock(lckp, read_write_max)
  201. #define read_unlock(lckp) read_write_unlock(lckp, 1)
  202. #define write_unlock(lckp) read_write_unlock(lckp, read_write_max)
  203.  
  204. #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. intel82599在centos6.5下编译安装

    .intel驱动下载地址:https://sourceforge.net/projects/e1000/files/ixgbe%20stable/ .编译安装步骤 yum install kernel ...

  2. sharepoint 增删改查

    前端提交 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="MeetingOneW ...

  3. Creating Dialogs

    #ifndef DIALOG_H #define DIALOG_H #include <QtWidgets> //#include <QDialog> //#include & ...

  4. JavaScript 中的对象

    JavaScript 中的对象 在 JavaScript 中,对象是数据(变量),拥有属性和方法. JavaScript 中的所有事物都是对象:字符串.数字.数组.日期,等等.   访问对象的属性 访 ...

  5. 已禁用对分布式事务管理器(MSDTC)的网络访问的解决方法之一

    C# ASP.NET项目提示上述错误,在代码中使用分布式事务提示添加或修改到数据库的时候.添加数据到数据库时,不会设置实体类的主键字段.

  6. RealSense开发-Session和SenseManager的几种创建方法

    从Intel RealSense 的SDK文档对其架构(如图1所示)的始描述可知,Session是SDK应用的主控模块,必须在所有模块操作之前创建,并且在所有模块注销后最后注销.SenseManage ...

  7. python用来压缩目录的脚本

    import zipfile,os,sys def zip_dir(dirname, zipfilename): filelist = [] if os.path.isfile(dirname): f ...

  8. 如何正确使用$_SERVER['DOCUMENT_ROOT']识别该路径的文件

    echo $_SERVER['DOCUMENT_ROOT']; 这时输出当前文件所在的路径 D:/phpStudy/WWW/study/php&mysql $_SERVER['DOCUMENT ...

  9. Javascript 数组常用操作方法

    一.数组 Array 1.创建数组 /* 构造函数 */ var arr1 = new Array(); //创建一个空数组 var arr1 = new Array(5); //创建指定长度数组(数 ...

  10. Linux系统移植(1) ------搭建交叉编译环境

    本人的开发环境是ubuntu12.05的64版本,运行在11.00的虚拟机上.首先说明为什么需要搭建交叉编译环境.我们知道,我们的开发一般在PC机上,是基于X86架构的,而我们的开发板却是基于ARM架 ...