ptw32_reuse.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /*
  2. * ptw32_threadReuse.c
  3. *
  4. * Description:
  5. * This translation unit implements miscellaneous thread functions.
  6. *
  7. * --------------------------------------------------------------------------
  8. *
  9. * Pthreads-win32 - POSIX Threads Library for Win32
  10. * Copyright(C) 1998 John E. Bossom
  11. * Copyright(C) 1999,2005 Pthreads-win32 contributors
  12. *
  13. * Contact Email: [email protected]
  14. *
  15. * The current list of contributors is contained
  16. * in the file CONTRIBUTORS included with the source
  17. * code distribution. The list can also be seen at the
  18. * following World Wide Web location:
  19. * http://sources.redhat.com/pthreads-win32/contributors.html
  20. *
  21. * This library is free software; you can redistribute it and/or
  22. * modify it under the terms of the GNU Lesser General Public
  23. * License as published by the Free Software Foundation; either
  24. * version 2 of the License, or (at your option) any later version.
  25. *
  26. * This library is distributed in the hope that it will be useful,
  27. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  28. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  29. * Lesser General Public License for more details.
  30. *
  31. * You should have received a copy of the GNU Lesser General Public
  32. * License along with this library in the file COPYING.LIB;
  33. * if not, write to the Free Software Foundation, Inc.,
  34. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  35. */
  36. #include "pthread.h"
  37. #include "implement.h"
  38. /*
  39. * How it works:
  40. * A pthread_t is a struct (2x32 bit scalar types on IA-32, 2x64 bit on IA-64)
  41. * which is normally passed/returned by value to/from pthreads routines.
  42. * Applications are therefore storing a copy of the struct as it is at that
  43. * time.
  44. *
  45. * The original pthread_t struct plus all copies of it contain the address of
  46. * the thread state struct ptw32_thread_t_ (p), plus a reuse counter (x). Each
  47. * ptw32_thread_t contains the original copy of it's pthread_t.
  48. * Once malloced, a ptw32_thread_t_ struct is not freed until the process exits.
  49. *
  50. * The thread reuse stack is a simple LILO stack managed through a singly
  51. * linked list element in the ptw32_thread_t.
  52. *
  53. * Each time a thread is destroyed, the ptw32_thread_t address is pushed onto the
  54. * reuse stack after it's ptHandle's reuse counter has been incremented.
  55. *
  56. * The following can now be said from this:
  57. * - two pthread_t's are identical if their ptw32_thread_t reference pointers
  58. * are equal and their reuse counters are equal. That is,
  59. *
  60. * equal = (a.p == b.p && a.x == b.x)
  61. *
  62. * - a pthread_t copy refers to a destroyed thread if the reuse counter in
  63. * the copy is not equal to the reuse counter in the original.
  64. *
  65. * threadDestroyed = (copy.x != ((ptw32_thread_t *)copy.p)->ptHandle.x)
  66. *
  67. */
  68. /*
  69. * Pop a clean pthread_t struct off the reuse stack.
  70. */
  71. pthread_t
  72. ptw32_threadReusePop (void)
  73. {
  74. pthread_t t = {NULL, 0};
  75. ptw32_mcs_local_node_t node;
  76. ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node);
  77. if (PTW32_THREAD_REUSE_EMPTY != ptw32_threadReuseTop)
  78. {
  79. ptw32_thread_t * tp;
  80. tp = ptw32_threadReuseTop;
  81. ptw32_threadReuseTop = tp->prevReuse;
  82. if (PTW32_THREAD_REUSE_EMPTY == ptw32_threadReuseTop)
  83. {
  84. ptw32_threadReuseBottom = PTW32_THREAD_REUSE_EMPTY;
  85. }
  86. tp->prevReuse = NULL;
  87. t = tp->ptHandle;
  88. }
  89. ptw32_mcs_lock_release(&node);
  90. return t;
  91. }
  92. /*
  93. * Push a clean pthread_t struct onto the reuse stack.
  94. * Must be re-initialised when reused.
  95. * All object elements (mutexes, events etc) must have been either
  96. * detroyed before this, or never initialised.
  97. */
  98. void
  99. ptw32_threadReusePush (pthread_t thread)
  100. {
  101. ptw32_thread_t * tp = (ptw32_thread_t *) thread.p;
  102. pthread_t t;
  103. ptw32_mcs_local_node_t node;
  104. ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node);
  105. t = tp->ptHandle;
  106. memset(tp, 0, sizeof(ptw32_thread_t));
  107. /* Must restore the original POSIX handle that we just wiped. */
  108. tp->ptHandle = t;
  109. /* Bump the reuse counter now */
  110. #if defined(PTW32_THREAD_ID_REUSE_INCREMENT)
  111. tp->ptHandle.x += PTW32_THREAD_ID_REUSE_INCREMENT;
  112. #else
  113. tp->ptHandle.x++;
  114. #endif
  115. tp->state = PThreadStateReuse;
  116. tp->prevReuse = PTW32_THREAD_REUSE_EMPTY;
  117. if (PTW32_THREAD_REUSE_EMPTY != ptw32_threadReuseBottom)
  118. {
  119. ptw32_threadReuseBottom->prevReuse = tp;
  120. }
  121. else
  122. {
  123. ptw32_threadReuseTop = tp;
  124. }
  125. ptw32_threadReuseBottom = tp;
  126. ptw32_mcs_lock_release(&node);
  127. }