syslocks.nim 8.7 KB

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