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: rpj (at) callisto.canberra.edu.au 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 37 #include "pthread.h" 38 #include "implement.h" 39 40 41 /* 42 * How it works: 43 * A pthread_t is a struct (2x32 bit scalar types on IA-32, 2x64 bit on IA-64) 44 * which is normally passed/returned by value to/from pthreads routines. 45 * Applications are therefore storing a copy of the struct as it is at that 46 * time. 47 * 48 * The original pthread_t struct plus all copies of it contain the address of 49 * the thread state struct ptw32_thread_t_ (p), plus a reuse counter (x). Each 50 * ptw32_thread_t contains the original copy of it's pthread_t. 51 * Once malloced, a ptw32_thread_t_ struct is not freed until the process exits. 52 * 53 * The thread reuse stack is a simple LILO stack managed through a singly 54 * linked list element in the ptw32_thread_t. 55 * 56 * Each time a thread is destroyed, the ptw32_thread_t address is pushed onto the 57 * reuse stack after it's ptHandle's reuse counter has been incremented. 58 * 59 * The following can now be said from this: 60 * - two pthread_t's are identical if their ptw32_thread_t reference pointers 61 * are equal and their reuse counters are equal. That is, 62 * 63 * equal = (a.p == b.p && a.x == b.x) 64 * 65 * - a pthread_t copy refers to a destroyed thread if the reuse counter in 66 * the copy is not equal to the reuse counter in the original. 67 * 68 * threadDestroyed = (copy.x != ((ptw32_thread_t *)copy.p)->ptHandle.x) 69 * 70 */ 71 72 /* 73 * Pop a clean pthread_t struct off the reuse stack. 74 */ 75 pthread_t 76 ptw32_threadReusePop (void) 77 { 78 pthread_t t = {NULL, 0}; 79 ptw32_mcs_local_node_t node; 80 81 ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node); 82 83 if (PTW32_THREAD_REUSE_EMPTY != ptw32_threadReuseTop) 84 { 85 ptw32_thread_t * tp; 86 87 tp = ptw32_threadReuseTop; 88 89 ptw32_threadReuseTop = tp->prevReuse; 90 91 if (PTW32_THREAD_REUSE_EMPTY == ptw32_threadReuseTop) 92 { 93 ptw32_threadReuseBottom = PTW32_THREAD_REUSE_EMPTY; 94 } 95 96 tp->prevReuse = NULL; 97 98 t = tp->ptHandle; 99 } 100 101 ptw32_mcs_lock_release(&node); 102 103 return t; 104 105 } 106 107 /* 108 * Push a clean pthread_t struct onto the reuse stack. 109 * Must be re-initialised when reused. 110 * All object elements (mutexes, events etc) must have been either 111 * detroyed before this, or never initialised. 112 */ 113 void 114 ptw32_threadReusePush (pthread_t thread) 115 { 116 ptw32_thread_t * tp = (ptw32_thread_t *) thread.p; 117 pthread_t t; 118 ptw32_mcs_local_node_t node; 119 120 ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node); 121 122 t = tp->ptHandle; 123 memset(tp, 0, sizeof(ptw32_thread_t)); 124 125 /* Must restore the original POSIX handle that we just wiped. */ 126 tp->ptHandle = t; 127 128 /* Bump the reuse counter now */ 129 #if defined(PTW32_THREAD_ID_REUSE_INCREMENT) 130 tp->ptHandle.x += PTW32_THREAD_ID_REUSE_INCREMENT; 131 #else 132 tp->ptHandle.x++; 133 #endif 134 135 tp->state = PThreadStateReuse; 136 137 tp->prevReuse = PTW32_THREAD_REUSE_EMPTY; 138 139 if (PTW32_THREAD_REUSE_EMPTY != ptw32_threadReuseBottom) 140 { 141 ptw32_threadReuseBottom->prevReuse = tp; 142 } 143 else 144 { 145 ptw32_threadReuseTop = tp; 146 } 147 148 ptw32_threadReuseBottom = tp; 149 150 ptw32_mcs_lock_release(&node); 151 } 152