@@ -81,14 +81,14 @@ PyThread_init_thread(void)
81
81
or the size specified by the THREAD_STACK_SIZE macro. */
82
82
static size_t _pythread_stacksize = 0;
83
83
84
-
#ifdef _POSIX_THREADS
85
-
#define PYTHREAD_NAME "pthread"
86
-
#include "thread_pthread.h"
87
-
#endif
88
-
89
-
#ifdef NT_THREADS
90
-
#define PYTHREAD_NAME "nt"
91
-
#include "thread_nt.h"
84
+
#if defined(_POSIX_THREADS)
85
+
# define PYTHREAD_NAME "pthread"
86
+
# include "thread_pthread.h"
87
+
#elif defined(NT_THREADS)
88
+
# define PYTHREAD_NAME "nt"
89
+
# include "thread_nt.h"
90
+
#else
91
+
# error "Require native thread feature. See https://bugs.python.org/issue30832"
92
92
#endif
93
93
94
94
@@ -114,13 +114,7 @@ PyThread_set_stacksize(size_t size)
114
114
#endif
115
115
}
116
116
117
-
#ifndef Py_HAVE_NATIVE_TLS
118
-
/* If the platform has not supplied a platform specific
119
-
TLS implementation, provide our own.
120
117
121
-
This code stolen from "thread_sgi.h", where it was the only
122
-
implementation of an existing Python TLS API.
123
-
*/
124
118
/* ------------------------------------------------------------------------
125
119
Per-thread data ("key") support.
126
120
@@ -157,205 +151,6 @@ any of the other functions are called. There's also a hidden assumption
157
151
that calls to PyThread_create_key() are serialized externally.
158
152
------------------------------------------------------------------------ */
159
153
160
-
/* A singly-linked list of struct key objects remembers all the key->value
161
-
* associations. File static keyhead heads the list. keymutex is used
162
-
* to enforce exclusion internally.
163
-
*/
164
-
struct key {
165
-
/* Next record in the list, or NULL if this is the last record. */
166
-
struct key *next;
167
-
168
-
/* The thread id, according to PyThread_get_thread_ident(). */
169
-
unsigned long id;
170
-
171
-
/* The key and its associated value. */
172
-
int key;
173
-
void *value;
174
-
};
175
-
176
-
static struct key *keyhead = NULL;
177
-
static PyThread_type_lock keymutex = NULL;
178
-
static int nkeys = 0; /* PyThread_create_key() hands out nkeys+1 next */
179
-
180
-
/* Internal helper.
181
-
* If the current thread has a mapping for key, the appropriate struct key*
182
-
* is returned. NB: value is ignored in this case!
183
-
* If there is no mapping for key in the current thread, then:
184
-
* If value is NULL, NULL is returned.
185
-
* Else a mapping of key to value is created for the current thread,
186
-
* and a pointer to a new struct key* is returned; except that if
187
-
* malloc() can't find room for a new struct key*, NULL is returned.
188
-
* So when value==NULL, this acts like a pure lookup routine, and when
189
-
* value!=NULL, this acts like dict.setdefault(), returning an existing
190
-
* mapping if one exists, else creating a new mapping.
191
-
*
192
-
* Caution: this used to be too clever, trying to hold keymutex only
193
-
* around the "p->next = keyhead; keyhead = p" pair. That allowed
194
-
* another thread to mutate the list, via key deletion, concurrent with
195
-
* find_key() crawling over the list. Hilarity ensued. For example, when
196
-
* the for-loop here does "p = p->next", p could end up pointing at a
197
-
* record that PyThread_delete_key_value() was concurrently free()'ing.
198
-
* That could lead to anything, from failing to find a key that exists, to
199
-
* segfaults. Now we lock the whole routine.
200
-
*/
201
-
static struct key *
202
-
find_key(int set_value, int key, void *value)
203
-
{
204
-
struct key *p, *prev_p;
205
-
unsigned long id = PyThread_get_thread_ident();
206
-
207
-
if (!keymutex)
208
-
return NULL;
209
-
PyThread_acquire_lock(keymutex, 1);
210
-
prev_p = NULL;
211
-
for (p = keyhead; p != NULL; p = p->next) {
212
-
if (p->id == id && p->key == key) {
213
-
if (set_value)
214
-
p->value = value;
215
-
goto Done;
216
-
}
217
-
/* Sanity check. These states should never happen but if
218
-
* they do we must abort. Otherwise we'll end up spinning
219
-
* in a tight loop with the lock held. A similar check is done
220
-
* in pystate.c tstate_delete_common(). */
221
-
if (p == prev_p)
222
-
Py_FatalError("tls find_key: small circular list(!)");
223
-
prev_p = p;
224
-
if (p->next == keyhead)
225
-
Py_FatalError("tls find_key: circular list(!)");
226
-
}
227
-
if (!set_value && value == NULL) {
228
-
assert(p == NULL);
229
-
goto Done;
230
-
}
231
-
p = (struct key *)PyMem_RawMalloc(sizeof(struct key));
232
-
if (p != NULL) {
233
-
p->id = id;
234
-
p->key = key;
235
-
p->value = value;
236
-
p->next = keyhead;
237
-
keyhead = p;
238
-
}
239
-
Done:
240
-
PyThread_release_lock(keymutex);
241
-
return p;
242
-
}
243
-
244
-
/* Return a new key. This must be called before any other functions in
245
-
* this family, and callers must arrange to serialize calls to this
246
-
* function. No violations are detected.
247
-
*/
248
-
int
249
-
PyThread_create_key(void)
250
-
{
251
-
/* All parts of this function are wrong if it's called by multiple
252
-
* threads simultaneously.
253
-
*/
254
-
if (keymutex == NULL)
255
-
keymutex = PyThread_allocate_lock();
256
-
return ++nkeys;
257
-
}
258
-
259
-
/* Forget the associations for key across *all* threads. */
260
-
void
261
-
PyThread_delete_key(int key)
262
-
{
263
-
struct key *p, **q;
264
-
265
-
PyThread_acquire_lock(keymutex, 1);
266
-
q = &keyhead;
267
-
while ((p = *q) != NULL) {
268
-
if (p->key == key) {
269
-
*q = p->next;
270
-
PyMem_RawFree((void *)p);
271
-
/* NB This does *not* free p->value! */
272
-
}
273
-
else
274
-
q = &p->next;
275
-
}
276
-
PyThread_release_lock(keymutex);
277
-
}
278
-
279
-
int
280
-
PyThread_set_key_value(int key, void *value)
281
-
{
282
-
struct key *p;
283
-
284
-
p = find_key(1, key, value);
285
-
if (p == NULL)
286
-
return -1;
287
-
else
288
-
return 0;
289
-
}
290
-
291
-
/* Retrieve the value associated with key in the current thread, or NULL
292
-
* if the current thread doesn't have an association for key.
293
-
*/
294
-
void *
295
-
PyThread_get_key_value(int key)
296
-
{
297
-
struct key *p = find_key(0, key, NULL);
298
-
299
-
if (p == NULL)
300
-
return NULL;
301
-
else
302
-
return p->value;
303
-
}
304
-
305
-
/* Forget the current thread's association for key, if any. */
306
-
void
307
-
PyThread_delete_key_value(int key)
308
-
{
309
-
unsigned long id = PyThread_get_thread_ident();
310
-
struct key *p, **q;
311
-
312
-
PyThread_acquire_lock(keymutex, 1);
313
-
q = &keyhead;
314
-
while ((p = *q) != NULL) {
315
-
if (p->key == key && p->id == id) {
316
-
*q = p->next;
317
-
PyMem_RawFree((void *)p);
318
-
/* NB This does *not* free p->value! */
319
-
break;
320
-
}
321
-
else
322
-
q = &p->next;
323
-
}
324
-
PyThread_release_lock(keymutex);
325
-
}
326
-
327
-
/* Forget everything not associated with the current thread id.
328
-
* This function is called from PyOS_AfterFork_Child(). It is necessary
329
-
* because other thread ids which were in use at the time of the fork
330
-
* may be reused for new threads created in the forked process.
331
-
*/
332
-
void
333
-
PyThread_ReInitTLS(void)
334
-
{
335
-
unsigned long id = PyThread_get_thread_ident();
336
-
struct key *p, **q;
337
-
338
-
if (!keymutex)
339
-
return;
340
-
341
-
/* As with interpreter_lock in PyEval_ReInitThreads()
342
-
we just create a new lock without freeing the old one */
343
-
keymutex = PyThread_allocate_lock();
344
-
345
-
/* Delete all keys which do not match the current thread id */
346
-
q = &keyhead;
347
-
while ((p = *q) != NULL) {
348
-
if (p->id != id) {
349
-
*q = p->next;
350
-
PyMem_RawFree((void *)p);
351
-
/* NB This does *not* free p->value! */
352
-
}
353
-
else
354
-
q = &p->next;
355
-
}
356
-
}
357
-
358
-
#endif /* Py_HAVE_NATIVE_TLS */
359
154
360
155
PyDoc_STRVAR(threadinfo__doc__,
361
156
"sys.thread_info\n\
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4