threadlocalstorage.nim 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import std/private/threadtypes
  2. when defined(windows):
  3. type
  4. ThreadVarSlot = distinct int32
  5. proc threadVarAlloc(): ThreadVarSlot {.
  6. importc: "TlsAlloc", stdcall, header: "<windows.h>".}
  7. proc threadVarSetValue(dwTlsIndex: ThreadVarSlot, lpTlsValue: pointer) {.
  8. importc: "TlsSetValue", stdcall, header: "<windows.h>".}
  9. proc tlsGetValue(dwTlsIndex: ThreadVarSlot): pointer {.
  10. importc: "TlsGetValue", stdcall, header: "<windows.h>".}
  11. proc getLastError(): uint32 {.
  12. importc: "GetLastError", stdcall, header: "<windows.h>".}
  13. proc setLastError(x: uint32) {.
  14. importc: "SetLastError", stdcall, header: "<windows.h>".}
  15. proc threadVarGetValue(dwTlsIndex: ThreadVarSlot): pointer =
  16. let realLastError = getLastError()
  17. result = tlsGetValue(dwTlsIndex)
  18. setLastError(realLastError)
  19. elif defined(genode):
  20. const
  21. GenodeHeader = "genode_cpp/threads.h"
  22. type
  23. ThreadVarSlot = int
  24. proc threadVarAlloc(): ThreadVarSlot = 0
  25. proc offMainThread(): bool {.
  26. importcpp: "Nim::SysThread::offMainThread",
  27. header: GenodeHeader.}
  28. proc threadVarSetValue(value: pointer) {.
  29. importcpp: "Nim::SysThread::threadVarSetValue(@)",
  30. header: GenodeHeader.}
  31. proc threadVarGetValue(): pointer {.
  32. importcpp: "Nim::SysThread::threadVarGetValue()",
  33. header: GenodeHeader.}
  34. var mainTls: pointer
  35. proc threadVarSetValue(s: ThreadVarSlot, value: pointer) {.inline.} =
  36. if offMainThread():
  37. threadVarSetValue(value);
  38. else:
  39. mainTls = value
  40. proc threadVarGetValue(s: ThreadVarSlot): pointer {.inline.} =
  41. if offMainThread():
  42. threadVarGetValue();
  43. else:
  44. mainTls
  45. else:
  46. when not (defined(macosx) or defined(haiku)):
  47. {.passl: "-pthread".}
  48. when not defined(haiku):
  49. {.passc: "-pthread".}
  50. when (defined(linux) or defined(nintendoswitch)) and defined(amd64):
  51. type
  52. ThreadVarSlot {.importc: "pthread_key_t",
  53. header: "<sys/types.h>".} = distinct cuint
  54. elif defined(openbsd) and defined(amd64):
  55. type
  56. ThreadVarSlot {.importc: "pthread_key_t",
  57. header: "<pthread.h>".} = cint
  58. else:
  59. type
  60. ThreadVarSlot {.importc: "pthread_key_t",
  61. header: "<sys/types.h>".} = object
  62. proc pthread_getspecific(a1: ThreadVarSlot): pointer {.
  63. importc: "pthread_getspecific", header: pthreadh.}
  64. proc pthread_key_create(a1: ptr ThreadVarSlot,
  65. destruct: proc (x: pointer) {.noconv.}): int32 {.
  66. importc: "pthread_key_create", header: pthreadh.}
  67. proc pthread_key_delete(a1: ThreadVarSlot): int32 {.
  68. importc: "pthread_key_delete", header: pthreadh.}
  69. proc pthread_setspecific(a1: ThreadVarSlot, a2: pointer): int32 {.
  70. importc: "pthread_setspecific", header: pthreadh.}
  71. proc threadVarAlloc(): ThreadVarSlot {.inline.} =
  72. discard pthread_key_create(addr(result), nil)
  73. proc threadVarSetValue(s: ThreadVarSlot, value: pointer) {.inline.} =
  74. discard pthread_setspecific(s, value)
  75. proc threadVarGetValue(s: ThreadVarSlot): pointer {.inline.} =
  76. result = pthread_getspecific(s)
  77. when emulatedThreadVars:
  78. # the compiler generates this proc for us, so that we can get the size of
  79. # the thread local var block; we use this only for sanity checking though
  80. proc nimThreadVarsSize(): int {.noconv, importc: "NimThreadVarsSize".}
  81. when emulatedThreadVars:
  82. var globalsSlot: ThreadVarSlot
  83. when not defined(useNimRtl):
  84. var mainThread: GcThread
  85. proc GetThreadLocalVars(): pointer {.compilerRtl, inl.} =
  86. result = addr(cast[PGcThread](threadVarGetValue(globalsSlot)).tls)
  87. proc initThreadVarsEmulation() {.compilerproc, inline.} =
  88. when not defined(useNimRtl):
  89. globalsSlot = threadVarAlloc()
  90. when declared(mainThread):
  91. threadVarSetValue(globalsSlot, addr(mainThread))
  92. when not defined(useNimRtl):
  93. when emulatedThreadVars:
  94. if nimThreadVarsSize() > sizeof(ThreadLocalStorage):
  95. c_fprintf(cstderr, """too large thread local storage size requested,
  96. use -d:\"nimTlsSize=X\" to setup even more or stop using unittest.nim""")
  97. rawQuit 1