/*
* Copyright (c) 2010 Stanislav Kozina
* Copyright (c) 2010 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @addtogroup libc
* @{
*/
/** @file
*/
#include <stats.h>
#include <sysinfo.h>
#include <errno.h>
#include <stdio.h>
#include <inttypes.h>
#include <stdlib.h>
#define SYSINFO_STATS_MAX_PATH 64
/** Thread states
*
*/
static const char *thread_states[] = {
"Invalid",
"Running",
"Sleeping",
"Ready",
"Entering",
"Exiting",
"Lingering"
};
/** Get CPUs statistics
*
* @param count Number of records returned.
*
* @return Array of stats_cpu_t structures.
* If non-NULL then it should be eventually freed
* by free().
*
*/
stats_cpu_t *stats_get_cpus(size_t *count)
{
size_t size = 0;
stats_cpu_t *stats_cpus =
(stats_cpu_t *) sysinfo_get_data("system.cpus", &size);
if ((size % sizeof(stats_cpu_t)) != 0) {
if (stats_cpus != NULL)
free(stats_cpus);
*count = 0;
return NULL;
}
*count = size / sizeof(stats_cpu_t);
return stats_cpus;
}
/** Get physical memory statistics
*
*
* @return Pointer to the stats_physmem_t structure.
* If non-NULL then it should be eventually freed
* by free().
*
*/
stats_physmem_t *stats_get_physmem(void)
{
size_t size = 0;
stats_physmem_t *stats_physmem =
(stats_physmem_t *) sysinfo_get_data("system.physmem", &size);
if (size != sizeof(stats_physmem_t)) {
if (stats_physmem != NULL)
free(stats_physmem);
return NULL;
}
return stats_physmem;
}
/** Get task statistics
*
* @param count Number of records returned.
*
* @return Array of stats_task_t structures.
* If non-NULL then it should be eventually freed
* by free().
*
*/
stats_task_t *stats_get_tasks(size_t *count)
{
size_t size = 0;
stats_task_t *stats_tasks =
(stats_task_t *) sysinfo_get_data("system.tasks", &size);
if ((size % sizeof(stats_task_t)) != 0) {
if (stats_tasks != NULL)
free(stats_tasks);
*count = 0;
return NULL;
}
*count = size / sizeof(stats_task_t);
return stats_tasks;
}
/** Get single task statistics
*
* @param task_id Task ID we are interested in.
*
* @return Pointer to the stats_task_t structure.
* If non-NULL then it should be eventually freed
* by free().
*
*/
stats_task_t *stats_get_task(task_id_t task_id)
{
char name[SYSINFO_STATS_MAX_PATH];
snprintf(name, SYSINFO_STATS_MAX_PATH, "system.tasks.%" PRIu64, task_id);
size_t size = 0;
stats_task_t *stats_task =
(stats_task_t *) sysinfo_get_data(name, &size);
if (size != sizeof(stats_task_t)) {
if (stats_task != NULL)
free(stats_task);
return NULL;
}
return stats_task;
}
/** Get thread statistics.
*
* @param count Number of records returned.
*
* @return Array of stats_thread_t structures.
* If non-NULL then it should be eventually freed
* by free().
*
*/
stats_thread_t *stats_get_threads(size_t *count)
{
size_t size = 0;
stats_thread_t *stats_threads =
(stats_thread_t *) sysinfo_get_data("system.threads", &size);
if ((size % sizeof(stats_thread_t)) != 0) {
if (stats_threads != NULL)
free(stats_threads);
*count = 0;
return NULL;
}
*count = size / sizeof(stats_thread_t);
return stats_threads;
}
/** Get IPC connections statistics.
*
* @param count Number of records returned.
*
* @return Array of stats_ipcc_t structures.
* If non-NULL then it should be eventually freed
* by free().
*
*/
stats_ipcc_t *stats_get_ipccs(size_t *count)
{
size_t size = 0;
stats_ipcc_t *stats_ipccs =
(stats_ipcc_t *) sysinfo_get_data("system.ipccs", &size);
if ((size % sizeof(stats_ipcc_t)) != 0) {
if (stats_ipccs != NULL)
free(stats_ipccs);
*count = 0;
return NULL;
}
*count = size / sizeof(stats_ipcc_t);
return stats_ipccs;
}
/** Get exception statistics.
*
* @param count Number of records returned.
*
* @return Array of stats_exc_t structures.
* If non-NULL then it should be eventually freed
* by free().
*
*/
stats_exc_t *stats_get_exceptions(size_t *count)
{
size_t size = 0;
stats_exc_t *stats_exceptions =
(stats_exc_t *) sysinfo_get_data("system.exceptions", &size);
if ((size % sizeof(stats_exc_t)) != 0) {
if (stats_exceptions != NULL)
free(stats_exceptions);
*count = 0;
return NULL;
}
*count = size / sizeof(stats_exc_t);
return stats_exceptions;
}
/** Get single exception statistics
*
* @param excn Exception number we are interested in.
*
* @return Pointer to the stats_exc_t structure.
* If non-NULL then it should be eventually freed
* by free().
*
*/
stats_exc_t *stats_get_exception(unsigned int excn)
{
char name[SYSINFO_STATS_MAX_PATH];
snprintf(name, SYSINFO_STATS_MAX_PATH, "system.exceptions.%u", excn);
size_t size = 0;
stats_exc_t *stats_exception =
(stats_exc_t *) sysinfo_get_data(name, &size);
if (size != sizeof(stats_exc_t)) {
if (stats_exception != NULL)
free(stats_exception);
return NULL;
}
return stats_exception;
}
/** Get system load
*
* @param count Number of load records returned.
*
* @return Array of load records (load_t).
* If non-NULL then it should be eventually freed
* by free().
*
*/
load_t *stats_get_load(size_t *count)
{
size_t size = 0;
load_t *load =
(load_t *) sysinfo_get_data("system.load", &size);
if ((size % sizeof(load_t)) != 0) {
if (load != NULL)
free(load);
*count = 0;
return NULL;
}
*count = size / sizeof(load_t);
return load;
}
/** Print load fixed-point value
*
* Print the load record fixed-point value in decimal
* representation on stdout.
*
* @param upper Load record.
* @param dec_length Number of decimal digits to print.
*
*/
void stats_print_load_fragment(load_t upper, unsigned int dec_length)
{
/* Print the whole part */
printf("%u.", upper / LOAD_UNIT);
load_t rest = (upper % LOAD_UNIT) * 10;
unsigned int i;
for (i = 0; i < dec_length; i++) {
printf("%u", rest / LOAD_UNIT);
rest = (rest % LOAD_UNIT) * 10;
}
}
const char *thread_get_state(state_t state)
{
if (state <= Lingering)
return thread_states[state];
return thread_states[Invalid];
}
/** @}
*/