Blame lib/os_monitoring.c

Packit Service 5befb9
/*
Packit Service 5befb9
 * BSD LICENSE
Packit Service 5befb9
 *
Packit Service 8a4b7a
 * Copyright(c) 2017-2020 Intel Corporation. All rights reserved.
Packit Service 5befb9
 * All rights reserved.
Packit Service 5befb9
 *
Packit Service 5befb9
 * Redistribution and use in source and binary forms, with or without
Packit Service 5befb9
 * modification, are permitted provided that the following conditions
Packit Service 5befb9
 * are met:
Packit Service 5befb9
 *
Packit Service 5befb9
 *   * Redistributions of source code must retain the above copyright
Packit Service 5befb9
 *     notice, this list of conditions and the following disclaimer.
Packit Service 5befb9
 *   * Redistributions in binary form must reproduce the above copyright
Packit Service 5befb9
 *     notice, this list of conditions and the following disclaimer in
Packit Service 5befb9
 *     the documentation and/or other materials provided with the
Packit Service 5befb9
 *     distribution.
Packit Service 5befb9
 *   * Neither the name of Intel Corporation nor the names of its
Packit Service 5befb9
 *     contributors may be used to endorse or promote products derived
Packit Service 5befb9
 *     from this software without specific prior written permission.
Packit Service 5befb9
 *
Packit Service 5befb9
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit Service 5befb9
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit Service 5befb9
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit Service 5befb9
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit Service 5befb9
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit Service 5befb9
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit Service 5befb9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit Service 5befb9
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit Service 5befb9
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit Service 5befb9
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit Service 5befb9
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit Service 5befb9
 *
Packit Service 5befb9
 */
Packit Service 5befb9
Packit Service 5befb9
#include <stdlib.h>
Packit Service 5befb9
#include <string.h>
Packit Service 8a4b7a
#include <unistd.h> /**< pid_t */
Packit Service 8a4b7a
#include <dirent.h> /**< scandir() */
Packit Service 5befb9
Packit Service 5befb9
#include "pqos.h"
Packit Service 5befb9
#include "cap.h"
Packit Service 5befb9
#include "log.h"
Packit Service 5befb9
#include "types.h"
Packit Service 8a4b7a
#include "monitoring.h"
Packit Service 5befb9
#include "os_monitoring.h"
Packit Service 5befb9
#include "perf_monitoring.h"
Packit Service 5befb9
#include "resctrl.h"
Packit Service 5befb9
#include "resctrl_monitoring.h"
Packit Service 5befb9
Packit Service 5befb9
/**
Packit Service 5befb9
 * ---------------------------------------
Packit Service 5befb9
 * Local data structures
Packit Service 5befb9
 * ---------------------------------------
Packit Service 5befb9
 */
Packit Service 5befb9
static const struct pqos_cpuinfo *m_cpu = NULL;
Packit Service 5befb9
Packit Service 5befb9
/** List of non virtual events */
Packit Service 5befb9
const enum pqos_mon_event os_mon_event[] = {
Packit Service 8a4b7a
    PQOS_MON_EVENT_L3_OCCUP,
Packit Service 8a4b7a
    PQOS_MON_EVENT_LMEM_BW,
Packit Service 8a4b7a
    PQOS_MON_EVENT_TMEM_BW,
Packit Service 8a4b7a
    PQOS_PERF_EVENT_LLC_MISS,
Packit Service 8a4b7a
    (enum pqos_mon_event)PQOS_PERF_EVENT_CYCLES,
Packit Service 8a4b7a
    (enum pqos_mon_event)PQOS_PERF_EVENT_INSTRUCTIONS};
Packit Service 5befb9
Packit Service 5befb9
/**
Packit Service 5befb9
 * @brief Filter directory filenames
Packit Service 5befb9
 *
Packit Service 5befb9
 * This function is used by the scandir function
Packit Service 5befb9
 * to filter hidden (dot) files
Packit Service 5befb9
 *
Packit Service 5befb9
 * @param dir dirent structure containing directory info
Packit Service 5befb9
 *
Packit Service 5befb9
 * @return if directory entry should be included in scandir() output list
Packit Service 5befb9
 * @retval 0 means don't include the entry  ("." in our case)
Packit Service 5befb9
 * @retval 1 means include the entry
Packit Service 5befb9
 */
Packit Service 5befb9
static int
Packit Service 5befb9
filter(const struct dirent *dir)
Packit Service 5befb9
{
Packit Service 8a4b7a
        return (dir->d_name[0] == '.') ? 0 : 1;
Packit Service 5befb9
}
Packit Service 5befb9
Packit Service 5befb9
/**
Packit Service 5befb9
 * @brief This function stops started events
Packit Service 5befb9
 *
Packit Service 5befb9
 * @param group monitoring structure
Packit Service 5befb9
 *
Packit Service 5befb9
 * @return Operation status
Packit Service 5befb9
 * @retval PQOS_RETVAL_OK on success
Packit Service 5befb9
 * @retval PQOS_RETVAL_ERROR on error
Packit Service 5befb9
 */
Packit Service 5befb9
static int
Packit Service 5befb9
stop_events(struct pqos_mon_data *group)
Packit Service 5befb9
{
Packit Service 5befb9
        int ret;
Packit Service 5befb9
        enum pqos_mon_event stopped_evts = (enum pqos_mon_event)0;
Packit Service 5befb9
        unsigned i;
Packit Service 5befb9
Packit Service 5befb9
        ASSERT(group != NULL);
Packit Service 5befb9
Packit Service 5befb9
        for (i = 0; i < DIM(os_mon_event); i++) {
Packit Service 5befb9
                enum pqos_mon_event evt = os_mon_event[i];
Packit Service 5befb9
Packit Service 5befb9
                /**
Packit Service 5befb9
                 * Stop perf event
Packit Service 5befb9
                 */
Packit Service 8a4b7a
                if (group->intl->perf.event & evt) {
Packit Service 5befb9
                        ret = perf_mon_stop(group, evt);
Packit Service 5befb9
                        if (ret == PQOS_RETVAL_OK)
Packit Service 5befb9
                                stopped_evts |= evt;
Packit Service 5befb9
                }
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 8a4b7a
        if (group->intl->resctrl.event) {
Packit Service 5befb9
                ret = resctrl_lock_exclusive();
Packit Service 5befb9
                if (ret != PQOS_RETVAL_OK)
Packit Service 5befb9
                        goto stop_event_error;
Packit Service 5befb9
Packit Service 5befb9
                ret = resctrl_mon_stop(group);
Packit Service 5befb9
                if (ret == PQOS_RETVAL_OK)
Packit Service 8a4b7a
                        stopped_evts |= group->intl->resctrl.event;
Packit Service 5befb9
Packit Service 5befb9
                resctrl_lock_release();
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 8a4b7a
stop_event_error:
Packit Service 5befb9
        if ((stopped_evts & PQOS_MON_EVENT_LMEM_BW) &&
Packit Service 8a4b7a
            (stopped_evts & PQOS_MON_EVENT_TMEM_BW))
Packit Service 5befb9
                stopped_evts |= (enum pqos_mon_event)PQOS_MON_EVENT_RMEM_BW;
Packit Service 5befb9
Packit Service 5befb9
        if ((stopped_evts & PQOS_PERF_EVENT_CYCLES) &&
Packit Service 8a4b7a
            (stopped_evts & PQOS_PERF_EVENT_INSTRUCTIONS))
Packit Service 5befb9
                stopped_evts |= (enum pqos_mon_event)PQOS_PERF_EVENT_IPC;
Packit Service 5befb9
Packit Service 8a4b7a
        if (group->intl->perf.ctx != NULL) {
Packit Service 8a4b7a
                free(group->intl->perf.ctx);
Packit Service 8a4b7a
                group->intl->perf.ctx = NULL;
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 8a4b7a
        if ((group->intl->perf.event & stopped_evts) !=
Packit Service 8a4b7a
            group->intl->perf.event) {
Packit Service 5befb9
                LOG_ERROR("Failed to stop all perf events\n");
Packit Service 5befb9
                return PQOS_RETVAL_ERROR;
Packit Service 5befb9
        }
Packit Service 8a4b7a
        group->intl->perf.event = (enum pqos_mon_event)0;
Packit Service 5befb9
Packit Service 8a4b7a
        if ((group->intl->resctrl.event & stopped_evts) !=
Packit Service 8a4b7a
            group->intl->resctrl.event) {
Packit Service 5befb9
                LOG_ERROR("Failed to stop resctrl events\n");
Packit Service 5befb9
                return PQOS_RETVAL_ERROR;
Packit Service 5befb9
        }
Packit Service 8a4b7a
        group->intl->resctrl.event = (enum pqos_mon_event)0;
Packit Service 5befb9
Packit Service 5befb9
        return PQOS_RETVAL_OK;
Packit Service 5befb9
}
Packit Service 5befb9
Packit Service 5befb9
/**
Packit Service 5befb9
 * @brief This function starts selected events
Packit Service 5befb9
 *
Packit Service 5befb9
 * @param group monitoring structure
Packit Service 5befb9
 *
Packit Service 5befb9
 * @return Operation status
Packit Service 5befb9
 * @retval PQOS_RETVAL_OK on success
Packit Service 5befb9
 * @retval PQOS_RETVAL_ERROR on error
Packit Service 5befb9
 */
Packit Service 5befb9
static int
Packit Service 5befb9
start_events(struct pqos_mon_data *group)
Packit Service 5befb9
{
Packit Service 5befb9
        int ret = PQOS_RETVAL_OK;
Packit Service 5befb9
        unsigned num_ctrs, i;
Packit Service 5befb9
        enum pqos_mon_event events;
Packit Service 5befb9
        enum pqos_mon_event started_evts = (enum pqos_mon_event)0;
Packit Service 5befb9
Packit Service 5befb9
        ASSERT(group != NULL);
Packit Service 5befb9
Packit Service 5befb9
        if (group->num_cores > 0)
Packit Service 5befb9
                num_ctrs = group->num_cores;
Packit Service 5befb9
        else if (group->tid_nr > 0)
Packit Service 5befb9
                num_ctrs = group->tid_nr;
Packit Service 5befb9
        else
Packit Service 5befb9
                return PQOS_RETVAL_ERROR;
Packit Service 5befb9
Packit Service 5befb9
        events = group->event;
Packit Service 8a4b7a
        group->intl->perf.event = (enum pqos_mon_event)0;
Packit Service 8a4b7a
        group->intl->perf.ctx =
Packit Service 8a4b7a
            malloc(sizeof(group->intl->perf.ctx[0]) * num_ctrs);
Packit Service 8a4b7a
        if (group->intl->perf.ctx == NULL) {
Packit Service 5befb9
                LOG_ERROR("Memory allocation failed\n");
Packit Service 5befb9
                return PQOS_RETVAL_ERROR;
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 5befb9
        if (events & PQOS_MON_EVENT_RMEM_BW)
Packit Service 5befb9
                events |= (enum pqos_mon_event)(PQOS_MON_EVENT_LMEM_BW |
Packit Service 8a4b7a
                                                PQOS_MON_EVENT_TMEM_BW);
Packit Service 5befb9
        if (events & PQOS_PERF_EVENT_IPC)
Packit Service 5befb9
                events |= (enum pqos_mon_event)(PQOS_PERF_EVENT_CYCLES |
Packit Service 8a4b7a
                                                PQOS_PERF_EVENT_INSTRUCTIONS);
Packit Service 5befb9
Packit Service 5befb9
        /**
Packit Service 5befb9
         * Determine selected events and Perf counters
Packit Service 5befb9
         */
Packit Service 5befb9
        for (i = 0; i < DIM(os_mon_event); i++) {
Packit Service 5befb9
                enum pqos_mon_event evt = os_mon_event[i];
Packit Service 5befb9
Packit Service 5befb9
                if (events & evt) {
Packit Service 5befb9
                        if (perf_mon_is_event_supported(evt)) {
Packit Service 5befb9
                                ret = perf_mon_start(group, evt);
Packit Service 5befb9
                                if (ret != PQOS_RETVAL_OK)
Packit Service 5befb9
                                        goto start_event_error;
Packit Service 8a4b7a
                                group->intl->perf.event |= evt;
Packit Service 5befb9
                                continue;
Packit Service 5befb9
                        }
Packit Service 5befb9
Packit Service 5befb9
                        if (resctrl_mon_is_event_supported(evt)) {
Packit Service 8a4b7a
                                group->intl->resctrl.event |= evt;
Packit Service 5befb9
                                continue;
Packit Service 5befb9
                        }
Packit Service 5befb9
Packit Service 5befb9
                        /**
Packit Service 5befb9
                         * Event is not supported
Packit Service 5befb9
                         */
Packit Service 5befb9
                        ret = PQOS_RETVAL_ERROR;
Packit Service 5befb9
                        goto start_event_error;
Packit Service 5befb9
                }
Packit Service 5befb9
        }
Packit Service 8a4b7a
        started_evts |= group->intl->perf.event;
Packit Service 5befb9
Packit Service 8a4b7a
        if (group->intl->resctrl.event != 0) {
Packit Service 5befb9
                ret = resctrl_lock_exclusive();
Packit Service 5befb9
                if (ret != PQOS_RETVAL_OK)
Packit Service 5befb9
                        goto start_event_error;
Packit Service 5befb9
Packit Service 5befb9
                ret = resctrl_mon_start(group);
Packit Service 5befb9
                resctrl_lock_release();
Packit Service 5befb9
                if (ret != PQOS_RETVAL_OK)
Packit Service 5befb9
                        goto start_event_error;
Packit Service 5befb9
        }
Packit Service 8a4b7a
        started_evts |= group->intl->resctrl.event;
Packit Service 5befb9
Packit Service 5befb9
        /**
Packit Service 5befb9
         * All events required by RMEM has been started
Packit Service 5befb9
         */
Packit Service 5befb9
        if ((started_evts & PQOS_MON_EVENT_LMEM_BW) &&
Packit Service 8a4b7a
            (started_evts & PQOS_MON_EVENT_TMEM_BW)) {
Packit Service 5befb9
                group->values.mbm_remote = 0;
Packit Service 5befb9
                started_evts |= (enum pqos_mon_event)PQOS_MON_EVENT_RMEM_BW;
Packit Service 5befb9
        }
Packit Service 5befb9
        /**
Packit Service 5befb9
         * All events required by IPC has been started
Packit Service 5befb9
         */
Packit Service 5befb9
        if ((started_evts & PQOS_PERF_EVENT_CYCLES) &&
Packit Service 8a4b7a
            (started_evts & PQOS_PERF_EVENT_INSTRUCTIONS)) {
Packit Service 5befb9
                group->values.ipc = 0;
Packit Service 5befb9
                started_evts |= (enum pqos_mon_event)PQOS_PERF_EVENT_IPC;
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 8a4b7a
start_event_error:
Packit Service 5befb9
        /*  Check if all selected events were started */
Packit Service 5befb9
        if ((group->event & started_evts) != group->event) {
Packit Service 5befb9
                stop_events(group);
Packit Service 5befb9
                LOG_ERROR("Failed to start all selected "
Packit Service 5befb9
                          "OS monitoring events\n");
Packit Service 8a4b7a
                free(group->intl->perf.ctx);
Packit Service 8a4b7a
                group->intl->perf.ctx = NULL;
Packit Service 5befb9
        }
Packit Service 5befb9
        return ret;
Packit Service 5befb9
}
Packit Service 5befb9
Packit Service 5befb9
/**
Packit Service 5befb9
 * @brief This function polls selected events
Packit Service 5befb9
 *
Packit Service 5befb9
 * @param group monitoring structure
Packit Service 5befb9
 *
Packit Service 5befb9
 * @return Operation status
Packit Service 5befb9
 * @retval PQOS_RETVAL_OK on success
Packit Service 5befb9
 * @retval PQOS_RETVAL_ERROR on error
Packit Service 5befb9
 */
Packit Service 5befb9
static int
Packit Service 8a4b7a
poll_events(struct pqos_mon_data *group)
Packit Service 8a4b7a
{
Packit Service 5befb9
        unsigned i;
Packit Service 5befb9
        int ret = PQOS_RETVAL_OK;
Packit Service 5befb9
Packit Service 8a4b7a
        if (group->intl->resctrl.event != 0) {
Packit Service 5befb9
                ret = resctrl_lock_shared();
Packit Service 5befb9
                if (ret != PQOS_RETVAL_OK)
Packit Service 5befb9
                        return ret;
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 5befb9
        for (i = 0; i < DIM(os_mon_event); i++) {
Packit Service 5befb9
                enum pqos_mon_event evt = os_mon_event[i];
Packit Service 5befb9
Packit Service 5befb9
                /**
Packit Service 5befb9
                 * poll perf event
Packit Service 5befb9
                 */
Packit Service 8a4b7a
                if (group->intl->perf.event & evt) {
Packit Service 5befb9
                        ret = perf_mon_poll(group, evt);
Packit Service 5befb9
                        if (ret != PQOS_RETVAL_OK)
Packit Service 5befb9
                                goto poll_events_exit;
Packit Service 5befb9
                }
Packit Service 5befb9
Packit Service 5befb9
                /**
Packit Service 5befb9
                 * poll resctrl event
Packit Service 5befb9
                 */
Packit Service 8a4b7a
                if (group->intl->resctrl.event & evt) {
Packit Service 5befb9
                        ret = resctrl_mon_poll(group, evt);
Packit Service 5befb9
                        if (ret != PQOS_RETVAL_OK)
Packit Service 5befb9
                                goto poll_events_exit;
Packit Service 5befb9
                }
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 5befb9
        /**
Packit Service 5befb9
         * Calculate values of virtual events
Packit Service 5befb9
         */
Packit Service 5befb9
        if (group->event & PQOS_MON_EVENT_RMEM_BW) {
Packit Service 5befb9
                group->values.mbm_remote_delta = 0;
Packit Service 5befb9
                if (group->values.mbm_total_delta >
Packit Service 5befb9
                    group->values.mbm_local_delta)
Packit Service 5befb9
                        group->values.mbm_remote_delta =
Packit Service 8a4b7a
                            group->values.mbm_total_delta -
Packit Service 8a4b7a
                            group->values.mbm_local_delta;
Packit Service 5befb9
        }
Packit Service 5befb9
        if (group->event & PQOS_PERF_EVENT_IPC) {
Packit Service 8a4b7a
                if (group->values.ipc_unhalted_delta > 0)
Packit Service 5befb9
                        group->values.ipc =
Packit Service 8a4b7a
                            (double)group->values.ipc_retired_delta /
Packit Service 8a4b7a
                            (double)group->values.ipc_unhalted_delta;
Packit Service 5befb9
                else
Packit Service 5befb9
                        group->values.ipc = 0;
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 8a4b7a
poll_events_exit:
Packit Service 8a4b7a
        if (group->intl->resctrl.event != 0)
Packit Service 5befb9
                resctrl_lock_release();
Packit Service 5befb9
Packit Service 5befb9
        return ret;
Packit Service 5befb9
}
Packit Service 5befb9
Packit Service 5befb9
int
Packit Service 5befb9
os_mon_init(const struct pqos_cpuinfo *cpu, const struct pqos_cap *cap)
Packit Service 5befb9
{
Packit Service 5befb9
        unsigned ret;
Packit Service 5befb9
Packit Service 8a4b7a
        ASSERT(cpu != NULL);
Packit Service 8a4b7a
        ASSERT(cap != NULL);
Packit Service 8a4b7a
Packit Service 8a4b7a
        if (cpu == NULL || cap == NULL)
Packit Service 8a4b7a
                return PQOS_RETVAL_PARAM;
Packit Service 5befb9
Packit Service 5befb9
        ret = perf_mon_init(cpu, cap);
Packit Service 5befb9
        if (ret == PQOS_RETVAL_RESOURCE)
Packit Service 5befb9
                ret = resctrl_mon_init(cpu, cap);
Packit Service 5befb9
Packit Service 5befb9
        if (ret != PQOS_RETVAL_OK)
Packit Service 5befb9
                return ret;
Packit Service 5befb9
Packit Service 8a4b7a
        m_cpu = cpu;
Packit Service 5befb9
Packit Service 5befb9
        return ret;
Packit Service 5befb9
}
Packit Service 5befb9
Packit Service 5befb9
int
Packit Service 5befb9
os_mon_fini(void)
Packit Service 5befb9
{
Packit Service 5befb9
        m_cpu = NULL;
Packit Service 5befb9
Packit Service 5befb9
        perf_mon_fini();
Packit Service 5befb9
        resctrl_mon_fini();
Packit Service 5befb9
Packit Service 5befb9
        return PQOS_RETVAL_OK;
Packit Service 5befb9
}
Packit Service 5befb9
Packit Service 5befb9
int
Packit Service 8a4b7a
os_mon_reset(void)
Packit Service 8a4b7a
{
Packit Service 5befb9
        return resctrl_mon_reset();
Packit Service 5befb9
}
Packit Service 5befb9
Packit Service 5befb9
int
Packit Service 5befb9
os_mon_stop(struct pqos_mon_data *group)
Packit Service 5befb9
{
Packit Service 5befb9
        int ret;
Packit Service 5befb9
Packit Service 5befb9
        ASSERT(group != NULL);
Packit Service 5befb9
Packit Service 5befb9
        if (group->num_cores == 0 && group->tid_nr == 0)
Packit Service 5befb9
                return PQOS_RETVAL_PARAM;
Packit Service 5befb9
Packit Service 5befb9
        /* stop all started events */
Packit Service 5befb9
        ret = stop_events(group);
Packit Service 5befb9
Packit Service 5befb9
        /* free memory */
Packit Service 5befb9
        if (group->num_cores > 0) {
Packit Service 5befb9
                free(group->cores);
Packit Service 5befb9
                group->cores = NULL;
Packit Service 5befb9
        }
Packit Service 5befb9
        if (group->tid_nr > 0) {
Packit Service 5befb9
                free(group->tid_map);
Packit Service 5befb9
                group->tid_map = NULL;
Packit Service 5befb9
        }
Packit Service 5befb9
        memset(group, 0, sizeof(*group));
Packit Service 5befb9
Packit Service 5befb9
        return ret;
Packit Service 5befb9
}
Packit Service 5befb9
Packit Service 5befb9
int
Packit Service 5befb9
os_mon_start(const unsigned num_cores,
Packit Service 5befb9
             const unsigned *cores,
Packit Service 5befb9
             const enum pqos_mon_event event,
Packit Service 5befb9
             void *context,
Packit Service 5befb9
             struct pqos_mon_data *group)
Packit Service 5befb9
{
Packit Service 5befb9
        unsigned i = 0;
Packit Service 5befb9
        int ret;
Packit Service 8a4b7a
        const struct pqos_cap *cap;
Packit Service 8a4b7a
        const struct pqos_cpuinfo *cpu;
Packit Service 5befb9
Packit Service 5befb9
        ASSERT(group != NULL);
Packit Service 5befb9
        ASSERT(cores != NULL);
Packit Service 5befb9
        ASSERT(num_cores > 0);
Packit Service 5befb9
        ASSERT(event > 0);
Packit Service 5befb9
Packit Service 8a4b7a
        _pqos_cap_get(&cap, &cpu);
Packit Service 5befb9
Packit Service 5befb9
        /**
Packit Service 5befb9
         * Validate if event is listed in capabilities
Packit Service 5befb9
         */
Packit Service 5befb9
        for (i = 0; i < (sizeof(event) * 8); i++) {
Packit Service 5befb9
                const enum pqos_mon_event evt_mask =
Packit Service 8a4b7a
                    (enum pqos_mon_event)(1U << i);
Packit Service 5befb9
                const struct pqos_monitor *ptr = NULL;
Packit Service 5befb9
Packit Service 5befb9
                if (!(evt_mask & event))
Packit Service 5befb9
                        continue;
Packit Service 5befb9
Packit Service 8a4b7a
                ret = pqos_cap_get_event(cap, evt_mask, &ptr);
Packit Service 5befb9
                if (ret != PQOS_RETVAL_OK || ptr == NULL)
Packit Service 5befb9
                        return PQOS_RETVAL_PARAM;
Packit Service 5befb9
        }
Packit Service 5befb9
        /**
Packit Service 5befb9
         * Check if all requested cores are valid
Packit Service 5befb9
         * and not used by other monitoring processes.
Packit Service 5befb9
         */
Packit Service 5befb9
        for (i = 0; i < num_cores; i++) {
Packit Service 5befb9
                const unsigned lcore = cores[i];
Packit Service 5befb9
Packit Service 8a4b7a
                ret = pqos_cpu_check_core(cpu, lcore);
Packit Service 5befb9
                if (ret != PQOS_RETVAL_OK)
Packit Service 5befb9
                        return PQOS_RETVAL_PARAM;
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 5befb9
        /**
Packit Service 5befb9
         * Fill in the monitoring group structure
Packit Service 5befb9
         */
Packit Service 5befb9
        group->event = event;
Packit Service 5befb9
        group->context = context;
Packit Service 8a4b7a
        group->cores = (unsigned *)malloc(sizeof(group->cores[0]) * num_cores);
Packit Service 5befb9
        if (group->cores == NULL)
Packit Service 5befb9
                return PQOS_RETVAL_RESOURCE;
Packit Service 5befb9
Packit Service 5befb9
        group->num_cores = num_cores;
Packit Service 5befb9
        for (i = 0; i < num_cores; i++)
Packit Service 5befb9
                group->cores[i] = cores[i];
Packit Service 5befb9
Packit Service 5befb9
        ret = start_events(group);
Packit Service 5befb9
        if (ret != PQOS_RETVAL_OK && group->cores != NULL)
Packit Service 5befb9
                free(group->cores);
Packit Service 5befb9
Packit Service 5befb9
        return ret;
Packit Service 5befb9
}
Packit Service 5befb9
Packit Service 5befb9
/**
Packit Service 5befb9
 * @brief Check if \a tid is in \a tid_map
Packit Service 5befb9
 *
Packit Service 5befb9
 * @param[in] tid TID number to search for
Packit Service 8a4b7a
 * @param[in] tid_nr length of \a tid_map
Packit Service 5befb9
 * @param[in] tid_map list of TIDs
Packit Service 5befb9
 *
Packit Service 5befb9
 * @retval 1 if found
Packit Service 5befb9
 */
Packit Service 5befb9
static int
Packit Service 5befb9
tid_exists(const pid_t tid, const unsigned tid_nr, const pid_t *tid_map)
Packit Service 5befb9
{
Packit Service 5befb9
        unsigned i;
Packit Service 5befb9
Packit Service 5befb9
        if (tid_map == NULL)
Packit Service 5befb9
                return 0;
Packit Service 5befb9
Packit Service 5befb9
        for (i = 0; i < tid_nr; i++)
Packit Service 5befb9
                if (tid_map[i] == tid)
Packit Service 5befb9
                        return 1;
Packit Service 5befb9
Packit Service 5befb9
        return 0;
Packit Service 5befb9
}
Packit Service 5befb9
Packit Service 5befb9
/**
Packit Service 5befb9
 * @brief Add TID to \a tid_map
Packit Service 5befb9
 *
Packit Service 5befb9
 * @param[in] tid TID number to add
Packit Service 8a4b7a
 * @param[in] tid_nr length of \a tid_map
Packit Service 5befb9
 * @param[in] tid_map list of TIDs
Packit Service 5befb9
 *
Packit Service 5befb9
 * @return Operational status
Packit Service 5befb9
 * @retval PQOS_RETVAL_OK on success
Packit Service 5befb9
 */
Packit Service 5befb9
static int
Packit Service 8a4b7a
tid_add(const pid_t tid, unsigned *tid_nr, pid_t **tid_map)
Packit Service 8a4b7a
{
Packit Service 5befb9
        pid_t *tids;
Packit Service 5befb9
Packit Service 5befb9
        if (tid_exists(tid, *tid_nr, *tid_map))
Packit Service 5befb9
                return PQOS_RETVAL_OK;
Packit Service 5befb9
Packit Service 5befb9
        tids = realloc(*tid_map, sizeof(pid_t) * (*tid_nr + 1));
Packit Service 5befb9
        if (tids == NULL) {
Packit Service 5befb9
                LOG_ERROR("TID map allocation error!\n");
Packit Service 5befb9
                return PQOS_RETVAL_ERROR;
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 5befb9
        tids[*tid_nr] = tid;
Packit Service 5befb9
        (*tid_nr)++;
Packit Service 5befb9
        *tid_map = tids;
Packit Service 5befb9
Packit Service 5befb9
        return PQOS_RETVAL_OK;
Packit Service 5befb9
}
Packit Service 5befb9
Packit Service 5befb9
/**
Packit Service 5befb9
 * @brief Find process TID's and add them to the list
Packit Service 5befb9
 *
Packit Service 5befb9
 * @param[in] pid peocess id
Packit Service 5befb9
 * @param[inout] tid_nr numer of tids
Packit Service 5befb9
 * @param[inout] tid_map tid mapping
Packit Service 5befb9
 *
Packit Service 5befb9
 * @return Operations status
Packit Service 5befb9
 * @retval PQOS_RETVAL_OK on success
Packit Service 5befb9
 */
Packit Service 5befb9
static int
Packit Service 5befb9
tid_find(const pid_t pid, unsigned *tid_nr, pid_t **tid_map)
Packit Service 5befb9
{
Packit Service 5befb9
        char buf[64];
Packit Service 5befb9
        pid_t tid;
Packit Service 5befb9
        int num_tasks, i;
Packit Service 5befb9
        struct dirent **namelist = NULL;
Packit Service 5befb9
        int ret;
Packit Service 5befb9
Packit Service 5befb9
        snprintf(buf, sizeof(buf) - 1, "/proc/%d/task", (int)pid);
Packit Service 5befb9
        num_tasks = scandir(buf, &namelist, filter, NULL);
Packit Service 5befb9
        if (num_tasks <= 0) {
Packit Service 5befb9
                LOG_ERROR("Failed to read proc tasks!\n");
Packit Service 5befb9
                return PQOS_RETVAL_ERROR;
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 5befb9
        /**
Packit Service 5befb9
         * Determine if user selected a PID or TID
Packit Service 5befb9
         * If TID selected, only monitor events for that task
Packit Service 5befb9
         * otherwise monitor all tasks in the process
Packit Service 5befb9
         */
Packit Service 5befb9
        tid = atoi(namelist[0]->d_name);
Packit Service 5befb9
        if (pid != tid)
Packit Service 5befb9
                ret = tid_add(pid, tid_nr, tid_map);
Packit Service 5befb9
        else
Packit Service 5befb9
                for (i = 0; i < num_tasks; i++) {
Packit Service 8a4b7a
                        ret = tid_add((pid_t)atoi(namelist[i]->d_name), tid_nr,
Packit Service 8a4b7a
                                      tid_map);
Packit Service 5befb9
                        if (ret != PQOS_RETVAL_OK)
Packit Service 5befb9
                                break;
Packit Service 5befb9
                }
Packit Service 5befb9
Packit Service 8a4b7a
        for (i = 0; i < num_tasks; i++)
Packit Service 8a4b7a
                free(namelist[i]);
Packit Service 8a4b7a
Packit Service 5befb9
        free(namelist);
Packit Service 5befb9
Packit Service 5befb9
        return ret;
Packit Service 5befb9
}
Packit Service 5befb9
Packit Service 5befb9
/**
Packit Service 5befb9
 * @brief Verify is PID is correct
Packit Service 5befb9
 *
Packit Service 5befb9
 * @param[in] pid PID number to check
Packit Service 5befb9
 *
Packit Service 5befb9
 * @retval 1 if PID is correct
Packit Service 5befb9
 */
Packit Service 5befb9
static int
Packit Service 5befb9
tid_verify(const pid_t pid)
Packit Service 5befb9
{
Packit Service 5befb9
        int found = 0;
Packit Service 5befb9
        char buf[64];
Packit Service 5befb9
        DIR *dir;
Packit Service 5befb9
Packit Service 5befb9
        snprintf(buf, sizeof(buf) - 1, "/proc/%d", (int)pid);
Packit Service 5befb9
        dir = opendir(buf);
Packit Service 5befb9
        if (dir != NULL) {
Packit Service 5befb9
                found = 1;
Packit Service 5befb9
                closedir(dir);
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 5befb9
        return found;
Packit Service 5befb9
}
Packit Service 5befb9
Packit Service 5befb9
int
Packit Service 5befb9
os_mon_start_pids(const unsigned num_pids,
Packit Service 5befb9
                  const pid_t *pids,
Packit Service 5befb9
                  const enum pqos_mon_event event,
Packit Service 5befb9
                  void *context,
Packit Service 5befb9
                  struct pqos_mon_data *group)
Packit Service 5befb9
{
Packit Service 5befb9
        int ret;
Packit Service 5befb9
        unsigned i;
Packit Service 5befb9
        pid_t *tid_map = NULL;
Packit Service 5befb9
        unsigned tid_nr = 0;
Packit Service 5befb9
Packit Service 5befb9
        ASSERT(group != NULL);
Packit Service 5befb9
        ASSERT(num_pids > 0);
Packit Service 5befb9
        ASSERT(event > 0);
Packit Service 5befb9
        ASSERT(pids != NULL);
Packit Service 5befb9
Packit Service 5befb9
        /**
Packit Service 5befb9
         * Check if all PIDs exists
Packit Service 5befb9
         */
Packit Service 5befb9
        for (i = 0; i < num_pids; i++) {
Packit Service 5befb9
                pid_t pid = pids[i];
Packit Service 5befb9
Packit Service 5befb9
                if (!tid_verify(pid)) {
Packit Service 5befb9
                        LOG_ERROR("Task %d does not exist!\n", (int)pid);
Packit Service 5befb9
                        return PQOS_RETVAL_PARAM;
Packit Service 5befb9
                }
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 5befb9
        /**
Packit Service 5befb9
         * Get TID's for selected tasks
Packit Service 5befb9
         */
Packit Service 5befb9
        for (i = 0; i < num_pids; i++) {
Packit Service 5befb9
                ret = tid_find(pids[i], &tid_nr, &tid_map);
Packit Service 5befb9
                if (ret != PQOS_RETVAL_OK)
Packit Service 5befb9
                        goto os_mon_start_pids_exit;
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 8a4b7a
        group->pids = (pid_t *)malloc(sizeof(pid_t) * num_pids);
Packit Service 5befb9
        if (group->pids == NULL) {
Packit Service 5befb9
                ret = PQOS_RETVAL_RESOURCE;
Packit Service 5befb9
                goto os_mon_start_pids_exit;
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 5befb9
        group->context = context;
Packit Service 5befb9
        group->tid_nr = tid_nr;
Packit Service 5befb9
        group->tid_map = tid_map;
Packit Service 5befb9
        group->event = event;
Packit Service 5befb9
        group->num_pids = num_pids;
Packit Service 5befb9
Packit Service 5befb9
        for (i = 0; i < num_pids; i++)
Packit Service 5befb9
                group->pids[i] = pids[i];
Packit Service 5befb9
Packit Service 5befb9
        ret = start_events(group);
Packit Service 5befb9
Packit Service 8a4b7a
os_mon_start_pids_exit:
Packit Service 5befb9
        if (ret != PQOS_RETVAL_OK && tid_map != NULL)
Packit Service 5befb9
                free(tid_map);
Packit Service 5befb9
Packit Service 5befb9
        return ret;
Packit Service 5befb9
}
Packit Service 5befb9
Packit Service 5befb9
int
Packit Service 5befb9
os_mon_add_pids(const unsigned num_pids,
Packit Service 5befb9
                const pid_t *pids,
Packit Service 5befb9
                struct pqos_mon_data *group)
Packit Service 5befb9
{
Packit Service 5befb9
        int ret;
Packit Service 5befb9
        unsigned i;
Packit Service 5befb9
        pid_t *tid_map = NULL;
Packit Service 5befb9
        pid_t *ptr;
Packit Service 5befb9
        unsigned tid_nr = 0;
Packit Service 5befb9
        struct pqos_mon_data added;
Packit Service 5befb9
        struct pqos_mon_perf_ctx *ctx;
Packit Service 5befb9
        unsigned num_duplicated = 0;
Packit Service 5befb9
Packit Service 5befb9
        ASSERT(group != NULL);
Packit Service 5befb9
        ASSERT(num_pids > 0);
Packit Service 5befb9
        ASSERT(pids != NULL);
Packit Service 5befb9
Packit Service 5befb9
        memset(&added, 0, sizeof(added));
Packit Service 5befb9
Packit Service 5befb9
        /**
Packit Service 5befb9
         * Check if all PIDs exists
Packit Service 5befb9
         */
Packit Service 5befb9
        for (i = 0; i < num_pids; i++) {
Packit Service 5befb9
                pid_t pid = pids[i];
Packit Service 5befb9
Packit Service 5befb9
                if (!tid_verify(pid)) {
Packit Service 5befb9
                        LOG_ERROR("Task %d does not exist!\n", (int)pid);
Packit Service 5befb9
                        return PQOS_RETVAL_PARAM;
Packit Service 5befb9
                }
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 5befb9
        /**
Packit Service 5befb9
         * Get TID's for added tasks
Packit Service 5befb9
         */
Packit Service 5befb9
        for (i = 0; i < num_pids; i++) {
Packit Service 5befb9
                ret = tid_find(pids[i], &tid_nr, &tid_map);
Packit Service 5befb9
                if (ret != PQOS_RETVAL_OK)
Packit Service 5befb9
                        goto os_mon_add_pids_exit;
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 5befb9
        /**
Packit Service 5befb9
         * Find duplicated tids
Packit Service 5befb9
         */
Packit Service 5befb9
        for (i = 0; i < tid_nr; i++) {
Packit Service 5befb9
                if (tid_exists(tid_map[i], group->tid_nr, group->tid_map)) {
Packit Service 5befb9
                        num_duplicated++;
Packit Service 5befb9
                        continue;
Packit Service 5befb9
                }
Packit Service 5befb9
Packit Service 5befb9
                tid_map[i - num_duplicated] = tid_map[i];
Packit Service 5befb9
        }
Packit Service 5befb9
        tid_nr -= num_duplicated;
Packit Service 5befb9
        if (tid_nr == 0) {
Packit Service 5befb9
                LOG_INFO("No new TIDs to be added\n");
Packit Service 5befb9
                ret = PQOS_RETVAL_OK;
Packit Service 5befb9
                goto os_mon_add_pids_exit;
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 5befb9
        /**
Packit Service 5befb9
         * Start monitoring for the new TIDs
Packit Service 5befb9
         */
Packit Service 5befb9
        added.tid_nr = tid_nr;
Packit Service 5befb9
        added.tid_map = tid_map;
Packit Service 5befb9
        added.event = group->event;
Packit Service 5befb9
        added.num_pids = num_pids;
Packit Service 8a4b7a
        added.intl = malloc(sizeof(*added.intl));
Packit Service 8a4b7a
        if (added.intl == NULL)
Packit Service 8a4b7a
                goto os_mon_add_pids_exit;
Packit Service 8a4b7a
        memset(added.intl, 0, sizeof(*added.intl));
Packit Service 8a4b7a
        if (group->intl->resctrl.mon_group != NULL) {
Packit Service 8a4b7a
                added.intl->resctrl.mon_group =
Packit Service 8a4b7a
                    strdup(group->intl->resctrl.mon_group);
Packit Service 8a4b7a
                if (added.intl->resctrl.mon_group == NULL) {
Packit Service 5befb9
                        ret = PQOS_RETVAL_RESOURCE;
Packit Service 5befb9
                        goto os_mon_add_pids_exit;
Packit Service 5befb9
                }
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 5befb9
        ret = start_events(&added);
Packit Service 5befb9
        if (ret != PQOS_RETVAL_OK)
Packit Service 5befb9
                goto os_mon_add_pids_exit;
Packit Service 5befb9
Packit Service 5befb9
        /**
Packit Service 5befb9
         * Update mon group
Packit Service 5befb9
         */
Packit Service 8a4b7a
        ptr = realloc(group->tid_map, sizeof(group->tid_map[0]) *
Packit Service 8a4b7a
                                          (group->tid_nr + added.tid_nr));
Packit Service 5befb9
        if (ptr == NULL) {
Packit Service 5befb9
                ret = PQOS_RETVAL_RESOURCE;
Packit Service 5befb9
                goto os_mon_add_pids_exit;
Packit Service 5befb9
        }
Packit Service 5befb9
        group->tid_map = ptr;
Packit Service 5befb9
Packit Service 8a4b7a
        ctx =
Packit Service 8a4b7a
            realloc(group->intl->perf.ctx, sizeof(group->intl->perf.ctx[0]) *
Packit Service 8a4b7a
                                               (group->tid_nr + added.tid_nr));
Packit Service 5befb9
        if (ctx == NULL) {
Packit Service 5befb9
                ret = PQOS_RETVAL_RESOURCE;
Packit Service 5befb9
                goto os_mon_add_pids_exit;
Packit Service 5befb9
        }
Packit Service 8a4b7a
        group->intl->perf.ctx = ctx;
Packit Service 5befb9
Packit Service 5befb9
        ptr = realloc(group->pids,
Packit Service 8a4b7a
                      sizeof(group->pids[0]) * (group->num_pids + num_pids));
Packit Service 5befb9
        if (ptr == NULL) {
Packit Service 5befb9
                ret = PQOS_RETVAL_RESOURCE;
Packit Service 5befb9
                goto os_mon_add_pids_exit;
Packit Service 5befb9
        }
Packit Service 5befb9
        group->pids = ptr;
Packit Service 5befb9
Packit Service 5befb9
        for (i = 0; i < added.tid_nr; i++) {
Packit Service 5befb9
                group->tid_map[group->tid_nr] = added.tid_map[i];
Packit Service 8a4b7a
                group->intl->perf.ctx[group->tid_nr] = added.intl->perf.ctx[i];
Packit Service 5befb9
                group->tid_nr++;
Packit Service 5befb9
        }
Packit Service 5befb9
        for (i = 0; i < num_pids; i++) {
Packit Service 5befb9
                group->pids[group->num_pids] = pids[i];
Packit Service 5befb9
                group->num_pids++;
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 8a4b7a
os_mon_add_pids_exit:
Packit Service 8a4b7a
        if (added.intl != NULL && added.intl->resctrl.mon_group != NULL) {
Packit Service 8a4b7a
                free(added.intl->resctrl.mon_group);
Packit Service 8a4b7a
                added.intl->resctrl.mon_group = NULL;
Packit Service 5befb9
        }
Packit Service 5befb9
        if (ret == PQOS_RETVAL_RESOURCE) {
Packit Service 5befb9
                LOG_ERROR("Memory allocation error!\n");
Packit Service 5befb9
                stop_events(&added);
Packit Service 5befb9
        }
Packit Service 8a4b7a
        if (added.intl != NULL) {
Packit Service 8a4b7a
                if (added.intl->perf.ctx != NULL)
Packit Service 8a4b7a
                        free(added.intl->perf.ctx);
Packit Service 8a4b7a
                free(added.intl);
Packit Service 8a4b7a
        }
Packit Service 5befb9
        if (tid_map != NULL)
Packit Service 5befb9
                free(tid_map);
Packit Service 5befb9
        return ret;
Packit Service 5befb9
}
Packit Service 5befb9
Packit Service 5befb9
int
Packit Service 5befb9
os_mon_remove_pids(const unsigned num_pids,
Packit Service 5befb9
                   const pid_t *pids,
Packit Service 5befb9
                   struct pqos_mon_data *group)
Packit Service 5befb9
{
Packit Service 5befb9
Packit Service 5befb9
        int ret = PQOS_RETVAL_OK;
Packit Service 5befb9
        unsigned i;
Packit Service 5befb9
        pid_t *keep_tid_map = NULL; /* List of not removed TIDs */
Packit Service 5befb9
        unsigned keep_tid_nr = 0;
Packit Service 5befb9
        struct pqos_mon_data remove;
Packit Service 5befb9
        unsigned removed;
Packit Service 5befb9
Packit Service 5befb9
        ASSERT(num_pids > 0);
Packit Service 5befb9
        ASSERT(pids != NULL);
Packit Service 5befb9
        ASSERT(group != NULL);
Packit Service 5befb9
Packit Service 8a4b7a
        memset(&remove, 0, sizeof(remove));
Packit Service 8a4b7a
Packit Service 5befb9
        /**
Packit Service 5befb9
         * Find TID's for not removed tasks
Packit Service 5befb9
         */
Packit Service 5befb9
        for (i = 0; i < group->num_pids; i++) {
Packit Service 5befb9
                /* skip PIDs on removed list */
Packit Service 5befb9
                if (tid_exists(group->pids[i], num_pids, pids))
Packit Service 5befb9
                        continue;
Packit Service 5befb9
Packit Service 5befb9
                /* pid no longer exists */
Packit Service 5befb9
                if (!tid_verify(group->pids[i]))
Packit Service 5befb9
                        continue;
Packit Service 5befb9
Packit Service 5befb9
                ret = tid_find(group->pids[i], &keep_tid_nr, &keep_tid_map);
Packit Service 5befb9
                if (ret != PQOS_RETVAL_OK)
Packit Service 5befb9
                        goto os_mon_remove_pids_exit;
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 8a4b7a
        remove.intl =
Packit Service 8a4b7a
            (struct pqos_mon_data_internal *)malloc(sizeof(*remove.intl));
Packit Service 8a4b7a
        if (remove.intl == NULL)
Packit Service 8a4b7a
                goto os_mon_remove_pids_exit;
Packit Service 8a4b7a
        memset(remove.intl, 0, sizeof(*remove.intl));
Packit Service 8a4b7a
        remove.intl->perf.event = group->intl->perf.event;
Packit Service 8a4b7a
        remove.intl->resctrl.event = group->intl->resctrl.event;
Packit Service 5befb9
        remove.pids = NULL;
Packit Service 5befb9
        remove.num_pids = num_pids;
Packit Service 5befb9
        remove.tid_map = malloc(sizeof(remove.tid_map[0]) * group->tid_nr);
Packit Service 5befb9
        if (remove.tid_map == NULL)
Packit Service 5befb9
                goto os_mon_remove_pids_exit;
Packit Service 8a4b7a
        remove.intl->perf.ctx =
Packit Service 8a4b7a
            malloc(sizeof(remove.intl->perf.ctx[0]) * group->tid_nr);
Packit Service 8a4b7a
        if (remove.intl->perf.ctx == NULL)
Packit Service 5befb9
                goto os_mon_remove_pids_exit;
Packit Service 5befb9
Packit Service 5befb9
        /* Add tid's for removal */
Packit Service 5befb9
        for (i = 0; i < group->tid_nr; i++) {
Packit Service 5befb9
                /* TID is not removed */
Packit Service 5befb9
                if (tid_exists(group->tid_map[i], keep_tid_nr, keep_tid_map))
Packit Service 5befb9
                        continue;
Packit Service 5befb9
Packit Service 5befb9
                remove.tid_map[remove.tid_nr] = group->tid_map[i];
Packit Service 8a4b7a
                remove.intl->perf.ctx[remove.tid_nr] = group->intl->perf.ctx[i];
Packit Service 5befb9
                remove.tid_nr++;
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 5befb9
        ret = stop_events(&remove);
Packit Service 5befb9
        if (ret != PQOS_RETVAL_OK)
Packit Service 5befb9
                goto os_mon_remove_pids_exit;
Packit Service 5befb9
Packit Service 5befb9
        /**
Packit Service 5befb9
         * Update mon group
Packit Service 5befb9
         */
Packit Service 5befb9
        removed = 0;
Packit Service 5befb9
        for (i = 0; i < group->tid_nr; i++) {
Packit Service 5befb9
                /* TID does not exists on the not keep list */
Packit Service 5befb9
                if (!tid_exists(group->tid_map[i], keep_tid_nr, keep_tid_map)) {
Packit Service 5befb9
                        removed++;
Packit Service 5befb9
                        continue;
Packit Service 5befb9
                }
Packit Service 5befb9
Packit Service 5befb9
                group->tid_map[i - removed] = group->tid_map[i];
Packit Service 8a4b7a
                group->intl->perf.ctx[i - removed] = group->intl->perf.ctx[i];
Packit Service 5befb9
        }
Packit Service 5befb9
        group->tid_nr -= removed;
Packit Service 8a4b7a
        group->tid_map =
Packit Service 8a4b7a
            realloc(group->tid_map, sizeof(group->tid_map[0]) * group->tid_nr);
Packit Service 8a4b7a
        group->intl->perf.ctx =
Packit Service 8a4b7a
            realloc(group->intl->perf.ctx,
Packit Service 8a4b7a
                    sizeof(group->intl->perf.ctx[0]) * group->tid_nr);
Packit Service 5befb9
        removed = 0;
Packit Service 5befb9
        for (i = 0; i < group->num_pids; i++) {
Packit Service 5befb9
                if (tid_exists(group->pids[i], num_pids, pids)) {
Packit Service 5befb9
                        removed++;
Packit Service 5befb9
                        continue;
Packit Service 5befb9
                }
Packit Service 5befb9
Packit Service 5befb9
                group->pids[i - removed] = group->pids[i];
Packit Service 5befb9
        }
Packit Service 5befb9
        group->num_pids -= removed;
Packit Service 8a4b7a
        group->pids =
Packit Service 8a4b7a
            realloc(group->pids, sizeof(group->pids[0]) * group->num_pids);
Packit Service 5befb9
Packit Service 8a4b7a
os_mon_remove_pids_exit:
Packit Service 8a4b7a
        if (remove.tid_map != NULL)
Packit Service 8a4b7a
                free(remove.tid_map);
Packit Service 8a4b7a
        if (remove.intl != NULL) {
Packit Service 8a4b7a
                if (remove.intl->perf.ctx)
Packit Service 8a4b7a
                        free(remove.intl->perf.ctx);
Packit Service 8a4b7a
                free(remove.intl);
Packit Service 8a4b7a
        }
Packit Service 5befb9
        if (keep_tid_map != NULL)
Packit Service 5befb9
                free(keep_tid_map);
Packit Service 5befb9
        return ret;
Packit Service 5befb9
}
Packit Service 5befb9
Packit Service 5befb9
int
Packit Service 8a4b7a
os_mon_poll(struct pqos_mon_data **groups, const unsigned num_groups)
Packit Service 5befb9
{
Packit Service 5befb9
        unsigned i = 0;
Packit Service 5befb9
Packit Service 5befb9
        ASSERT(groups != NULL);
Packit Service 5befb9
        ASSERT(num_groups > 0);
Packit Service 5befb9
Packit Service 5befb9
        for (i = 0; i < num_groups; i++) {
Packit Service 8a4b7a
                int ret = poll_events(groups[i]);
Packit Service 8a4b7a
Packit Service 5befb9
                if (ret != PQOS_RETVAL_OK)
Packit Service 8a4b7a
                        LOG_WARN("Failed to poll event on "
Packit Service 8a4b7a
                                 "group number %u\n",
Packit Service 8a4b7a
                                 i);
Packit Service 5befb9
        }
Packit Service 5befb9
Packit Service 5befb9
        return PQOS_RETVAL_OK;
Packit Service 5befb9
}