Mercurial > cpython-lru_cache-weakref
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; |
