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

`+

`

``

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;

`