Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

213 lines
7.5 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 2001 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: threadlocalptrs.h
  6. * Content: Thread local pointer macros
  7. *
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 03/21/2001 vanceo Created.
  12. ***************************************************************************/
  13. #ifndef __THREADLOCALPTRS_H__
  14. #define __THREADLOCALPTRS_H__
  15. //**********************************************************************
  16. // Structure definitions
  17. //**********************************************************************
  18. typedef struct _THREADLOCAL_HEADER THREADLOCAL_HEADER, * PTHREADLOCAL_HEADER;
  19. struct _THREADLOCAL_HEADER
  20. {
  21. PTHREADLOCAL_HEADER pNext; // pointer to next allocated threadlocal structure header
  22. PTHREADLOCAL_HEADER pPrev; // pointer to previous allocated threadlocal structure header
  23. DWORD dwThreadID; // ID of thread that owns this header
  24. //
  25. // The actual thread local pointer structure follows this.
  26. //
  27. };
  28. //**********************************************************************
  29. // Macro definitions
  30. //**********************************************************************
  31. //
  32. // Global thread local pointer declarations.
  33. //
  34. #define DECLARE_THREADLOCALPTRS(pointers) extern DWORD g_dw##pointers##TlsIndex;\
  35. extern DNCRITICAL_SECTION g_csAllocated##pointers;\
  36. extern PTHREADLOCAL_HEADER g_pAllocated##pointers;\
  37. \
  38. struct pointers
  39. //
  40. // Thread local pointer storage, define in only one location.
  41. //
  42. #define IMPL_THREADLOCALPTRS(pointers) DWORD g_dw##pointers##TlsIndex = -1;\
  43. DNCRITICAL_SECTION g_csAllocated##pointers;\
  44. PTHREADLOCAL_HEADER g_pAllocated##pointers = NULL
  45. //
  46. // Thread local pointer initialization, call only once (DLL_PROCESS_ATTACH),
  47. // returns TRUE if successful, FALSE otherwise.
  48. //
  49. #define INIT_THREADLOCALPTRS(pointers) g_pAllocated##pointers = NULL, g_dw##pointers##TlsIndex = TlsAlloc(), ((g_dw##pointers##TlsIndex != -1) ? DNInitializeCriticalSection(&g_csAllocated##pointers) : FALSE)
  50. //
  51. // Total thread local pointer cleanup, call only once (DLL_PROCESS_DETACH).
  52. //
  53. #define DEINIT_THREADLOCALPTRS(pointers, pfnCleanup) {\
  54. PTHREADLOCAL_HEADER pNext;\
  55. \
  56. \
  57. if (g_dw##pointers##TlsIndex != -1)\
  58. {\
  59. DNDeleteCriticalSection(&g_csAllocated##pointers);\
  60. \
  61. TlsFree(g_dw##pointers##TlsIndex);\
  62. g_dw##pointers##TlsIndex = -1;\
  63. }\
  64. \
  65. while (g_pAllocated##pointers != NULL)\
  66. {\
  67. pNext = g_pAllocated##pointers->pNext;\
  68. pfnCleanup((pointers *) (g_pAllocated##pointers + 1), g_pAllocated##pointers->dwThreadID);\
  69. DNFree(g_pAllocated##pointers);\
  70. g_pAllocated##pointers = pNext;\
  71. }\
  72. }
  73. //
  74. // Cleanup only current thread's local pointers (DLL_THREAD_DETACH).
  75. //
  76. #define RELEASE_CURRENTTHREAD_LOCALPTRS(pointers, pfnCleanup) {\
  77. PTHREADLOCAL_HEADER pHeader;\
  78. PTHREADLOCAL_HEADER pNext;\
  79. \
  80. \
  81. pHeader = (PTHREADLOCAL_HEADER) TlsGetValue(g_dw##pointers##TlsIndex);\
  82. if (pHeader != NULL)\
  83. {\
  84. DNEnterCriticalSection(&g_csAllocated##pointers);\
  85. \
  86. pNext = pHeader->pNext;\
  87. if (pHeader->pPrev != NULL)\
  88. {\
  89. pHeader->pPrev->pNext = pNext;\
  90. }\
  91. if (pNext != NULL)\
  92. {\
  93. pNext->pPrev = pHeader->pPrev;\
  94. }\
  95. \
  96. if (pHeader == g_pAllocated##pointers)\
  97. {\
  98. g_pAllocated##pointers = pNext;\
  99. }\
  100. \
  101. DNLeaveCriticalSection(&g_csAllocated##pointers);\
  102. \
  103. DNASSERT(pHeader->dwThreadID == GetCurrentThreadId());\
  104. pfnCleanup((pointers *) (pHeader + 1), pHeader->dwThreadID);\
  105. DNFree(pHeader);\
  106. }\
  107. }
  108. //
  109. // Thread local pointer retrieval function.
  110. //
  111. #define GET_THREADLOCALPTR(pointers, name, pptr) {\
  112. PTHREADLOCAL_HEADER pHeader;\
  113. \
  114. \
  115. pHeader = (PTHREADLOCAL_HEADER) TlsGetValue(g_dw##pointers##TlsIndex);\
  116. if (pHeader == NULL)\
  117. {\
  118. DPFX(DPFPREP, 9, "No header for " #name ".");\
  119. (*pptr) = NULL;\
  120. }\
  121. else\
  122. {\
  123. DPFX(DPFPREP, 9, "Found header 0x%p, returning " #name " 0x%p.", pHeader, ((pointers *) (pHeader + 1))->name);\
  124. (*pptr) = ((pointers *) (pHeader + 1))->name;\
  125. }\
  126. }
  127. //
  128. // Thread local pointer storage function.
  129. //
  130. #define SET_THREADLOCALPTR(pointers, name, ptr, pfResult) {\
  131. PTHREADLOCAL_HEADER pHeader;\
  132. \
  133. \
  134. pHeader = (PTHREADLOCAL_HEADER) TlsGetValue(g_dw##pointers##TlsIndex);\
  135. if (pHeader == NULL)\
  136. {\
  137. pHeader = (PTHREADLOCAL_HEADER) DNMalloc(sizeof(THREADLOCAL_HEADER) + sizeof(pointers));\
  138. if (pHeader == NULL)\
  139. {\
  140. (*pfResult) = FALSE;\
  141. }\
  142. else\
  143. {\
  144. memset(pHeader, 0, (sizeof(THREADLOCAL_HEADER) + sizeof(pointers)));\
  145. pHeader->dwThreadID = GetCurrentThreadId();\
  146. ((pointers *) (pHeader + 1))->name = ptr;\
  147. \
  148. if (! TlsSetValue(g_dw##pointers##TlsIndex, pHeader))\
  149. {\
  150. DPFX(DPFPREP, 9, "Couldn't set thread local storage 0x%p!", pHeader);\
  151. DNFree(pHeader);\
  152. (*pfResult) = FALSE;\
  153. }\
  154. else\
  155. {\
  156. DPFX(DPFPREP, 9, "Setting 0x%p " #name " to 0x%p (create).", pHeader, ptr);\
  157. \
  158. DNEnterCriticalSection(&g_csAllocated##pointers);\
  159. pHeader->pNext = g_pAllocated##pointers;\
  160. if (g_pAllocated##pointers != NULL)\
  161. {\
  162. DNASSERT(g_pAllocated##pointers##->pPrev == NULL);\
  163. g_pAllocated##pointers##->pPrev = pHeader;\
  164. }\
  165. g_pAllocated##pointers = pHeader;\
  166. DNLeaveCriticalSection(&g_csAllocated##pointers);\
  167. \
  168. (*pfResult) = TRUE;\
  169. }\
  170. }\
  171. }\
  172. else\
  173. {\
  174. DPFX(DPFPREP, 9, "Setting 0x%p " #name " to 0x%p (existing).", pHeader, ptr);\
  175. DNASSERT(((pointers *) (pHeader + 1))->name == NULL);\
  176. ((pointers *) (pHeader + 1))->name = ptr;\
  177. (*pfResult) = TRUE;\
  178. }\
  179. }
  180. #endif // __THREADLOCALPTRS_H__