/src/rt/critical_.d

http://github.com/AlexeyProkhin/druntime · D · 211 lines · 158 code · 24 blank · 29 comment · 16 complexity · 6c94a848845b192826b97da5ffd92456 MD5 · raw file

  1. /**
  2. * Implementation of support routines for synchronized blocks.
  3. *
  4. * Copyright: Copyright Digital Mars 2000 - 2011.
  5. * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
  6. * Authors: Walter Bright, Sean Kelly
  7. */
  8. /* Copyright Digital Mars 2000 - 2011.
  9. * Distributed under the Boost Software License, Version 1.0.
  10. * (See accompanying file LICENSE or copy at
  11. * http://www.boost.org/LICENSE_1_0.txt)
  12. */
  13. module rt.critical_;
  14. private
  15. {
  16. debug(PRINTF) import core.stdc.stdio;
  17. import core.stdc.stdlib;
  18. version( linux )
  19. {
  20. version = USE_PTHREADS;
  21. }
  22. else version( FreeBSD )
  23. {
  24. version = USE_PTHREADS;
  25. }
  26. else version( OSX )
  27. {
  28. version = USE_PTHREADS;
  29. }
  30. else version( Solaris )
  31. {
  32. version = USE_PTHREADS;
  33. }
  34. version( Windows )
  35. {
  36. import core.sys.windows.windows;
  37. /* We don't initialize critical sections unless we actually need them.
  38. * So keep a linked list of the ones we do use, and in the static destructor
  39. * code, walk the list and release them.
  40. */
  41. struct D_CRITICAL_SECTION
  42. {
  43. D_CRITICAL_SECTION *next;
  44. CRITICAL_SECTION cs;
  45. }
  46. }
  47. else version( USE_PTHREADS )
  48. {
  49. import core.sys.posix.pthread;
  50. /* We don't initialize critical sections unless we actually need them.
  51. * So keep a linked list of the ones we do use, and in the static destructor
  52. * code, walk the list and release them.
  53. */
  54. struct D_CRITICAL_SECTION
  55. {
  56. D_CRITICAL_SECTION *next;
  57. pthread_mutex_t cs;
  58. }
  59. }
  60. else
  61. {
  62. static assert(0, "Unsupported platform");
  63. }
  64. }
  65. /* ================================= Win32 ============================ */
  66. version( Windows )
  67. {
  68. version (DigitalMars) version (Win32)
  69. pragma(lib, "snn.lib");
  70. /******************************************
  71. * Enter/exit critical section.
  72. */
  73. static __gshared D_CRITICAL_SECTION *dcs_list;
  74. static __gshared D_CRITICAL_SECTION critical_section;
  75. static __gshared int inited;
  76. extern (C) void _d_criticalenter(D_CRITICAL_SECTION *dcs)
  77. {
  78. if (!dcs_list)
  79. {
  80. _STI_critical_init();
  81. atexit(&_STD_critical_term);
  82. }
  83. debug(PRINTF) printf("_d_criticalenter(dcs = x%x)\n", dcs);
  84. if (!dcs.next)
  85. {
  86. EnterCriticalSection(&critical_section.cs);
  87. if (!dcs.next) // if, in the meantime, another thread didn't set it
  88. {
  89. dcs.next = dcs_list;
  90. dcs_list = dcs;
  91. InitializeCriticalSection(&dcs.cs);
  92. }
  93. LeaveCriticalSection(&critical_section.cs);
  94. }
  95. EnterCriticalSection(&dcs.cs);
  96. }
  97. extern (C) void _d_criticalexit(D_CRITICAL_SECTION *dcs)
  98. {
  99. debug(PRINTF) printf("_d_criticalexit(dcs = x%x)\n", dcs);
  100. LeaveCriticalSection(&dcs.cs);
  101. }
  102. extern (C) void _STI_critical_init()
  103. {
  104. if (!inited)
  105. {
  106. debug(PRINTF) printf("_STI_critical_init()\n");
  107. InitializeCriticalSection(&critical_section.cs);
  108. dcs_list = &critical_section;
  109. inited = 1;
  110. }
  111. }
  112. extern (C) void _STD_critical_term()
  113. {
  114. if (inited)
  115. {
  116. debug(PRINTF) printf("_STI_critical_term()\n");
  117. while (dcs_list)
  118. {
  119. debug(PRINTF) printf("\tlooping... %x\n", dcs_list);
  120. DeleteCriticalSection(&dcs_list.cs);
  121. dcs_list = dcs_list.next;
  122. }
  123. inited = 0;
  124. }
  125. }
  126. }
  127. /* ================================= linux ============================ */
  128. version( USE_PTHREADS )
  129. {
  130. /******************************************
  131. * Enter/exit critical section.
  132. */
  133. static __gshared D_CRITICAL_SECTION *dcs_list;
  134. static __gshared D_CRITICAL_SECTION critical_section;
  135. static __gshared pthread_mutexattr_t _criticals_attr;
  136. extern (C) void _d_criticalenter(D_CRITICAL_SECTION *dcs)
  137. {
  138. if (!dcs_list)
  139. {
  140. _STI_critical_init();
  141. atexit(&_STD_critical_term);
  142. }
  143. debug(PRINTF) printf("_d_criticalenter(dcs = x%x)\n", dcs);
  144. if (!dcs.next)
  145. {
  146. pthread_mutex_lock(&critical_section.cs);
  147. if (!dcs.next) // if, in the meantime, another thread didn't set it
  148. {
  149. dcs.next = dcs_list;
  150. dcs_list = dcs;
  151. pthread_mutex_init(&dcs.cs, &_criticals_attr);
  152. }
  153. pthread_mutex_unlock(&critical_section.cs);
  154. }
  155. pthread_mutex_lock(&dcs.cs);
  156. }
  157. extern (C) void _d_criticalexit(D_CRITICAL_SECTION *dcs)
  158. {
  159. debug(PRINTF) printf("_d_criticalexit(dcs = x%x)\n", dcs);
  160. pthread_mutex_unlock(&dcs.cs);
  161. }
  162. extern (C) void _STI_critical_init()
  163. {
  164. if (!dcs_list)
  165. {
  166. debug(PRINTF) printf("_STI_critical_init()\n");
  167. pthread_mutexattr_init(&_criticals_attr);
  168. pthread_mutexattr_settype(&_criticals_attr, PTHREAD_MUTEX_RECURSIVE);
  169. // The global critical section doesn't need to be recursive
  170. pthread_mutex_init(&critical_section.cs, null);
  171. dcs_list = &critical_section;
  172. }
  173. }
  174. extern (C) void _STD_critical_term()
  175. {
  176. if (dcs_list)
  177. {
  178. debug(PRINTF) printf("_STI_critical_term()\n");
  179. while (dcs_list)
  180. {
  181. debug(PRINTF) printf("\tlooping... %x\n", dcs_list);
  182. pthread_mutex_destroy(&dcs_list.cs);
  183. dcs_list = dcs_list.next;
  184. }
  185. }
  186. }
  187. }