mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2025-12-26 14:41:25 +00:00
Signed-off-by: Frediano Ziglio <fziglio@redhat.com> Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
134 lines
4.2 KiB
C
134 lines
4.2 KiB
C
/*
|
|
Copyright (C) 2009 Red Hat, Inc.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#define _GNU_SOURCE
|
|
#include <config.h>
|
|
#include <sys/types.h>
|
|
#include <sys/mman.h>
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <inttypes.h>
|
|
#include <spice/stats.h>
|
|
|
|
#define TAB_LEN 4
|
|
#define VALUE_TABS 7
|
|
#define INVALID_STAT_REF (~(uint32_t)0)
|
|
|
|
static SpiceStat *reds_stat = (SpiceStat *)MAP_FAILED;
|
|
static uint64_t *values = NULL;
|
|
|
|
static void print_stat_tree(int32_t node_index, int depth)
|
|
{
|
|
SpiceStatNode *node = &reds_stat->nodes[node_index];
|
|
|
|
if ((node->flags & SPICE_STAT_NODE_MASK_SHOW) == SPICE_STAT_NODE_MASK_SHOW) {
|
|
printf("%*s%s", depth * TAB_LEN, "", node->name);
|
|
if (node->flags & SPICE_STAT_NODE_FLAG_VALUE) {
|
|
printf(":%*s%"PRIu64" (%"PRIu64")\n", (int) ((VALUE_TABS - depth) * TAB_LEN - strlen(node->name) - 1), "",
|
|
node->value, node->value - values[node_index]);
|
|
values[node_index] = node->value;
|
|
} else {
|
|
printf("\n");
|
|
if (node->first_child_index != INVALID_STAT_REF) {
|
|
print_stat_tree(node->first_child_index, depth + 1);
|
|
}
|
|
}
|
|
}
|
|
if (node->next_sibling_index != INVALID_STAT_REF) {
|
|
print_stat_tree(node->next_sibling_index, depth);
|
|
}
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
char *shm_name;
|
|
pid_t kvm_pid;
|
|
uint32_t num_of_nodes = 0;
|
|
size_t shm_size;
|
|
size_t shm_old_size;
|
|
int shm_name_len;
|
|
int ret = -1;
|
|
int fd;
|
|
|
|
if (argc != 2 || !(kvm_pid = atoi(argv[1]))) {
|
|
printf("usage: reds_stat [qemu_pid] (e.g. `pgrep qemu`)\n");
|
|
return -1;
|
|
}
|
|
shm_name_len = strlen(SPICE_STAT_SHM_NAME) + strlen(argv[1]);
|
|
if (!(shm_name = (char *)malloc(shm_name_len))) {
|
|
perror("malloc");
|
|
return -1;
|
|
}
|
|
snprintf(shm_name, shm_name_len, SPICE_STAT_SHM_NAME, kvm_pid);
|
|
if ((fd = shm_open(shm_name, O_RDONLY, 0444)) == -1) {
|
|
perror("shm_open");
|
|
free(shm_name);
|
|
return -1;
|
|
}
|
|
shm_size = sizeof(SpiceStat);
|
|
reds_stat = (SpiceStat *)mmap(NULL, shm_size, PROT_READ, MAP_SHARED, fd, 0);
|
|
if (reds_stat == (SpiceStat *)MAP_FAILED) {
|
|
perror("mmap");
|
|
goto error;
|
|
}
|
|
if (reds_stat->magic != SPICE_STAT_MAGIC) {
|
|
printf("bad magic %u\n", reds_stat->magic);
|
|
goto error;
|
|
}
|
|
if (reds_stat->version != SPICE_STAT_VERSION) {
|
|
printf("bad version %u\n", reds_stat->version);
|
|
goto error;
|
|
}
|
|
while (1) {
|
|
if (system("clear") != 0) {
|
|
printf("\n\n\n");
|
|
}
|
|
printf("spice statistics\n\n");
|
|
if (num_of_nodes != reds_stat->num_of_nodes) {
|
|
num_of_nodes = reds_stat->num_of_nodes;
|
|
shm_old_size = shm_size;
|
|
shm_size = sizeof(SpiceStat) + num_of_nodes * sizeof(SpiceStatNode);
|
|
reds_stat = mremap(reds_stat, shm_old_size, shm_size, MREMAP_MAYMOVE);
|
|
if (reds_stat == (SpiceStat *)MAP_FAILED) {
|
|
perror("mremap");
|
|
goto error;
|
|
}
|
|
values = (uint64_t *)realloc(values, num_of_nodes * sizeof(uint64_t));
|
|
if (values == NULL) {
|
|
perror("realloc");
|
|
goto error;
|
|
}
|
|
memset(values, 0, num_of_nodes * sizeof(uint64_t));
|
|
}
|
|
print_stat_tree(reds_stat->root_index, 0);
|
|
sleep(1);
|
|
}
|
|
ret = 0;
|
|
|
|
error:
|
|
free(values);
|
|
if (reds_stat != (SpiceStat *)MAP_FAILED) {
|
|
munmap(reds_stat, shm_size);
|
|
}
|
|
shm_unlink(shm_name);
|
|
free(shm_name);
|
|
return ret;
|
|
}
|