/[pcsx2_0.9.7]/trunk/3rdparty/w32pthreads/ptw32_callUserDestroyRoutines.c
ViewVC logotype

Contents of /trunk/3rdparty/w32pthreads/ptw32_callUserDestroyRoutines.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (9 years, 11 months ago) by william
File MIME type: text/plain
File size: 6677 byte(s)
committing r3113 initial commit again...
1 /*
2 * ptw32_callUserDestroyRoutines.c
3 *
4 * Description:
5 * This translation unit implements routines which are private to
6 * the implementation and may be used throughout it.
7 *
8 * --------------------------------------------------------------------------
9 *
10 * Pthreads-win32 - POSIX Threads Library for Win32
11 * Copyright(C) 1998 John E. Bossom
12 * Copyright(C) 1999,2005 Pthreads-win32 contributors
13 *
14 * Contact Email: rpj@callisto.canberra.edu.au
15 *
16 * The current list of contributors is contained
17 * in the file CONTRIBUTORS included with the source
18 * code distribution. The list can also be seen at the
19 * following World Wide Web location:
20 * http://sources.redhat.com/pthreads-win32/contributors.html
21 *
22 * This library is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU Lesser General Public
24 * License as published by the Free Software Foundation; either
25 * version 2 of the License, or (at your option) any later version.
26 *
27 * This library is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 * Lesser General Public License for more details.
31 *
32 * You should have received a copy of the GNU Lesser General Public
33 * License along with this library in the file COPYING.LIB;
34 * if not, write to the Free Software Foundation, Inc.,
35 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
36 */
37
38 #include "ptw32pch.h"
39
40 #ifdef __cplusplus
41 # if ! defined (_MSC_VER) && ! (defined(__GNUC__) && __GNUC__ < 3) && ! defined(__WATCOMC__)
42 using
43 std::terminate;
44 # endif
45 #endif
46
47 void
48 ptw32_callUserDestroyRoutines (pthread_t thread)
49 /*
50 * -------------------------------------------------------------------
51 * DOCPRIVATE
52 *
53 * This the routine runs through all thread keys and calls
54 * the destroy routines on the user's data for the current thread.
55 * It simulates the behaviour of POSIX Threads.
56 *
57 * PARAMETERS
58 * thread
59 * an instance of pthread_t
60 *
61 * RETURNS
62 * N/A
63 * -------------------------------------------------------------------
64 */
65 {
66 ThreadKeyAssoc * assoc;
67
68 if (thread.p != NULL)
69 {
70 int assocsRemaining;
71 int iterations = 0;
72 ptw32_thread_t * sp = (ptw32_thread_t *) thread.p;
73
74 /*
75 * Run through all Thread<-->Key associations
76 * for the current thread.
77 *
78 * Do this process at most PTHREAD_DESTRUCTOR_ITERATIONS times.
79 */
80 do
81 {
82 assocsRemaining = 0;
83 iterations++;
84
85 (void) pthread_mutex_lock(&(sp->threadLock));
86 /*
87 * The pointer to the next assoc is stored in the thread struct so that
88 * the assoc destructor in pthread_key_delete can adjust it
89 * if it deletes this assoc. This can happen if we fail to acquire
90 * both locks below, and are forced to release all of our locks,
91 * leaving open the opportunity for pthread_key_delete to get in
92 * before us.
93 */
94 sp->nextAssoc = sp->keys;
95 (void) pthread_mutex_unlock(&(sp->threadLock));
96
97 for (;;)
98 {
99 void * value;
100 pthread_key_t k;
101 void (*destructor) (void *);
102
103 /*
104 * First we need to serialise with pthread_key_delete by locking
105 * both assoc guards, but in the reverse order to our convention,
106 * so we must be careful to avoid deadlock.
107 */
108 (void) pthread_mutex_lock(&(sp->threadLock));
109
110 if ((assoc = (ThreadKeyAssoc *)sp->nextAssoc) == NULL)
111 {
112 /* Finished */
113 pthread_mutex_unlock(&(sp->threadLock));
114 break;
115 }
116 else
117 {
118 /*
119 * assoc->key must be valid because assoc can't change or be
120 * removed from our chain while we hold at least one lock. If
121 * the assoc was on our key chain then the key has not been
122 * deleted yet.
123 *
124 * Now try to acquire the second lock without deadlocking.
125 * If we fail, we need to relinquish the first lock and the
126 * processor and then try to acquire them all again.
127 */
128 if (pthread_mutex_trylock(&(assoc->key->keyLock)) == EBUSY)
129 {
130 pthread_mutex_unlock(&(sp->threadLock));
131 Sleep(1); // Ugly but necessary to avoid priority effects.
132 /*
133 * Go around again.
134 * If pthread_key_delete has removed this assoc in the meantime,
135 * sp->nextAssoc will point to a new assoc.
136 */
137 continue;
138 }
139 }
140
141 /* We now hold both locks */
142
143 sp->nextAssoc = assoc->nextKey;
144
145 /*
146 * Key still active; pthread_key_delete
147 * will block on these same mutexes before
148 * it can release actual key; therefore,
149 * key is valid and we can call the destroy
150 * routine;
151 */
152 k = assoc->key;
153 destructor = k->destructor;
154 value = TlsGetValue(k->key);
155 TlsSetValue (k->key, NULL);
156
157 // Every assoc->key exists and has a destructor
158 if (value != NULL && iterations <= PTHREAD_DESTRUCTOR_ITERATIONS)
159 {
160 /*
161 * Unlock both locks before the destructor runs.
162 * POSIX says pthread_key_delete can be run from destructors,
163 * and that probably includes with this key as target.
164 * pthread_setspecific can also be run from destructors and
165 * also needs to be able to access the assocs.
166 */
167 (void) pthread_mutex_unlock(&(sp->threadLock));
168 (void) pthread_mutex_unlock(&(k->keyLock));
169
170 assocsRemaining++;
171
172 #ifdef __cplusplus
173
174 try
175 {
176 /*
177 * Run the caller's cleanup routine.
178 */
179 destructor (value);
180 }
181 catch (...)
182 {
183 /*
184 * A system unexpected exception has occurred
185 * running the user's destructor.
186 * We get control back within this block in case
187 * the application has set up it's own terminate
188 * handler. Since we are leaving the thread we
189 * should not get any internal pthreads
190 * exceptions.
191 */
192 terminate ();
193 }
194
195 #else /* __cplusplus */
196
197 /*
198 * Run the caller's cleanup routine.
199 */
200 destructor (value);
201
202 #endif /* __cplusplus */
203
204 }
205 else
206 {
207 /*
208 * Remove association from both the key and thread chains
209 * and reclaim it's memory resources.
210 */
211 ptw32_tkAssocDestroy (assoc);
212 (void) pthread_mutex_unlock(&(sp->threadLock));
213 (void) pthread_mutex_unlock(&(k->keyLock));
214 }
215 }
216 }
217 while (assocsRemaining);
218 }
219 } /* ptw32_callUserDestroyRoutines */

  ViewVC Help
Powered by ViewVC 1.1.22