bpo-33608: Minor cleanup related to pending calls. (gh-12247) · python/cpython@5be45a6 (original) (raw)
`@@ -174,9 +174,11 @@ PyEval_InitThreads(void)
`
174
174
`PyThread_init_thread();
`
175
175
`create_gil();
`
176
176
`take_gil(_PyThreadState_GET());
`
177
``
`-
_PyRuntime.ceval.pending.main_thread = PyThread_get_thread_ident();
`
178
``
`-
if (!_PyRuntime.ceval.pending.lock)
`
``
177
`+
// Set it to the ID of the main thread of the main interpreter.
`
``
178
`+
_PyRuntime.main_thread = PyThread_get_thread_ident();
`
``
179
`+
if (!_PyRuntime.ceval.pending.lock) {
`
179
180
`_PyRuntime.ceval.pending.lock = PyThread_allocate_lock();
`
``
181
`+
}
`
180
182
`}
`
181
183
``
182
184
`void
`
`@@ -243,9 +245,9 @@ PyEval_ReInitThreads(void)
`
243
245
`if (!gil_created())
`
244
246
`return;
`
245
247
`recreate_gil();
`
246
``
`-
_PyRuntime.ceval.pending.lock = PyThread_allocate_lock();
`
247
248
`take_gil(current_tstate);
`
248
``
`-
_PyRuntime.ceval.pending.main_thread = PyThread_get_thread_ident();
`
``
249
`+
_PyRuntime.main_thread = PyThread_get_thread_ident();
`
``
250
`+
_PyRuntime.ceval.pending.lock = PyThread_allocate_lock();
`
249
251
``
250
252
`/* Destroy all threads except the current one */
`
251
253
`_PyThreadState_DeleteExcept(current_tstate);
`
`@@ -323,6 +325,35 @@ _PyEval_SignalReceived(void)
`
323
325
`SIGNAL_PENDING_SIGNALS();
`
324
326
`}
`
325
327
``
``
328
`+
/* Push one item onto the queue while holding the lock. */
`
``
329
`+
static int
`
``
330
`+
_push_pending_call(int (*func)(void *), void *arg)
`
``
331
`+
{
`
``
332
`+
int i = _PyRuntime.ceval.pending.last;
`
``
333
`+
int j = (i + 1) % NPENDINGCALLS;
`
``
334
`+
if (j == _PyRuntime.ceval.pending.first) {
`
``
335
`+
return -1; /* Queue full */
`
``
336
`+
}
`
``
337
`+
_PyRuntime.ceval.pending.calls[i].func = func;
`
``
338
`+
_PyRuntime.ceval.pending.calls[i].arg = arg;
`
``
339
`+
_PyRuntime.ceval.pending.last = j;
`
``
340
`+
return 0;
`
``
341
`+
}
`
``
342
+
``
343
`+
/* Pop one item off the queue while holding the lock. */
`
``
344
`+
static void
`
``
345
`+
_pop_pending_call(int (**func)(void *), void **arg)
`
``
346
`+
{
`
``
347
`+
int i = _PyRuntime.ceval.pending.first;
`
``
348
`+
if (i == _PyRuntime.ceval.pending.last) {
`
``
349
`+
return; /* Queue empty */
`
``
350
`+
}
`
``
351
+
``
352
`+
*func = _PyRuntime.ceval.pending.calls[i].func;
`
``
353
`+
*arg = _PyRuntime.ceval.pending.calls[i].arg;
`
``
354
`+
_PyRuntime.ceval.pending.first = (i + 1) % NPENDINGCALLS;
`
``
355
`+
}
`
``
356
+
326
357
`/* This implementation is thread-safe. It allows
`
327
358
` scheduling to be made from any thread, and even from an executing
`
328
359
` callback.
`
`@@ -331,7 +362,6 @@ _PyEval_SignalReceived(void)
`
331
362
`int
`
332
363
`Py_AddPendingCall(int (*func)(void *), void *arg)
`
333
364
`{
`
334
``
`-
int i, j, result=0;
`
335
365
`PyThread_type_lock lock = _PyRuntime.ceval.pending.lock;
`
336
366
``
337
367
`/* try a few times for the lock. Since this mechanism is used
`
`@@ -346,6 +376,7 @@ Py_AddPendingCall(int (*func)(void *), void *arg)
`
346
376
` * this function is called before any bytecode evaluation takes place.
`
347
377
` */
`
348
378
`if (lock != NULL) {
`
``
379
`+
int i;
`
349
380
`for (i = 0; i<100; i++) {
`
350
381
`if (PyThread_acquire_lock(lock, NOWAIT_LOCK))
`
351
382
`break;
`
`@@ -354,15 +385,8 @@ Py_AddPendingCall(int (*func)(void *), void *arg)
`
354
385
`return -1;
`
355
386
` }
`
356
387
``
357
``
`-
i = _PyRuntime.ceval.pending.last;
`
358
``
`-
j = (i + 1) % NPENDINGCALLS;
`
359
``
`-
if (j == _PyRuntime.ceval.pending.first) {
`
360
``
`-
result = -1; /* Queue full */
`
361
``
`-
} else {
`
362
``
`-
_PyRuntime.ceval.pending.calls[i].func = func;
`
363
``
`-
_PyRuntime.ceval.pending.calls[i].arg = arg;
`
364
``
`-
_PyRuntime.ceval.pending.last = j;
`
365
``
`-
}
`
``
388
`+
int result = _push_pending_call(func, arg);
`
``
389
+
366
390
`/* signal main loop */
`
367
391
`SIGNAL_PENDING_CALLS();
`
368
392
`if (lock != NULL)
`
`@@ -373,10 +397,10 @@ Py_AddPendingCall(int (*func)(void *), void *arg)
`
373
397
`static int
`
374
398
`handle_signals(void)
`
375
399
`{
`
376
``
`-
/* Only handle signals on main thread. */
`
377
``
`-
if (_PyRuntime.ceval.pending.main_thread &&
`
378
``
`-
PyThread_get_thread_ident() != _PyRuntime.ceval.pending.main_thread)
`
379
``
`-
{
`
``
400
`+
/* Only handle signals on main thread. PyEval_InitThreads must
`
``
401
`+
- have been called already.
`
``
402
`+
*/
`
``
403
`+
if (PyThread_get_thread_ident() != _PyRuntime.main_thread) {
`
380
404
`return 0;
`
381
405
` }
`
382
406
`/*
`
`@@ -401,9 +425,7 @@ make_pending_calls(void)
`
401
425
`static int busy = 0;
`
402
426
``
403
427
`/* only service pending calls on main thread */
`
404
``
`-
if (_PyRuntime.ceval.pending.main_thread &&
`
405
``
`-
PyThread_get_thread_ident() != _PyRuntime.ceval.pending.main_thread)
`
406
``
`-
{
`
``
428
`+
if (PyThread_get_thread_ident() != _PyRuntime.main_thread) {
`
407
429
`return 0;
`
408
430
` }
`
409
431
``
`@@ -428,24 +450,18 @@ make_pending_calls(void)
`
428
450
``
429
451
`/* perform a bounded number of calls, in case of recursion */
`
430
452
`for (int i=0; i<NPENDINGCALLS; i++) {
`
431
``
`-
int j;
`
432
``
`-
int (*func)(void *);
`
``
453
`+
int (*func)(void *) = NULL;
`
433
454
`void *arg = NULL;
`
434
455
``
435
456
`/* pop one item off the queue while holding the lock */
`
436
457
`PyThread_acquire_lock(_PyRuntime.ceval.pending.lock, WAIT_LOCK);
`
437
``
`-
j = _PyRuntime.ceval.pending.first;
`
438
``
`-
if (j == _PyRuntime.ceval.pending.last) {
`
439
``
`-
func = NULL; /* Queue empty */
`
440
``
`-
} else {
`
441
``
`-
func = _PyRuntime.ceval.pending.calls[j].func;
`
442
``
`-
arg = _PyRuntime.ceval.pending.calls[j].arg;
`
443
``
`-
_PyRuntime.ceval.pending.first = (j + 1) % NPENDINGCALLS;
`
444
``
`-
}
`
``
458
`+
_pop_pending_call(&func, &arg);
`
445
459
`PyThread_release_lock(_PyRuntime.ceval.pending.lock);
`
``
460
+
446
461
`/* having released the lock, perform the callback */
`
447
``
`-
if (func == NULL)
`
``
462
`+
if (func == NULL) {
`
448
463
`break;
`
``
464
`+
}
`
449
465
`res = func(arg);
`
450
466
`if (res) {
`
451
467
` goto error;
`