intel / pcm

Intel® Performance Counter Monitor (Intel® PCM)
BSD 3-Clause "New" or "Revised" License
2.83k stars 477 forks source link

PCM::checkError() without side effects #799

Closed artiomn closed 3 months ago

artiomn commented 4 months ago

Now this function has side effects (program exiting, console reading and writing):

void PCM::checkError(const PCM::ErrorCode code)
{
    switch (code)
    {
    case PCM::Success:
        break;
    case PCM::MSRAccessDenied:
        std::cerr << "Access to Intel(r) Performance Counter Monitor has denied (no MSR or PCI CFG space access).\n";
        exit(EXIT_FAILURE);
    case PCM::PMUBusy:
        std::cerr << "Access to Intel(r) Performance Counter Monitor has denied (Performance Monitoring Unit is occupied by other application)\n";
        std::cerr << "Try to stop the application that uses PMU, or reset PMU configuration from PCM application itself\n";
        std::cerr << "You can try to reset PMU configuration now. Try to reset? (y/n)\n";
        char yn;
        std::cin >> yn;
        if ('y' == yn)
        {
            resetPMU();
            std::cerr << "PMU configuration has been reset. Try to rerun the program again.\n";
        }
        exit(EXIT_FAILURE);
    default:
        std::cerr << "Access to Intel(r) Performance Counter Monitor has denied (Unknown error).\n";
        exit(EXIT_FAILURE);
    }
}

But it's not very convenient when PCM is used as a library in the applications, other than built-in utilities. Probably creating another function, which will be generate exceptions and use it in the checkError() will be convenient?

I.e.:

void check_pcm_status(const pcm::PCM::ErrorCode& status)
{
    switch (status)
    {
        case pcm::PCM::Success:
        {
            // Some logging?
            // SPDLOG_TRACE("PCM instance programming is ok");
            break;
        }
        case pcm::PCM::MSRAccessDenied:
            throw system_error(pcm::PCM::MSRAccessDenied, std::generic_category(),
                "Access to Intel(r) Performance Counter Monitor has denied (no MSR or PCI CFG space access).");
        case pcm::PCM::PMUBusy:
            throw system_error(pcm::PCM::PMUBusy, std::generic_category(),
                "Access to Intel(r) Performance Counter Monitor has denied (Performance Monitoring Unit"
                " is occupied by other application). Try to stop the application that uses PMU,"
                " or reset PMU configuration from PCM application itself");
        default:
            throw system_error(pcm::PCM::UnknownError, std::generic_category(),
                "Access to Intel(r) Performance Counter Monitor has denied (Unknown error).");
    }
}

...

void PCM::checkError(const PCM::ErrorCode code)
{
    try
    {
        check_pcm_status(code);
    }
    catch (const std::system_error &e)
    {
        switch (e.code())
        {
           case PCM::PMUBusy:
               std::cerr << e.what() << "\n"
                               << "You can try to reset PMU configuration now. Try to reset? (y/n)" << std::endl;
               char yn;
               std::cin >> yn;
               if ('y' == yn)
               {
                   resetPMU();
                   std::cerr << "PMU configuration has been reset. Try to rerun the program again." << std::endl;
               }
               exit(EXIT_FAILURE);
           case PCM::MSRAccessDenied:
           default:
               std::cerr << e.what() << std::endl;
               exit(EXIT_FAILURE);
        }
    }
}
rdementi commented 3 months ago

that is great! Would you like to submit a PR?

artiomn commented 3 months ago

Finished: https://github.com/intel/pcm/pull/814/files