| 709 | } |
| 710 | |
| 711 | u64 PerfEvents::readCounter(siginfo_t* siginfo, void* ucontext) { |
| 712 | switch (_event_type->counter_arg) { |
| 713 | case 1: return StackFrame(ucontext).arg0(); |
| 714 | case 2: return StackFrame(ucontext).arg1(); |
| 715 | case 3: return StackFrame(ucontext).arg2(); |
| 716 | case 4: return StackFrame(ucontext).arg3(); |
| 717 | default: { |
| 718 | // Read counter with multiplexing metadata for accurate scaling |
| 719 | struct PerfCounter counter; |
| 720 | if (read(siginfo->si_fd, &counter, sizeof(counter)) == sizeof(counter)) { |
| 721 | u64 current_val = counter.value; |
| 722 | if (counter.time_enabled > counter.time_running) { |
| 723 | int fd = siginfo->si_fd; |
| 724 | if (fd < MAX_MULTIPLEXED_FD) { |
| 725 | u64 delta_enabled = counter.time_enabled - multiplex_state[fd].time_enabled; |
| 726 | u64 delta_running = counter.time_running - multiplex_state[fd].time_running; |
| 727 | |
| 728 | multiplex_state[fd].time_enabled = counter.time_enabled; |
| 729 | multiplex_state[fd].time_running = counter.time_running; |
| 730 | |
| 731 | if (!multiplex_state_dirty) { |
| 732 | multiplex_state_dirty = true; |
| 733 | } |
| 734 | |
| 735 | if (delta_running > 0 && delta_enabled > delta_running) { |
| 736 | // scaled counter = (counter) * (delta_enabled / delta_running) |
| 737 | double ratio = (double)delta_enabled / delta_running; |
| 738 | return (u64)(current_val * ratio); |
| 739 | } |
| 740 | } else if (counter.time_running > 0) { |
| 741 | double ratio = (double)counter.time_enabled / counter.time_running; |
| 742 | return (u64)(current_val * ratio); |
| 743 | } |
| 744 | } |
| 745 | return current_val; |
| 746 | } |
| 747 | return 1; |
| 748 | } |
| 749 | } |
| 750 | } |
| 751 | |
| 752 | void PerfEvents::signalHandler(int signo, siginfo_t* siginfo, void* ucontext) { |
| 753 | if (siginfo->si_code <= 0) { |
nothing calls this directly
no test coverage detected