|
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 |
}
|