… | |
… | |
1139 | } |
1139 | } |
1140 | } |
1140 | } |
1141 | |
1141 | |
1142 | /* always use the TRANSFER macro */ |
1142 | /* always use the TRANSFER macro */ |
1143 | static void NOINLINE |
1143 | static void NOINLINE |
1144 | transfer (pTHX_ struct coro *prev, struct coro *next) |
1144 | transfer (pTHX_ struct coro *prev, struct coro *next, int force_cctx) |
1145 | { |
1145 | { |
1146 | dSTACKLEVEL; |
1146 | dSTACKLEVEL; |
1147 | static volatile int has_throw; |
1147 | static volatile int has_throw; |
1148 | |
1148 | |
1149 | /* sometimes transfer is only called to set idle_sp */ |
1149 | /* sometimes transfer is only called to set idle_sp */ |
… | |
… | |
1183 | load_perl (aTHX_ next); |
1183 | load_perl (aTHX_ next); |
1184 | |
1184 | |
1185 | prev__cctx = prev->cctx; |
1185 | prev__cctx = prev->cctx; |
1186 | |
1186 | |
1187 | /* possibly "free" the cctx */ |
1187 | /* possibly "free" the cctx */ |
1188 | if (expect_true (prev__cctx->idle_sp == STACKLEVEL && !(prev__cctx->flags & CC_TRACE))) |
1188 | if (expect_true ( |
|
|
1189 | prev__cctx->idle_sp == STACKLEVEL |
|
|
1190 | && !(prev__cctx->flags & CC_TRACE) |
|
|
1191 | && !force_cctx |
|
|
1192 | )) |
1189 | { |
1193 | { |
1190 | /* I assume that STACKLEVEL is a stronger indicator than PL_top_env changes */ |
1194 | /* I assume that STACKLEVEL is a stronger indicator than PL_top_env changes */ |
1191 | assert (("ERROR: current top_env must equal previous top_env", PL_top_env == prev__cctx->idle_te)); |
1195 | assert (("ERROR: current top_env must equal previous top_env", PL_top_env == prev__cctx->idle_te)); |
1192 | |
1196 | |
1193 | prev->cctx = 0; |
1197 | prev->cctx = 0; |
… | |
… | |
1236 | struct transfer_args |
1240 | struct transfer_args |
1237 | { |
1241 | { |
1238 | struct coro *prev, *next; |
1242 | struct coro *prev, *next; |
1239 | }; |
1243 | }; |
1240 | |
1244 | |
1241 | #define TRANSFER(ta) transfer (aTHX_ (ta).prev, (ta).next) |
1245 | #define TRANSFER(ta, force_cctx) transfer (aTHX_ (ta).prev, (ta).next, (force_cctx)) |
1242 | #define TRANSFER_CHECK(ta) transfer_check (aTHX_ (ta).prev, (ta).next) |
1246 | #define TRANSFER_CHECK(ta) transfer_check (aTHX_ (ta).prev, (ta).next) |
1243 | |
1247 | |
1244 | /** high level stuff ********************************************************/ |
1248 | /** high level stuff ********************************************************/ |
1245 | |
1249 | |
1246 | static int |
1250 | static int |
… | |
… | |
1340 | { |
1344 | { |
1341 | dTHX; |
1345 | dTHX; |
1342 | struct transfer_args ta; |
1346 | struct transfer_args ta; |
1343 | |
1347 | |
1344 | prepare_transfer (aTHX_ &ta, prev_sv, next_sv); |
1348 | prepare_transfer (aTHX_ &ta, prev_sv, next_sv); |
1345 | TRANSFER (ta); |
1349 | TRANSFER (ta, 1); |
1346 | } |
1350 | } |
1347 | |
1351 | |
1348 | /** Coro ********************************************************************/ |
1352 | /** Coro ********************************************************************/ |
1349 | |
1353 | |
1350 | static void |
1354 | static void |
… | |
… | |
1481 | { |
1485 | { |
1482 | dTHX; |
1486 | dTHX; |
1483 | struct transfer_args ta; |
1487 | struct transfer_args ta; |
1484 | |
1488 | |
1485 | prepare_schedule (aTHX_ &ta); |
1489 | prepare_schedule (aTHX_ &ta); |
1486 | TRANSFER (ta); |
1490 | TRANSFER (ta, 1); |
1487 | } |
1491 | } |
1488 | |
1492 | |
1489 | static int |
1493 | static int |
1490 | api_cede (void) |
1494 | api_cede (void) |
1491 | { |
1495 | { |
… | |
… | |
1494 | |
1498 | |
1495 | prepare_cede (aTHX_ &ta); |
1499 | prepare_cede (aTHX_ &ta); |
1496 | |
1500 | |
1497 | if (expect_true (ta.prev != ta.next)) |
1501 | if (expect_true (ta.prev != ta.next)) |
1498 | { |
1502 | { |
1499 | TRANSFER (ta); |
1503 | TRANSFER (ta, 1); |
1500 | return 1; |
1504 | return 1; |
1501 | } |
1505 | } |
1502 | else |
1506 | else |
1503 | return 0; |
1507 | return 0; |
1504 | } |
1508 | } |
… | |
… | |
1509 | dTHX; |
1513 | dTHX; |
1510 | struct transfer_args ta; |
1514 | struct transfer_args ta; |
1511 | |
1515 | |
1512 | if (prepare_cede_notself (aTHX_ &ta)) |
1516 | if (prepare_cede_notself (aTHX_ &ta)) |
1513 | { |
1517 | { |
1514 | TRANSFER (ta); |
1518 | TRANSFER (ta, 1); |
1515 | return 1; |
1519 | return 1; |
1516 | } |
1520 | } |
1517 | else |
1521 | else |
1518 | return 0; |
1522 | return 0; |
1519 | } |
1523 | } |
… | |
… | |
1661 | } |
1665 | } |
1662 | SPAGAIN; |
1666 | SPAGAIN; |
1663 | |
1667 | |
1664 | BARRIER; |
1668 | BARRIER; |
1665 | PUTBACK; |
1669 | PUTBACK; |
1666 | TRANSFER (ta); |
1670 | TRANSFER (ta, 0); |
1667 | SPAGAIN; /* might be the sp of a different coroutine now */ |
1671 | SPAGAIN; /* might be the sp of a different coroutine now */ |
1668 | /* be extra careful not to ever do anything after TRANSFER */ |
1672 | /* be extra careful not to ever do anything after TRANSFER */ |
1669 | } |
1673 | } |
1670 | |
1674 | |
1671 | bool |
1675 | bool |