/*
* Copyright (c) 2001-2020 Mellanox Technologies, Ltd. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* BSD license below:
*
* 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "stats/stats_data_reader.h"
#include "vma/util/vma_stats.h"
#include "vma/sock/sock-redirect.h"
#include "vma/event/event_handler_manager.h"
#define MODULE_NAME "STATS: "
static lock_spin g_lock_mc_info("g_lock_mc_info");
static lock_spin g_lock_skt_inst_arr("g_lock_skt_inst_arr");
static lock_spin g_lock_ring_inst_arr("g_lock_ring_inst_arr");
static lock_spin g_lock_cq_inst_arr("g_lock_cq_inst_arr");
static lock_spin g_lock_bpool_inst_arr("g_lock_bpool_inst_arr");
static lock_spin g_lock_iomux("g_lock_iomux");
static sh_mem_info_t g_sh_mem_info;
static sh_mem_t* g_sh_mem;
static sh_mem_t g_local_sh_mem;
//statistic file
FILE* g_stats_file = NULL;
stats_data_reader* g_p_stats_data_reader = NULL;
// keep writing statistics after a request for "duration" with "interval"
#define STATS_PUBLISH_DURATION (10*1000) // 10 sec
#define STATS_PUBLISH_INTERVAL 500 // 500 msec
#define TIMERS_IN_STATS_PUBLISH_DURATION (STATS_PUBLISH_DURATION/STATS_PUBLISHER_TIMER_PERIOD)
#define TIMERS_IN_STATS_PUBLISH_INTERVAL (STATS_PUBLISH_INTERVAL/STATS_PUBLISHER_TIMER_PERIOD)
bool printed_sock_limit_info = false;
bool printed_ring_limit_info = false;
bool printed_cq_limit_info = false;
bool printed_bpool_limit_info = false;
stats_data_reader::stats_data_reader() : m_timer_handler(NULL), m_lock_data_map("m_lock_data_map")
{
}
#define LOCAL_OBJECT_DATA iter->first
#define SHM_DATA_ADDRESS iter->second.first
#define COPY_SIZE iter->second.second
bool should_write()
{
// initial value that will prevent write to shmem before an explicit request
static int timers_counter = TIMERS_IN_STATS_PUBLISH_DURATION + 1;
static int reader_counter = 0;
int prev_reader_counter = reader_counter;
reader_counter = g_sh_mem->reader_counter;
if (prev_reader_counter != reader_counter) {
timers_counter = 0; // will allow writing without new request for "duration"
return true;
}
if (timers_counter > TIMERS_IN_STATS_PUBLISH_DURATION)
return false; // don't write until we'll see explicit request
++timers_counter;
return (timers_counter % TIMERS_IN_STATS_PUBLISH_INTERVAL == 0); // write once in interval
}
void stats_data_reader::handle_timer_expired(void *ctx)
{
NOT_IN_USE(ctx);
if (!should_write()) {
return;
}
if (g_sh_mem->fd_dump != STATS_FD_STATISTICS_DISABLED) {
if (g_p_event_handler_manager) {
g_p_event_handler_manager->statistics_print(g_sh_mem->fd_dump, g_sh_mem->fd_dump_log_level);
}
g_sh_mem->fd_dump = STATS_FD_STATISTICS_DISABLED;
g_sh_mem->fd_dump_log_level = STATS_FD_STATISTICS_LOG_LEVEL_DEFAULT;
}
stats_read_map_t::iterator iter;
m_lock_data_map.lock();
for (iter = m_data_map.begin(); iter != m_data_map.end(); iter++) {
memcpy(SHM_DATA_ADDRESS, LOCAL_OBJECT_DATA, COPY_SIZE);
}
m_lock_data_map.unlock();
}
void stats_data_reader::register_to_timer()
{
m_timer_handler = g_p_event_handler_manager->register_timer_event(STATS_PUBLISHER_TIMER_PERIOD, g_p_stats_data_reader, PERIODIC_TIMER, 0);
}
void stats_data_reader::add_data_reader(void* local_addr, void* shm_addr, int size)
{
m_lock_data_map.lock();
m_data_map[local_addr] = std::make_pair(shm_addr, size);
m_lock_data_map.unlock();
}
void* stats_data_reader::pop_data_reader(void* local_addr)
{
void* rv = NULL;
m_lock_data_map.lock();
stats_read_map_t::iterator iter = m_data_map.find(local_addr);
if (iter != m_data_map.end()) {//found
rv = SHM_DATA_ADDRESS;
m_data_map.erase(local_addr);
}
m_lock_data_map.unlock();
return rv;
}
void write_version_details_to_shmem(version_info_t* p_ver_info)
{
p_ver_info->vma_lib_maj = VMA_LIBRARY_MAJOR;
p_ver_info->vma_lib_min = VMA_LIBRARY_MINOR;
p_ver_info->vma_lib_rev = VMA_LIBRARY_REVISION;
p_ver_info->vma_lib_rel = VMA_LIBRARY_RELEASE;
}
void vma_shmem_stats_open(vlog_levels_t** p_p_vma_log_level, uint8_t** p_p_vma_log_details)
{
void *buf = NULL;
void *p_shmem = NULL;
int ret;
size_t shmem_size = 0;
mode_t saved_mode;
g_p_stats_data_reader = new stats_data_reader();
BULLSEYE_EXCLUDE_BLOCK_START
if (NULL == g_p_stats_data_reader) {
vlog_printf(VLOG_ERROR,"%s:%d: Can't allocate g_p_stats_data_reader \n", __func__, __LINE__);
goto shmem_error;
}
BULLSEYE_EXCLUDE_BLOCK_END
shmem_size = SHMEM_STATS_SIZE(safe_mce_sys().stats_fd_num_max);
buf = malloc(shmem_size);
if (buf == NULL)
goto shmem_error;
memset(buf, 0, shmem_size);
p_shmem = buf;
if (strlen(safe_mce_sys().stats_shmem_dirname) <= 0)
goto no_shmem;
g_sh_mem_info.filename_sh_stats[0] = '\0';
g_sh_mem_info.p_sh_stats = MAP_FAILED;
ret = snprintf(g_sh_mem_info.filename_sh_stats, sizeof(g_sh_mem_info.filename_sh_stats), "%s/vmastat.%d", safe_mce_sys().stats_shmem_dirname, getpid());
if (!((0 < ret) && (ret < (int)sizeof(g_sh_mem_info.filename_sh_stats)))) {
vlog_printf(VLOG_ERROR, "%s: Could not create file under %s %m\n", __func__, safe_mce_sys().stats_shmem_dirname, errno);
goto no_shmem;
}
saved_mode = umask(0);
g_sh_mem_info.fd_sh_stats = open(g_sh_mem_info.filename_sh_stats, O_CREAT|O_RDWR,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
umask(saved_mode);
BULLSEYE_EXCLUDE_BLOCK_START
if (g_sh_mem_info.fd_sh_stats < 0) {
vlog_printf(VLOG_ERROR, "%s: Could not open %s %m\n", __func__, g_sh_mem_info.filename_sh_stats, errno);
goto no_shmem;
}
BULLSEYE_EXCLUDE_BLOCK_END
ret = write(g_sh_mem_info.fd_sh_stats, buf, shmem_size);
BULLSEYE_EXCLUDE_BLOCK_START
if (ret < 0) {
vlog_printf(VLOG_ERROR, "%s: Could not write to %s - %m\n", __func__, g_sh_mem_info.filename_sh_stats, errno);
goto no_shmem;
}
BULLSEYE_EXCLUDE_BLOCK_END
g_sh_mem_info.p_sh_stats = mmap(0, shmem_size, PROT_WRITE|PROT_READ, MAP_SHARED, g_sh_mem_info.fd_sh_stats, 0);
BULLSEYE_EXCLUDE_BLOCK_START
if (g_sh_mem_info.p_sh_stats == MAP_FAILED) {
vlog_printf(VLOG_ERROR, "%s: MAP_FAILED for %s - %m\n", __func__, g_sh_mem_info.filename_sh_stats);
goto no_shmem;
}
BULLSEYE_EXCLUDE_BLOCK_END
p_shmem = g_sh_mem_info.p_sh_stats;
free(buf);
buf = NULL;
goto success;
no_shmem:
if (g_sh_mem_info.p_sh_stats == MAP_FAILED) {
if (g_sh_mem_info.fd_sh_stats > 0) {
close(g_sh_mem_info.fd_sh_stats);
unlink(g_sh_mem_info.filename_sh_stats);
}
}
g_sh_mem_info.p_sh_stats = 0;
success:
MAP_SH_MEM(g_sh_mem, p_shmem);
write_version_details_to_shmem(&g_sh_mem->ver_info);
memcpy(g_sh_mem->stats_protocol_ver, STATS_PROTOCOL_VER, min(sizeof(g_sh_mem->stats_protocol_ver), sizeof(STATS_PROTOCOL_VER)));
g_sh_mem->max_skt_inst_num = safe_mce_sys().stats_fd_num_max;
g_sh_mem->reader_counter = 0;
__log_dbg("file '%s' fd %d shared memory at %p with %d max blocks\n", g_sh_mem_info.filename_sh_stats, g_sh_mem_info.fd_sh_stats, g_sh_mem_info.p_sh_stats, safe_mce_sys().stats_fd_num_max);
// Update the shmem initial log values
g_sh_mem->log_level = **p_p_vma_log_level;
g_sh_mem->log_details_level = **p_p_vma_log_details;
// Update the shmem with initial fd dump values
g_sh_mem->fd_dump = STATS_FD_STATISTICS_DISABLED;
g_sh_mem->fd_dump_log_level = STATS_FD_STATISTICS_LOG_LEVEL_DEFAULT;
// ReMap internal log level to ShMem area
*p_p_vma_log_level = &g_sh_mem->log_level;
*p_p_vma_log_details = &g_sh_mem->log_details_level;
g_p_stats_data_reader->register_to_timer();
return;
shmem_error:
BULLSEYE_EXCLUDE_BLOCK_START
g_sh_mem_info.fd_sh_stats = -1;
g_sh_mem_info.p_sh_stats = MAP_FAILED;
g_sh_mem = &g_local_sh_mem;
g_sh_mem->reset();
*p_p_vma_log_level = &g_sh_mem->log_level;
*p_p_vma_log_details = &g_sh_mem->log_details_level;
BULLSEYE_EXCLUDE_BLOCK_END
}
void vma_shmem_stats_close()
{
if (g_sh_mem_info.p_sh_stats && g_sh_mem_info.p_sh_stats != MAP_FAILED) {
__log_dbg("file '%s' fd %d shared memory at %p with %d max blocks\n", g_sh_mem_info.filename_sh_stats, g_sh_mem_info.fd_sh_stats, g_sh_mem_info.p_sh_stats, safe_mce_sys().stats_fd_num_max);
BULLSEYE_EXCLUDE_BLOCK_START
if (munmap(g_sh_mem_info.p_sh_stats, SHMEM_STATS_SIZE(safe_mce_sys().stats_fd_num_max)) != 0) {
vlog_printf(VLOG_ERROR, "%s: file [%s] fd [%d] error while unmap shared memory at [%p]\n", __func__, g_sh_mem_info.filename_sh_stats, g_sh_mem_info.fd_sh_stats, g_sh_mem_info.p_sh_stats);
}
BULLSEYE_EXCLUDE_BLOCK_END
g_sh_mem_info.p_sh_stats = MAP_FAILED;
if (g_sh_mem_info.fd_sh_stats)
close(g_sh_mem_info.fd_sh_stats);
if(!g_is_forked_child)
unlink(g_sh_mem_info.filename_sh_stats);
} else if (g_sh_mem_info.p_sh_stats != MAP_FAILED) {
free(g_sh_mem);
}
g_sh_mem = NULL;
g_p_vlogger_level = NULL;
g_p_vlogger_details = NULL;
delete g_p_stats_data_reader;
g_p_stats_data_reader = NULL;
}
void vma_stats_instance_create_socket_block(socket_stats_t* local_stats_addr)
{
socket_stats_t* p_skt_stats = NULL;
g_lock_skt_inst_arr.lock();
//search the first free sh_mem block
for (uint32_t i = 0; i < g_sh_mem->max_skt_inst_num; i++) {
if (g_sh_mem->skt_inst_arr[i].b_enabled == false) {
// found free slot ,enabled and returning to the user
p_skt_stats = &g_sh_mem->skt_inst_arr[i].skt_stats;
g_sh_mem->skt_inst_arr[i].b_enabled = true;
goto out;
}
}
if (g_sh_mem->max_skt_inst_num + 1 < safe_mce_sys().stats_fd_num_max) {
// allocate next sh_mem block
p_skt_stats = &g_sh_mem->skt_inst_arr[g_sh_mem->max_skt_inst_num].skt_stats;
g_sh_mem->skt_inst_arr[g_sh_mem->max_skt_inst_num].b_enabled = true;
g_sh_mem->max_skt_inst_num++;
goto out;
}
else {
if (!printed_sock_limit_info) {
printed_sock_limit_info = true;
vlog_printf(VLOG_INFO, "VMA Statistics can monitor up to %d sockets - increase VMA_STATS_FD_NUM\n", safe_mce_sys().stats_fd_num_max);
}
goto out;
}
out:
if (p_skt_stats) {
p_skt_stats->reset();
g_p_stats_data_reader->add_data_reader(local_stats_addr, p_skt_stats, sizeof(socket_stats_t));
}
g_lock_skt_inst_arr.unlock();
}
void vma_stats_instance_remove_socket_block(socket_stats_t* local_addr)
{
g_lock_skt_inst_arr.lock();
print_full_stats(local_addr, NULL, g_stats_file);
socket_stats_t* p_skt_stats = (socket_stats_t*)g_p_stats_data_reader->pop_data_reader(local_addr);
if (p_skt_stats == NULL) {
__log_dbg("application vma_stats pointer is NULL\n");
g_lock_skt_inst_arr.unlock();
return;
}
//coverity - g_sh_mem->skt_inst_arr cannot be null
/*BULLSEYE_EXCLUDE_BLOCK_START
if (g_sh_mem->skt_inst_arr == NULL) {
vlog_printf(VLOG_ERROR,"%s:%d: g_sh_mem->instances_arr not init\n", __func__, __LINE__);
g_lock_skt_stats.unlock();
return;
}
BULLSEYE_EXCLUDE_BLOCK_END*/
// Search sh_mem block to release
for (uint32_t i = 0; i < g_sh_mem->max_skt_inst_num; i++) {
if (&g_sh_mem->skt_inst_arr[i].skt_stats == p_skt_stats) {
g_sh_mem->skt_inst_arr[i].b_enabled = false;
g_lock_skt_inst_arr.unlock();
return;
}
}
vlog_printf(VLOG_ERROR, "%s:%d: Could not find user pointer (%p)\n", __func__, __LINE__, p_skt_stats);
g_lock_skt_inst_arr.unlock();
}
void vma_stats_mc_group_add(in_addr_t mc_grp, socket_stats_t* p_socket_stats)
{
int empty_entry = -1;
int index_to_insert = -1;
g_lock_mc_info.lock();
for (int grp_idx = 0; grp_idx < g_sh_mem->mc_info.max_grp_num && index_to_insert == -1; grp_idx++) {
if (g_sh_mem->mc_info.mc_grp_tbl[grp_idx].sock_num == 0 && empty_entry == -1)
empty_entry = grp_idx;
else if (g_sh_mem->mc_info.mc_grp_tbl[grp_idx].sock_num && g_sh_mem->mc_info.mc_grp_tbl[grp_idx].mc_grp == mc_grp)
index_to_insert = grp_idx;
}
if (index_to_insert == -1 && empty_entry != -1)
index_to_insert = empty_entry;
else if (index_to_insert == -1 && g_sh_mem->mc_info.max_grp_num < MC_TABLE_SIZE) {
index_to_insert = g_sh_mem->mc_info.max_grp_num;
g_sh_mem->mc_info.mc_grp_tbl[index_to_insert].mc_grp = mc_grp;
g_sh_mem->mc_info.max_grp_num++;
}
if (index_to_insert != -1) {
g_sh_mem->mc_info.mc_grp_tbl[index_to_insert].sock_num++;
p_socket_stats->mc_grp_map.set((size_t)index_to_insert, 1);
}
g_lock_mc_info.unlock();
if (index_to_insert == -1)
vlog_printf(VLOG_INFO, "VMA Statistics can monitor up to %d mc groups\n", MC_TABLE_SIZE);
}
void vma_stats_mc_group_remove(in_addr_t mc_grp, socket_stats_t* p_socket_stats)
{
g_lock_mc_info.lock();
for (int grp_idx = 0; grp_idx < g_sh_mem->mc_info.max_grp_num; grp_idx++) {
if (g_sh_mem->mc_info.mc_grp_tbl[grp_idx].sock_num && g_sh_mem->mc_info.mc_grp_tbl[grp_idx].mc_grp == mc_grp) {
p_socket_stats->mc_grp_map.set((size_t)grp_idx, 0);
g_sh_mem->mc_info.mc_grp_tbl[grp_idx].sock_num--;
if (!g_sh_mem->mc_info.mc_grp_tbl[grp_idx].sock_num)
g_sh_mem->mc_info.max_grp_num--;
}
}
g_lock_mc_info.unlock();
}
void vma_stats_instance_create_ring_block(ring_stats_t* local_stats_addr)
{
ring_stats_t* p_instance_ring = NULL;
g_lock_ring_inst_arr.lock();
for (int i=0; i < NUM_OF_SUPPORTED_RINGS; i++) {
if (!g_sh_mem->ring_inst_arr[i].b_enabled) {
g_sh_mem->ring_inst_arr[i].b_enabled = true;
p_instance_ring = &g_sh_mem->ring_inst_arr[i].ring_stats;
memset(p_instance_ring, 0, sizeof(*p_instance_ring));
break;
}
}
if (p_instance_ring == NULL) {
if (!printed_ring_limit_info) {
printed_ring_limit_info = true;
vlog_printf(VLOG_INFO, "VMA Statistics can monitor up to %d ring elements\n", NUM_OF_SUPPORTED_RINGS);
}
}
else {
g_p_stats_data_reader->add_data_reader(local_stats_addr, p_instance_ring, sizeof(ring_stats_t));
__log_dbg("Added ring local=%p shm=%p\n", local_stats_addr, p_instance_ring);
}
g_lock_ring_inst_arr.unlock();
}
void vma_stats_instance_remove_ring_block(ring_stats_t* local_stats_addr)
{
g_lock_ring_inst_arr.lock();
__log_dbg("Remove ring local=%p\n", local_stats_addr);
ring_stats_t* p_ring_stats = (ring_stats_t*)g_p_stats_data_reader->pop_data_reader(local_stats_addr);
if (p_ring_stats == NULL) { // happens on the tx cq (why don't we keep tx cq stats?)
__log_dbg("application vma_stats pointer is NULL\n");
g_lock_ring_inst_arr.unlock();
return;
}
//coverity - g_sh_mem->ring_inst_arr cannot be null
/*BULLSEYE_EXCLUDE_BLOCK_START
if (g_sh_mem->ring_inst_arr == NULL) {
vlog_printf(VLOG_ERROR,"%s:%d: g_sh_mem->instances_arr not init\n", __func__, __LINE__);
g_lock_skt_stats.unlock();
return;
}
BULLSEYE_EXCLUDE_BLOCK_END*/
// Search sh_mem block to release
for (int i=0; i<NUM_OF_SUPPORTED_RINGS; i++) {
if (&g_sh_mem->ring_inst_arr[i].ring_stats == p_ring_stats) {
g_sh_mem->ring_inst_arr[i].b_enabled = false;
g_lock_ring_inst_arr.unlock();
return;
}
}
vlog_printf(VLOG_ERROR, "%s:%d: Could not find user pointer (%p)", __func__, __LINE__, p_ring_stats);
g_lock_ring_inst_arr.unlock();
}
void vma_stats_instance_create_cq_block(cq_stats_t* local_stats_addr)
{
cq_stats_t* p_instance_cq = NULL;
g_lock_cq_inst_arr.lock();
for (int i=0; i < NUM_OF_SUPPORTED_CQS; i++) {
if (!g_sh_mem->cq_inst_arr[i].b_enabled) {
g_sh_mem->cq_inst_arr[i].b_enabled = true;
p_instance_cq = &g_sh_mem->cq_inst_arr[i].cq_stats;
memset(p_instance_cq, 0, sizeof(*p_instance_cq));
break;
}
}
if (p_instance_cq == NULL) {
if (!printed_cq_limit_info) {
printed_cq_limit_info = true;
vlog_printf(VLOG_INFO, "VMA Statistics can monitor up to %d cq elements\n", NUM_OF_SUPPORTED_CQS);
}
}
else {
g_p_stats_data_reader->add_data_reader(local_stats_addr, p_instance_cq, sizeof(cq_stats_t));
__log_dbg("Added cq local=%p shm=%p\n", local_stats_addr, p_instance_cq);
}
g_lock_cq_inst_arr.unlock();
}
void vma_stats_instance_remove_cq_block(cq_stats_t* local_stats_addr)
{
g_lock_cq_inst_arr.lock();
__log_dbg("Remove cq local=%p\n", local_stats_addr);
cq_stats_t* p_cq_stats = (cq_stats_t*)g_p_stats_data_reader->pop_data_reader(local_stats_addr);
if (p_cq_stats == NULL) { // happens on the tx cq (why don't we keep tx cq stats?)
__log_dbg("application vma_stats pointer is NULL\n");
g_lock_cq_inst_arr.unlock();
return;
}
//coverity - g_sh_mem->cq_inst_arr cannot be null
/*BULLSEYE_EXCLUDE_BLOCK_START
if (g_sh_mem->cq_inst_arr == NULL) {
vlog_printf(VLOG_ERROR,"%s:%d: g_sh_mem->instances_arr not init\n", __func__, __LINE__);
g_lock_skt_stats.unlock();
return;
}
BULLSEYE_EXCLUDE_BLOCK_END*/
// Search sh_mem block to release
for (int i=0; i<NUM_OF_SUPPORTED_CQS; i++) {
if (&g_sh_mem->cq_inst_arr[i].cq_stats == p_cq_stats) {
g_sh_mem->cq_inst_arr[i].b_enabled = false;
g_lock_cq_inst_arr.unlock();
return;
}
}
vlog_printf(VLOG_ERROR, "%s:%d: Could not find user pointer (%p)", __func__, __LINE__, p_cq_stats);
g_lock_cq_inst_arr.unlock();
}
void vma_stats_instance_create_bpool_block(bpool_stats_t* local_stats_addr)
{
bpool_stats_t* p_instance_bpool = NULL;
g_lock_bpool_inst_arr.lock();
for (int i=0; i < NUM_OF_SUPPORTED_BPOOLS; i++) {
if (!g_sh_mem->bpool_inst_arr[i].b_enabled) {
g_sh_mem->bpool_inst_arr[i].b_enabled = true;
p_instance_bpool = &g_sh_mem->bpool_inst_arr[i].bpool_stats;
memset(p_instance_bpool, 0, sizeof(bpool_stats_t));
break;
}
}
if (p_instance_bpool == NULL) {
if (!printed_bpool_limit_info) {
printed_bpool_limit_info = true;
vlog_printf(VLOG_INFO, "VMA Statistics can monitor up to %d buffer pools\n", NUM_OF_SUPPORTED_BPOOLS);
}
}
else {
g_p_stats_data_reader->add_data_reader(local_stats_addr, p_instance_bpool, sizeof(bpool_stats_t));
__log_dbg("Added bpool local=%p shm=%p\n", local_stats_addr, p_instance_bpool);
}
g_lock_bpool_inst_arr.unlock();
}
void vma_stats_instance_remove_bpool_block(bpool_stats_t* local_stats_addr)
{
g_lock_bpool_inst_arr.lock();
__log_dbg("Remove bpool local=%p\n", local_stats_addr);
bpool_stats_t* p_bpool_stats = (bpool_stats_t*)g_p_stats_data_reader->pop_data_reader(local_stats_addr);
if (p_bpool_stats == NULL) {
__log_dbg("application vma_stats pointer is NULL\n");
g_lock_bpool_inst_arr.unlock();
return;
}
// Search sh_mem block to release
for (int i=0; i<NUM_OF_SUPPORTED_BPOOLS; i++) {
if (&g_sh_mem->bpool_inst_arr[i].bpool_stats == p_bpool_stats) {
g_sh_mem->bpool_inst_arr[i].b_enabled = false;
g_lock_bpool_inst_arr.unlock();
return;
}
}
vlog_printf(VLOG_ERROR, "%s:%d: Could not find user pointer (%p)", __func__, __LINE__, p_bpool_stats);
g_lock_bpool_inst_arr.unlock();
}
void vma_stats_instance_get_poll_block(iomux_func_stats_t* local_stats_addr)
{
g_p_stats_data_reader->add_data_reader(local_stats_addr, &g_sh_mem->iomux.poll, sizeof(iomux_func_stats_t));
}
void vma_stats_instance_get_select_block(iomux_func_stats_t* local_stats_addr)
{
g_p_stats_data_reader->add_data_reader(local_stats_addr, &g_sh_mem->iomux.select, sizeof(iomux_func_stats_t));
}
void vma_stats_instance_create_epoll_block(int fd, iomux_func_stats_t* local_stats_addr)
{
g_lock_iomux.lock();
for (unsigned i = 0; i < NUM_OF_SUPPORTED_EPFDS; ++i) {
epoll_stats_t* ep_stats = &g_sh_mem->iomux.epoll[i];
if (!ep_stats->enabled) {
ep_stats->enabled = true;
ep_stats->epfd = fd;
g_p_stats_data_reader->add_data_reader(local_stats_addr, &ep_stats->stats, sizeof(iomux_func_stats_t));
g_lock_iomux.unlock();
return;
}
}
vlog_printf(VLOG_INFO, "VMA Statistics can monitor up to %d epoll fds", NUM_OF_SUPPORTED_EPFDS);
g_lock_iomux.unlock();
return;
}
void vma_stats_instance_remove_epoll_block(iomux_func_stats_t* local_stats_addr)
{
g_lock_iomux.lock();
iomux_func_stats_t* ep_func_stats = (iomux_func_stats_t*)g_p_stats_data_reader->pop_data_reader(local_stats_addr);
if (NULL == ep_func_stats) {
__log_dbg("application vma_stats pointer is NULL\n");
g_lock_iomux.unlock();
return;
}
// Search ep_mem block to release
for (int i=0; i<NUM_OF_SUPPORTED_EPFDS; i++) {
if (&g_sh_mem->iomux.epoll[i].stats == ep_func_stats) {
g_sh_mem->iomux.epoll[i].enabled = false;
g_lock_iomux.unlock();
return;
}
}
vlog_printf(VLOG_ERROR, "%s:%d: Could not find user pointer (%p)", __func__, __LINE__, ep_func_stats);
g_lock_iomux.unlock();
return;
}