/** * @brief Starts monitoring on selected cores/PIDs * * @param [in] cpu_info cpu information structure * @param [in] cap_mon monitoring capabilities structure * * @return Operation status * @retval 0 OK * @retval -1 error */ static int setup_monitoring(const struct pqos_cpuinfo *cpu_info, const struct pqos_capability * const cap_mon) { unsigned i; const enum pqos_mon_event perf_events = PQOS_PERF_EVENT_IPC | PQOS_PERF_EVENT_LLC_MISS; for (i = 0; (unsigned)i < cap_mon->u.mon->num_events; i++) sel_events_max |= (cap_mon->u.mon->events[i].type); /* Remove perf events IPC and LLC MISSES */ sel_events_max &= ~perf_events; if (sel_monitor_num == 0 && sel_process_num == 0) { for (i = 0; i < cpu_info->num_cores; i++) { unsigned lcore = cpu_info->cores[i].lcore; sel_monitor_core_tab[sel_monitor_num].core = lcore; sel_monitor_core_tab[sel_monitor_num].events = sel_events_max; m_mon_grps[sel_monitor_num] = malloc(sizeof(**m_mon_grps)); sel_monitor_core_tab[sel_monitor_num].pgrp = m_mon_grps[sel_monitor_num]; sel_monitor_num++; } } if (!process_mode()) { for (i = 0; i < (unsigned) sel_monitor_num; i++) { unsigned lcore = sel_monitor_core_tab[i].core; int ret; ret = pqos_mon_start(1, &lcore, sel_events_max, NULL, sel_monitor_core_tab[i].pgrp); if (ret != PQOS_RETVAL_OK) { printf("Monitoring start error on core %u," "status %d\n", lcore, ret); return ret; } } } else { for (i = 0; i < (unsigned) sel_process_num; i++) { pid_t pid = sel_monitor_pid_tab[i].pid; int ret; ret = pqos_mon_start_pid(pid, PQOS_MON_EVENT_L3_OCCUP, NULL, sel_monitor_pid_tab[i].pgrp); if (ret != PQOS_RETVAL_OK) { printf("Monitoring start error on pid %u," "status %d\n", pid, ret); return ret; } } } return PQOS_RETVAL_OK; }
int monitor_setup(const struct pqos_cpuinfo *cpu_info, const struct pqos_capability const *cap_mon) { unsigned i; int ret; enum pqos_mon_event all_core_evts = 0, all_pid_evts = 0; const enum pqos_mon_event evt_all = (enum pqos_mon_event)PQOS_MON_EVENT_ALL; ASSERT(sel_monitor_num >= 0); ASSERT(sel_process_num >= 0); /** * Check output file type */ if (sel_output_type == NULL) sel_output_type = strdup("text"); if (sel_output_type == NULL) { printf("Memory allocation error!\n"); return -1; } if (strcasecmp(sel_output_type, "text") != 0 && strcasecmp(sel_output_type, "xml") != 0 && strcasecmp(sel_output_type, "csv") != 0) { printf("Invalid selection of file output type '%s'!\n", sel_output_type); return -1; } /** * Set up file descriptor for monitored data */ if (sel_output_file == NULL) { fp_monitor = stdout; } else { if (strcasecmp(sel_output_type, "xml") == 0 || strcasecmp(sel_output_type, "csv") == 0) fp_monitor = fopen(sel_output_file, "w+"); else fp_monitor = fopen(sel_output_file, "a"); if (fp_monitor == NULL) { perror("Monitoring output file open error:"); printf("Error opening '%s' output file!\n", sel_output_file); return -1; } if (strcasecmp(sel_output_type, "xml") == 0) fprintf(fp_monitor, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "%s\n", xml_root_open); } /** * get all available events on this platform */ for (i = 0; i < cap_mon->u.mon->num_events; i++) { struct pqos_monitor *mon = &cap_mon->u.mon->events[i]; all_core_evts |= mon->type; if (mon->pid_support) all_pid_evts |= mon->type; } /** * If no cores and events selected through command line * by default let's monitor all cores */ if (sel_monitor_num == 0 && sel_process_num == 0) { sel_events_max = all_core_evts; for (i = 0; i < cpu_info->num_cores; i++) { unsigned lcore = cpu_info->cores[i].lcore; uint64_t core = (uint64_t)lcore; struct core_group *pg = &sel_monitor_core_tab[sel_monitor_num]; if ((unsigned) sel_monitor_num >= DIM(sel_monitor_core_tab)) break; ret = set_cgrp(pg, uinttostr(lcore), &core, 1); if (ret != 0) { printf("Core group setup error!\n"); exit(EXIT_FAILURE); } pg->events = sel_events_max; pg->pgrp = malloc(sizeof(*pg->pgrp)); if (pg->pgrp == NULL) { printf("Error with memory allocation!\n"); exit(EXIT_FAILURE); } sel_monitor_num++; } } if (sel_process_num > 0 && sel_monitor_num > 0) { printf("Monitoring start error, process and core" " tracking can not be done simultaneously\n"); return -1; } if (!process_mode()) { /** * Make calls to pqos_mon_start - track cores */ for (i = 0; i < (unsigned)sel_monitor_num; i++) { struct core_group *cg = &sel_monitor_core_tab[i]; /* check if all available events were selected */ if (cg->events == evt_all) { cg->events = all_core_evts; sel_events_max |= all_core_evts; } else { if (all_core_evts & PQOS_PERF_EVENT_IPC) cg->events |= PQOS_PERF_EVENT_IPC; if (all_core_evts & PQOS_PERF_EVENT_LLC_MISS) cg->events |= PQOS_PERF_EVENT_LLC_MISS; } ret = pqos_mon_start(cg->num_cores, cg->cores, cg->events, (void *)cg->desc, cg->pgrp); ASSERT(ret == PQOS_RETVAL_OK); /** * The error raised also if two instances of PQoS * attempt to use the same core id. */ if (ret != PQOS_RETVAL_OK) { if (ret == PQOS_RETVAL_PERF_CTR) printf("Use -r option to start " "monitoring anyway.\n"); printf("Monitoring start error on core(s) " "%s, status %d\n", cg->desc, ret); return -1; } } } else { /** * Make calls to pqos_mon_start_pid - track PIDs */ for (i = 0; i < (unsigned)sel_process_num; i++) { struct pid_group *pg = &sel_monitor_pid_tab[i]; /* check if all available events were selected */ if (pg->events == evt_all) { pg->events = all_pid_evts; sel_events_max |= all_pid_evts; } else { if (all_pid_evts & PQOS_PERF_EVENT_IPC) pg->events |= PQOS_PERF_EVENT_IPC; if (all_pid_evts & PQOS_PERF_EVENT_LLC_MISS) pg->events |= PQOS_PERF_EVENT_LLC_MISS; } ret = pqos_mon_start_pid(sel_monitor_pid_tab[i].pid, sel_monitor_pid_tab[i].events, NULL, sel_monitor_pid_tab[i].pgrp); ASSERT(ret == PQOS_RETVAL_OK); /** * Any problem with monitoring the process? */ if (ret != PQOS_RETVAL_OK) { printf("PID %d monitoring start error," "status %d\n", sel_monitor_pid_tab[i].pid, ret); return -1; } } } return 0; }