comparison Python/thread.c @ 33950:633be43bed17 2.3

Backported thread fixes from 2.4 (by mostly copying pystate.c over from 2.4): * using malloc() and free() directly, as explained in the new comment * coding style in the PyGILState_*() functions * the recent destroy-tstate-without-holding-the-GIL bug * lock fixes and many more comments in thread.c
author Armin Rigo <arigo@tunes.org>
date Tue, 09 Nov 2004 15:35:23 +0000
parents 1a817694ecbd
children
comparison
equal deleted inserted replaced
33913:9ce5764019ae 33950:633be43bed17
144 TLS implementation, provide our own. 144 TLS implementation, provide our own.
145 145
146 This code stolen from "thread_sgi.h", where it was the only 146 This code stolen from "thread_sgi.h", where it was the only
147 implementation of an existing Python TLS API. 147 implementation of an existing Python TLS API.
148 */ 148 */
149 /* 149 /* ------------------------------------------------------------------------
150 * Per-thread data ("key") support. 150 Per-thread data ("key") support.
151 */ 151
152 152 Use PyThread_create_key() to create a new key. This is typically shared
153 across threads.
154
155 Use PyThread_set_key_value(thekey, value) to associate void* value with
156 thekey in the current thread. Each thread has a distinct mapping of thekey
157 to a void* value. Caution: if the current thread already has a mapping
158 for thekey, value is ignored.
159
160 Use PyThread_get_key_value(thekey) to retrieve the void* value associated
161 with thekey in the current thread. This returns NULL if no value is
162 associated with thekey in the current thread.
163
164 Use PyThread_delete_key_value(thekey) to forget the current thread's associated
165 value for thekey. PyThread_delete_key(thekey) forgets the values associated
166 with thekey across *all* threads.
167
168 While some of these functions have error-return values, none set any
169 Python exception.
170
171 None of the functions does memory management on behalf of the void* values.
172 You need to allocate and deallocate them yourself. If the void* values
173 happen to be PyObject*, these functions don't do refcount operations on
174 them either.
175
176 The GIL does not need to be held when calling these functions; they supply
177 their own locking. This isn't true of PyThread_create_key(), though (see
178 next paragraph).
179
180 There's a hidden assumption that PyThread_create_key() will be called before
181 any of the other functions are called. There's also a hidden assumption
182 that calls to PyThread_create_key() are serialized externally.
183 ------------------------------------------------------------------------ */
184
185 /* A singly-linked list of struct key objects remembers all the key->value
186 * associations. File static keyhead heads the list. keymutex is used
187 * to enforce exclusion internally.
188 */
153 struct key { 189 struct key {
190 /* Next record in the list, or NULL if this is the last record. */
154 struct key *next; 191 struct key *next;
192
193 /* The thread id, according to PyThread_get_thread_ident(). */
155 long id; 194 long id;
195
196 /* The key and its associated value. */
156 int key; 197 int key;
157 void *value; 198 void *value;
158 }; 199 };
159 200
160 static struct key *keyhead = NULL; 201 static struct key *keyhead = NULL;
161 static int nkeys = 0;
162 static PyThread_type_lock keymutex = NULL; 202 static PyThread_type_lock keymutex = NULL;
163 203 static int nkeys = 0; /* PyThread_create_key() hands out nkeys+1 next */
164 static struct key *find_key(int key, void *value) 204
205 /* Internal helper.
206 * If the current thread has a mapping for key, the appropriate struct key*
207 * is returned. NB: value is ignored in this case!
208 * If there is no mapping for key in the current thread, then:
209 * If value is NULL, NULL is returned.
210 * Else a mapping of key to value is created for the current thread,
211 * and a pointer to a new struct key* is returned; except that if
212 * malloc() can't find room for a new struct key*, NULL is returned.
213 * So when value==NULL, this acts like a pure lookup routine, and when
214 * value!=NULL, this acts like dict.setdefault(), returning an existing
215 * mapping if one exists, else creating a new mapping.
216 *
217 * Caution: this used to be too clever, trying to hold keymutex only
218 * around the "p->next = keyhead; keyhead = p" pair. That allowed
219 * another thread to mutate the list, via key deletion, concurrent with
220 * find_key() crawling over the list. Hilarity ensued. For example, when
221 * the for-loop here does "p = p->next", p could end up pointing at a
222 * record that PyThread_delete_key_value() was concurrently free()'ing.
223 * That could lead to anything, from failing to find a key that exists, to
224 * segfaults. Now we lock the whole routine.
225 */
226 static struct key *
227 find_key(int key, void *value)
165 { 228 {
166 struct key *p; 229 struct key *p;
167 long id = PyThread_get_thread_ident(); 230 long id = PyThread_get_thread_ident();
231
232 PyThread_acquire_lock(keymutex, 1);
168 for (p = keyhead; p != NULL; p = p->next) { 233 for (p = keyhead; p != NULL; p = p->next) {
169 if (p->id == id && p->key == key) 234 if (p->id == id && p->key == key)
170 return p; 235 goto Done;
171 } 236 }
172 if (value == NULL) 237 if (value == NULL) {
173 return NULL; 238 assert(p == NULL);
239 goto Done;
240 }
174 p = (struct key *)malloc(sizeof(struct key)); 241 p = (struct key *)malloc(sizeof(struct key));
175 if (p != NULL) { 242 if (p != NULL) {
176 p->id = id; 243 p->id = id;
177 p->key = key; 244 p->key = key;
178 p->value = value; 245 p->value = value;
179 PyThread_acquire_lock(keymutex, 1);
180 p->next = keyhead; 246 p->next = keyhead;
181 keyhead = p; 247 keyhead = p;
182 PyThread_release_lock(keymutex); 248 }
183 } 249 Done:
250 PyThread_release_lock(keymutex);
184 return p; 251 return p;
185 } 252 }
186 253
187 int PyThread_create_key(void) 254 /* Return a new key. This must be called before any other functions in
188 { 255 * this family, and callers must arrange to serialize calls to this
256 * function. No violations are detected.
257 */
258 int
259 PyThread_create_key(void)
260 {
261 /* All parts of this function are wrong if it's called by multiple
262 * threads simultaneously.
263 */
189 if (keymutex == NULL) 264 if (keymutex == NULL)
190 keymutex = PyThread_allocate_lock(); 265 keymutex = PyThread_allocate_lock();
191 return ++nkeys; 266 return ++nkeys;
192 } 267 }
193 268
194 void PyThread_delete_key(int key) 269 /* Forget the associations for key across *all* threads. */
270 void
271 PyThread_delete_key(int key)
195 { 272 {
196 struct key *p, **q; 273 struct key *p, **q;
274
197 PyThread_acquire_lock(keymutex, 1); 275 PyThread_acquire_lock(keymutex, 1);
198 q = &keyhead; 276 q = &keyhead;
199 while ((p = *q) != NULL) { 277 while ((p = *q) != NULL) {
200 if (p->key == key) { 278 if (p->key == key) {
201 *q = p->next; 279 *q = p->next;
206 q = &p->next; 284 q = &p->next;
207 } 285 }
208 PyThread_release_lock(keymutex); 286 PyThread_release_lock(keymutex);
209 } 287 }
210 288
211 int PyThread_set_key_value(int key, void *value) 289 /* Confusing: If the current thread has an association for key,
212 { 290 * value is ignored, and 0 is returned. Else an attempt is made to create
213 struct key *p = find_key(key, value); 291 * an association of key to value for the current thread. 0 is returned
292 * if that succeeds, but -1 is returned if there's not enough memory
293 * to create the association. value must not be NULL.
294 */
295 int
296 PyThread_set_key_value(int key, void *value)
297 {
298 struct key *p;
299
300 assert(value != NULL);
301 p = find_key(key, value);
214 if (p == NULL) 302 if (p == NULL)
215 return -1; 303 return -1;
216 else 304 else
217 return 0; 305 return 0;
218 } 306 }
219 307
220 void *PyThread_get_key_value(int key) 308 /* Retrieve the value associated with key in the current thread, or NULL
309 * if the current thread doesn't have an association for key.
310 */
311 void *
312 PyThread_get_key_value(int key)
221 { 313 {
222 struct key *p = find_key(key, NULL); 314 struct key *p = find_key(key, NULL);
315
223 if (p == NULL) 316 if (p == NULL)
224 return NULL; 317 return NULL;
225 else 318 else
226 return p->value; 319 return p->value;
227 } 320 }
228 321
229 void PyThread_delete_key_value(int key) 322 /* Forget the current thread's association for key, if any. */
323 void
324 PyThread_delete_key_value(int key)
230 { 325 {
231 long id = PyThread_get_thread_ident(); 326 long id = PyThread_get_thread_ident();
232 struct key *p, **q; 327 struct key *p, **q;
328
233 PyThread_acquire_lock(keymutex, 1); 329 PyThread_acquire_lock(keymutex, 1);
234 q = &keyhead; 330 q = &keyhead;
235 while ((p = *q) != NULL) { 331 while ((p = *q) != NULL) {
236 if (p->key == key && p->id == id) { 332 if (p->key == key && p->id == id) {
237 *q = p->next; 333 *q = p->next;