syslocks.nim 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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. SysCond = Handle
  23. proc initSysLock(L: var SysLock) {.importc: "InitializeCriticalSection",
  24. header: "<windows.h>".}
  25. ## Initializes the lock `L`.
  26. proc tryAcquireSysAux(L: var SysLock): int32 {.importc: "TryEnterCriticalSection",
  27. header: "<windows.h>".}
  28. ## Tries to acquire the lock `L`.
  29. proc tryAcquireSys(L: var SysLock): bool {.inline.} =
  30. result = tryAcquireSysAux(L) != 0'i32
  31. proc acquireSys(L: var SysLock) {.importc: "EnterCriticalSection",
  32. header: "<windows.h>".}
  33. ## Acquires the lock `L`.
  34. proc releaseSys(L: var SysLock) {.importc: "LeaveCriticalSection",
  35. header: "<windows.h>".}
  36. ## Releases the lock `L`.
  37. proc deinitSys(L: var SysLock) {.importc: "DeleteCriticalSection",
  38. header: "<windows.h>".}
  39. proc createEvent(lpEventAttributes: pointer,
  40. bManualReset, bInitialState: int32,
  41. lpName: cstring): SysCond {.stdcall, noSideEffect,
  42. dynlib: "kernel32", importc: "CreateEventA".}
  43. proc closeHandle(hObject: Handle) {.stdcall, noSideEffect,
  44. dynlib: "kernel32", importc: "CloseHandle".}
  45. proc waitForSingleObject(hHandle: Handle, dwMilliseconds: int32): int32 {.
  46. stdcall, dynlib: "kernel32", importc: "WaitForSingleObject", noSideEffect.}
  47. proc signalSysCond(hEvent: SysCond) {.stdcall, noSideEffect,
  48. dynlib: "kernel32", importc: "SetEvent".}
  49. proc initSysCond(cond: var SysCond) {.inline.} =
  50. cond = createEvent(nil, 0'i32, 0'i32, nil)
  51. proc deinitSysCond(cond: var SysCond) {.inline.} =
  52. closeHandle(cond)
  53. proc waitSysCond(cond: var SysCond, lock: var SysLock) =
  54. releaseSys(lock)
  55. discard waitForSingleObject(cond, -1'i32)
  56. acquireSys(lock)
  57. proc waitSysCondWindows(cond: var SysCond) =
  58. discard waitForSingleObject(cond, -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. else:
  79. type
  80. SysLockObj {.importc: "pthread_mutex_t", pure, final,
  81. header: """#include <sys/types.h>
  82. #include <pthread.h>""".} = object
  83. when defined(linux) and defined(amd64):
  84. abi: array[40 div sizeof(clong), clong]
  85. SysLockAttr {.importc: "pthread_mutexattr_t", pure, final
  86. header: """#include <sys/types.h>
  87. #include <pthread.h>""".} = object
  88. when defined(linux) and defined(amd64):
  89. abi: array[4 div sizeof(cint), cint] # actually a cint
  90. SysCondObj {.importc: "pthread_cond_t", pure, final,
  91. header: """#include <sys/types.h>
  92. #include <pthread.h>""".} = object
  93. when defined(linux) and defined(amd64):
  94. abi: array[48 div sizeof(clonglong), clonglong]
  95. SysCondAttr {.importc: "pthread_condattr_t", pure, final
  96. header: """#include <sys/types.h>
  97. #include <pthread.h>""".} = object
  98. when defined(linux) and defined(amd64):
  99. abi: array[4 div sizeof(cint), cint] # actually a cint
  100. SysLockType = distinct cint
  101. proc initSysLockAux(L: var SysLockObj, attr: ptr SysLockAttr) {.
  102. importc: "pthread_mutex_init", header: "<pthread.h>", noSideEffect.}
  103. proc deinitSysAux(L: var SysLockObj) {.noSideEffect,
  104. importc: "pthread_mutex_destroy", header: "<pthread.h>".}
  105. proc acquireSysAux(L: var SysLockObj) {.noSideEffect,
  106. importc: "pthread_mutex_lock", header: "<pthread.h>".}
  107. proc tryAcquireSysAux(L: var SysLockObj): cint {.noSideEffect,
  108. importc: "pthread_mutex_trylock", header: "<pthread.h>".}
  109. proc releaseSysAux(L: var SysLockObj) {.noSideEffect,
  110. importc: "pthread_mutex_unlock", header: "<pthread.h>".}
  111. when defined(ios):
  112. # iOS will behave badly if sync primitives are moved in memory. In order
  113. # to prevent this once and for all, we're doing an extra malloc when
  114. # initializing the primitive.
  115. type
  116. SysLock = ptr SysLockObj
  117. SysCond = ptr SysCondObj
  118. when not declared(c_malloc):
  119. proc c_malloc(size: csize): pointer {.
  120. importc: "malloc", header: "<stdlib.h>".}
  121. proc c_free(p: pointer) {.
  122. importc: "free", header: "<stdlib.h>".}
  123. proc initSysLock(L: var SysLock, attr: ptr SysLockAttr = nil) =
  124. L = cast[SysLock](c_malloc(sizeof(SysLockObj)))
  125. initSysLockAux(L[], attr)
  126. proc deinitSys(L: var SysLock) =
  127. deinitSysAux(L[])
  128. c_free(L)
  129. template acquireSys(L: var SysLock) =
  130. acquireSysAux(L[])
  131. template tryAcquireSys(L: var SysLock): bool =
  132. tryAcquireSysAux(L[]) == 0'i32
  133. template releaseSys(L: var SysLock) =
  134. releaseSysAux(L[])
  135. else:
  136. type
  137. SysLock = SysLockObj
  138. SysCond = SysCondObj
  139. template initSysLock(L: var SysLock, attr: ptr SysLockAttr = nil) =
  140. initSysLockAux(L, attr)
  141. template deinitSys(L: var SysLock) =
  142. deinitSysAux(L)
  143. template acquireSys(L: var SysLock) =
  144. acquireSysAux(L)
  145. template tryAcquireSys(L: var SysLock): bool =
  146. tryAcquireSysAux(L) == 0'i32
  147. template releaseSys(L: var SysLock) =
  148. releaseSysAux(L)
  149. when insideRLocksModule:
  150. proc SysLockType_Reentrant: SysLockType =
  151. {.emit: "`result` = PTHREAD_MUTEX_RECURSIVE;".}
  152. proc initSysLockAttr(a: var SysLockAttr) {.
  153. importc: "pthread_mutexattr_init", header: "<pthread.h>", noSideEffect.}
  154. proc setSysLockType(a: var SysLockAttr, t: SysLockType) {.
  155. importc: "pthread_mutexattr_settype", header: "<pthread.h>", noSideEffect.}
  156. else:
  157. proc initSysCondAux(cond: var SysCondObj, cond_attr: ptr SysCondAttr = nil) {.
  158. importc: "pthread_cond_init", header: "<pthread.h>", noSideEffect.}
  159. proc deinitSysCondAux(cond: var SysCondObj) {.noSideEffect,
  160. importc: "pthread_cond_destroy", header: "<pthread.h>".}
  161. proc waitSysCondAux(cond: var SysCondObj, lock: var SysLockObj) {.
  162. importc: "pthread_cond_wait", header: "<pthread.h>", noSideEffect.}
  163. proc signalSysCondAux(cond: var SysCondObj) {.
  164. importc: "pthread_cond_signal", header: "<pthread.h>", noSideEffect.}
  165. when defined(ios):
  166. proc initSysCond(cond: var SysCond, cond_attr: ptr SysCondAttr = nil) =
  167. cond = cast[SysCond](c_malloc(sizeof(SysCondObj)))
  168. initSysCondAux(cond[], cond_attr)
  169. proc deinitSysCond(cond: var SysCond) =
  170. deinitSysCondAux(cond[])
  171. c_free(cond)
  172. template waitSysCond(cond: var SysCond, lock: var SysLock) =
  173. waitSysCondAux(cond[], lock[])
  174. template signalSysCond(cond: var SysCond) =
  175. signalSysCondAux(cond[])
  176. else:
  177. template initSysCond(cond: var SysCond, cond_attr: ptr SysCondAttr = nil) =
  178. initSysCondAux(cond, cond_attr)
  179. template deinitSysCond(cond: var SysCond) =
  180. deinitSysCondAux(cond)
  181. template waitSysCond(cond: var SysCond, lock: var SysLock) =
  182. waitSysCondAux(cond, lock)
  183. template signalSysCond(cond: var SysCond) =
  184. signalSysCondAux(cond)
  185. {.pop.}