syslocks.nim 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2012 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. # Low level system locks and condition vars.
  10. {.push stackTrace: off.}
  11. when defined(windows):
  12. type
  13. Handle = int
  14. SysLock* {.importc: "CRITICAL_SECTION",
  15. header: "<windows.h>", final, pure, byref.} = object # CRITICAL_SECTION in WinApi
  16. DebugInfo: pointer
  17. LockCount: int32
  18. RecursionCount: int32
  19. OwningThread: int
  20. LockSemaphore: int
  21. SpinCount: int
  22. SysCond* {.importc: "RTL_CONDITION_VARIABLE", header: "<windows.h>", byref.} = object
  23. thePtr {.importc: "Ptr".} : Handle
  24. proc initSysLock*(L: var SysLock) {.importc: "InitializeCriticalSection",
  25. header: "<windows.h>".}
  26. ## Initializes the lock `L`.
  27. proc tryAcquireSysAux(L: var SysLock): int32 {.importc: "TryEnterCriticalSection",
  28. header: "<windows.h>".}
  29. ## Tries to acquire the lock `L`.
  30. proc tryAcquireSys*(L: var SysLock): bool {.inline.} =
  31. result = tryAcquireSysAux(L) != 0'i32
  32. proc acquireSys*(L: var SysLock) {.importc: "EnterCriticalSection",
  33. header: "<windows.h>".}
  34. ## Acquires the lock `L`.
  35. proc releaseSys*(L: var SysLock) {.importc: "LeaveCriticalSection",
  36. header: "<windows.h>".}
  37. ## Releases the lock `L`.
  38. proc deinitSys*(L: SysLock) {.importc: "DeleteCriticalSection",
  39. header: "<windows.h>".}
  40. proc initializeConditionVariable(
  41. conditionVariable: var SysCond
  42. ) {.stdcall, noSideEffect, dynlib: "kernel32", importc: "InitializeConditionVariable".}
  43. proc sleepConditionVariableCS(
  44. conditionVariable: var SysCond,
  45. PCRITICAL_SECTION: var SysLock,
  46. dwMilliseconds: int
  47. ): int32 {.stdcall, noSideEffect, dynlib: "kernel32", importc: "SleepConditionVariableCS".}
  48. proc signalSysCond*(hEvent: var SysCond) {.stdcall, noSideEffect,
  49. dynlib: "kernel32", importc: "WakeConditionVariable".}
  50. proc broadcastSysCond*(hEvent: var SysCond) {.stdcall, noSideEffect,
  51. dynlib: "kernel32", importc: "WakeAllConditionVariable".}
  52. proc initSysCond*(cond: var SysCond) {.inline.} =
  53. initializeConditionVariable(cond)
  54. proc deinitSysCond*(cond: SysCond) {.inline.} =
  55. discard
  56. proc waitSysCond*(cond: var SysCond, lock: var SysLock) =
  57. discard sleepConditionVariableCS(cond, lock, -1'i32)
  58. elif defined(genode):
  59. const
  60. Header = "genode_cpp/syslocks.h"
  61. type
  62. SysLock* {.importcpp: "Nim::SysLock", pure, final,
  63. header: Header.} = object
  64. SysCond* {.importcpp: "Nim::SysCond", pure, final,
  65. header: Header.} = object
  66. proc initSysLock*(L: var SysLock) = discard
  67. proc deinitSys*(L: SysLock) = discard
  68. proc acquireSys*(L: var SysLock) {.noSideEffect, importcpp.}
  69. proc tryAcquireSys*(L: var SysLock): bool {.noSideEffect, importcpp.}
  70. proc releaseSys*(L: var SysLock) {.noSideEffect, importcpp.}
  71. proc initSysCond*(L: var SysCond) = discard
  72. proc deinitSysCond*(L: SysCond) = discard
  73. proc waitSysCond*(cond: var SysCond, lock: var SysLock) {.
  74. noSideEffect, importcpp.}
  75. proc signalSysCond*(cond: var SysCond) {.
  76. noSideEffect, importcpp.}
  77. proc broadcastSysCond*(cond: var SysCond) {.
  78. noSideEffect, importcpp.}
  79. else:
  80. type
  81. SysLockObj {.importc: "pthread_mutex_t", pure, final,
  82. header: """#include <sys/types.h>
  83. #include <pthread.h>""", byref.} = object
  84. when defined(linux) and defined(amd64):
  85. abi: array[40 div sizeof(clong), clong]
  86. SysLockAttr* {.importc: "pthread_mutexattr_t", pure, final
  87. header: """#include <sys/types.h>
  88. #include <pthread.h>""".} = object
  89. when defined(linux) and defined(amd64):
  90. abi: array[4 div sizeof(cint), cint] # actually a cint
  91. SysCondObj {.importc: "pthread_cond_t", pure, final,
  92. header: """#include <sys/types.h>
  93. #include <pthread.h>""", byref.} = object
  94. when defined(linux) and defined(amd64):
  95. abi: array[48 div sizeof(clonglong), clonglong]
  96. SysCondAttr {.importc: "pthread_condattr_t", pure, final
  97. header: """#include <sys/types.h>
  98. #include <pthread.h>""".} = object
  99. when defined(linux) and defined(amd64):
  100. abi: array[4 div sizeof(cint), cint] # actually a cint
  101. SysLockType = distinct cint
  102. proc initSysLockAux(L: var SysLockObj, attr: ptr SysLockAttr) {.
  103. importc: "pthread_mutex_init", header: "<pthread.h>", noSideEffect.}
  104. proc deinitSysAux(L: SysLockObj) {.noSideEffect,
  105. importc: "pthread_mutex_destroy", header: "<pthread.h>".}
  106. proc acquireSysAux(L: var SysLockObj) {.noSideEffect,
  107. importc: "pthread_mutex_lock", header: "<pthread.h>".}
  108. proc tryAcquireSysAux(L: var SysLockObj): cint {.noSideEffect,
  109. importc: "pthread_mutex_trylock", header: "<pthread.h>".}
  110. proc releaseSysAux(L: var SysLockObj) {.noSideEffect,
  111. importc: "pthread_mutex_unlock", header: "<pthread.h>".}
  112. when defined(ios):
  113. # iOS will behave badly if sync primitives are moved in memory. In order
  114. # to prevent this once and for all, we're doing an extra malloc when
  115. # initializing the primitive.
  116. type
  117. SysLock* = ptr SysLockObj
  118. SysCond* = ptr SysCondObj
  119. when not declared(c_malloc):
  120. proc c_malloc(size: csize_t): pointer {.
  121. importc: "malloc", header: "<stdlib.h>".}
  122. proc c_free(p: pointer) {.
  123. importc: "free", header: "<stdlib.h>".}
  124. proc initSysLock*(L: var SysLock, attr: ptr SysLockAttr = nil) =
  125. L = cast[SysLock](c_malloc(csize_t(sizeof(SysLockObj))))
  126. initSysLockAux(L[], attr)
  127. proc deinitSys*(L: SysLock) =
  128. deinitSysAux(L[])
  129. c_free(L)
  130. template acquireSys*(L: var SysLock) =
  131. acquireSysAux(L[])
  132. template tryAcquireSys*(L: var SysLock): bool =
  133. tryAcquireSysAux(L[]) == 0'i32
  134. template releaseSys*(L: var SysLock) =
  135. releaseSysAux(L[])
  136. else:
  137. type
  138. SysLock* = SysLockObj
  139. SysCond* = SysCondObj
  140. template initSysLock*(L: var SysLock, attr: ptr SysLockAttr = nil) =
  141. initSysLockAux(L, attr)
  142. template deinitSys*(L: SysLock) =
  143. deinitSysAux(L)
  144. template acquireSys*(L: var SysLock) =
  145. acquireSysAux(L)
  146. template tryAcquireSys*(L: var SysLock): bool =
  147. tryAcquireSysAux(L) == 0'i32
  148. template releaseSys*(L: var SysLock) =
  149. releaseSysAux(L)
  150. # rlocks
  151. var SysLockType_Reentrant* {.importc: "PTHREAD_MUTEX_RECURSIVE",
  152. header: "<pthread.h>".}: SysLockType
  153. proc initSysLockAttr*(a: var SysLockAttr) {.
  154. importc: "pthread_mutexattr_init", header: "<pthread.h>", noSideEffect.}
  155. proc setSysLockType*(a: var SysLockAttr, t: SysLockType) {.
  156. importc: "pthread_mutexattr_settype", header: "<pthread.h>", noSideEffect.}
  157. # locks
  158. proc initSysCondAux(cond: var SysCondObj, cond_attr: ptr SysCondAttr = nil) {.
  159. importc: "pthread_cond_init", header: "<pthread.h>", noSideEffect.}
  160. proc deinitSysCondAux(cond: SysCondObj) {.noSideEffect,
  161. importc: "pthread_cond_destroy", header: "<pthread.h>".}
  162. proc waitSysCondAux(cond: var SysCondObj, lock: var SysLockObj): cint {.
  163. importc: "pthread_cond_wait", header: "<pthread.h>", noSideEffect.}
  164. proc signalSysCondAux(cond: var SysCondObj) {.
  165. importc: "pthread_cond_signal", header: "<pthread.h>", noSideEffect.}
  166. proc broadcastSysCondAux(cond: var SysCondObj) {.
  167. importc: "pthread_cond_broadcast", header: "<pthread.h>", noSideEffect.}
  168. when defined(ios):
  169. proc initSysCond*(cond: var SysCond, cond_attr: ptr SysCondAttr = nil) =
  170. cond = cast[SysCond](c_malloc(csize_t(sizeof(SysCondObj))))
  171. initSysCondAux(cond[], cond_attr)
  172. proc deinitSysCond*(cond: SysCond) =
  173. deinitSysCondAux(cond[])
  174. c_free(cond)
  175. template waitSysCond*(cond: var SysCond, lock: var SysLock) =
  176. discard waitSysCondAux(cond[], lock[])
  177. template signalSysCond*(cond: var SysCond) =
  178. signalSysCondAux(cond[])
  179. template broadcastSysCond*(cond: var SysCond) =
  180. broadcastSysCondAux(cond[])
  181. else:
  182. template initSysCond*(cond: var SysCond, cond_attr: ptr SysCondAttr = nil) =
  183. initSysCondAux(cond, cond_attr)
  184. template deinitSysCond*(cond: SysCond) =
  185. deinitSysCondAux(cond)
  186. template waitSysCond*(cond: var SysCond, lock: var SysLock) =
  187. discard waitSysCondAux(cond, lock)
  188. template signalSysCond*(cond: var SysCond) =
  189. signalSysCondAux(cond)
  190. template broadcastSysCond*(cond: var SysCond) =
  191. broadcastSysCondAux(cond)
  192. {.pop.}