Removed dynamic memory allocation from this module to reduce real time inpact.
Replaced use of liblfds611 by a simple data FIFO. git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4738 818b1a75-f10b-46b9-bf7c-635c3b92a50f
This commit is contained in:
@@ -1,30 +1,30 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
*
|
*
|
||||||
E *urecom OpenAirInterface
|
* Eurecom OpenAirInterface 1
|
||||||
Copyright(c) 1999 - 2011 Eurecom
|
* Copyright(c) 1999 - 2012 Eurecom
|
||||||
|
*
|
||||||
This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
version 2, as published by the Free Software Foundation.
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
This program is distributed in the hope it will be useful, but WITHOUT
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
more details.
|
* more details.
|
||||||
|
*
|
||||||
You should have received a copy of the GNU General Public License along with
|
* You should have received a copy of the GNU General Public License along with
|
||||||
this program; if not, write to the Free Software Foundation, Inc.,
|
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
The full GNU General Public License is included in this distribution in
|
* The full GNU General Public License is included in this distribution in
|
||||||
the file called "COPYING".
|
* the file called "COPYING".
|
||||||
|
*
|
||||||
Contact Information
|
* Contact Information
|
||||||
Openair Admin: openair_admin@eurecom.fr
|
* Openair Admin: openair_admin@eurecom.fr
|
||||||
Openair Tech : openair_tech@eurecom.fr
|
* Openair Tech : openair_tech@eurecom.fr
|
||||||
Forums : http://forums.eurecom.fsr/openairinterface
|
* Forums : http://forums.eurecom.fsr/openairinterface
|
||||||
Address : Eurecom, 2229, route des crêtes, 06560 Valbonne Sophia Antipolis, France
|
* Address : Eurecom, 2229, route des crêtes, 06560 Valbonne Sophia Antipolis, France
|
||||||
|
*
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
/*! \file vcd_signal_dumper.c
|
/*! \file vcd_signal_dumper.c
|
||||||
@@ -51,10 +51,8 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "assertions.h"
|
||||||
#include "signals.h"
|
#include "signals.h"
|
||||||
#if defined(ENABLE_VCD_FIFO)
|
|
||||||
# include "liblfds611.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "vcd_signal_dumper.h"
|
#include "vcd_signal_dumper.h"
|
||||||
|
|
||||||
@@ -189,17 +187,20 @@ RTIME start;
|
|||||||
|
|
||||||
#if defined(ENABLE_VCD_FIFO)
|
#if defined(ENABLE_VCD_FIFO)
|
||||||
|
|
||||||
# define VCD_STACK_NB_ELEMENTS (2 * 1024 * 1024)
|
# define VCD_POLL_DELAY (500) // Poll delay in micro-seconds
|
||||||
|
# define VCD_MAX_WAIT_DELAY (200 * 1000) // Maximum data ready wait delay in micro-seconds
|
||||||
|
# define VCD_FIFO_NB_ELEMENTS (1 << 20) // Must be a power of 2
|
||||||
|
# define VCD_FIFO_MASK (VCD_FIFO_NB_ELEMENTS - 1)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct vcd_queue_user_data_s {
|
||||||
uint32_t log_id;
|
uint32_t log_id;
|
||||||
vcd_signal_dumper_modules module;
|
vcd_signal_dumper_modules module;
|
||||||
union {
|
union data_u {
|
||||||
struct {
|
struct function_s {
|
||||||
vcd_signal_dump_functions function_name;
|
vcd_signal_dump_functions function_name;
|
||||||
vcd_signal_dump_in_out in_out;
|
vcd_signal_dump_in_out in_out;
|
||||||
} function;
|
} function;
|
||||||
struct {
|
struct variable_s {
|
||||||
vcd_signal_dump_variables variable_name;
|
vcd_signal_dump_variables variable_name;
|
||||||
unsigned long value;
|
unsigned long value;
|
||||||
} variable;
|
} variable;
|
||||||
@@ -208,7 +209,15 @@ typedef struct {
|
|||||||
long long unsigned int time;
|
long long unsigned int time;
|
||||||
} vcd_queue_user_data_t;
|
} vcd_queue_user_data_t;
|
||||||
|
|
||||||
struct lfds611_queue_state *vcd_queue = NULL;
|
typedef struct vcd_fifo_s {
|
||||||
|
vcd_queue_user_data_t user_data[VCD_FIFO_NB_ELEMENTS];
|
||||||
|
|
||||||
|
volatile uint32_t write_index;
|
||||||
|
volatile uint32_t read_index;
|
||||||
|
} vcd_fifo_t;
|
||||||
|
|
||||||
|
vcd_fifo_t vcd_fifo;
|
||||||
|
|
||||||
pthread_t vcd_dumper_thread;
|
pthread_t vcd_dumper_thread;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -267,11 +276,28 @@ static void uint64_to_binary(uint64_t value, char *binary)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(ENABLE_VCD_FIFO)
|
#if defined(ENABLE_VCD_FIFO)
|
||||||
|
inline static uint32_t vcd_get_write_index(void)
|
||||||
|
{
|
||||||
|
uint32_t write_index;
|
||||||
|
uint32_t read_index;
|
||||||
|
|
||||||
|
/* Get current write index and increment it (atomic operation) */
|
||||||
|
write_index = __sync_fetch_and_add(&vcd_fifo.write_index, 1);
|
||||||
|
/* Wrap index */
|
||||||
|
write_index &= VCD_FIFO_MASK;
|
||||||
|
|
||||||
|
/* Check FIFO overflow */
|
||||||
|
DevCheck((read_index = vcd_fifo.read_index, ((write_index + 1) & VCD_FIFO_MASK) != read_index), write_index, read_index, 0);
|
||||||
|
|
||||||
|
return write_index;
|
||||||
|
}
|
||||||
|
|
||||||
void *vcd_dumper_thread_rt(void *args)
|
void *vcd_dumper_thread_rt(void *args)
|
||||||
{
|
{
|
||||||
vcd_queue_user_data_t *data;
|
vcd_queue_user_data_t *data;
|
||||||
char binary_string[(sizeof (uint64_t) * BYTE_SIZE) + 1];
|
char binary_string[(sizeof (uint64_t) * BYTE_SIZE) + 1];
|
||||||
struct sched_param sched_param;
|
struct sched_param sched_param;
|
||||||
|
uint32_t data_ready_wait;
|
||||||
|
|
||||||
# if defined(ENABLE_ITTI)
|
# if defined(ENABLE_ITTI)
|
||||||
signal_mask();
|
signal_mask();
|
||||||
@@ -281,10 +307,20 @@ void *vcd_dumper_thread_rt(void *args)
|
|||||||
sched_setscheduler(0, SCHED_FIFO, &sched_param);
|
sched_setscheduler(0, SCHED_FIFO, &sched_param);
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
if (lfds611_queue_dequeue(vcd_queue, (void **) &data) == 0) {
|
if (vcd_fifo.read_index == (vcd_fifo.write_index & VCD_FIFO_MASK)) {
|
||||||
/* No element -> sleep a while */
|
/* No element -> sleep a while */
|
||||||
usleep(500);
|
usleep(VCD_POLL_DELAY);
|
||||||
} else {
|
} else {
|
||||||
|
data = &vcd_fifo.user_data[vcd_fifo.read_index];
|
||||||
|
data_ready_wait = 0;
|
||||||
|
while (data->module == VCD_SIGNAL_DUMPER_MODULE_FREE)
|
||||||
|
{
|
||||||
|
DevCheck(data_ready_wait < VCD_MAX_WAIT_DELAY, data_ready_wait, VCD_MAX_WAIT_DELAY, 0);
|
||||||
|
|
||||||
|
/* data is not yet ready, wait for it to be completed */
|
||||||
|
data_ready_wait += VCD_POLL_DELAY;
|
||||||
|
usleep(VCD_POLL_DELAY);
|
||||||
|
}
|
||||||
switch (data->module) {
|
switch (data->module) {
|
||||||
case VCD_SIGNAL_DUMPER_MODULE_VARIABLES:
|
case VCD_SIGNAL_DUMPER_MODULE_VARIABLES:
|
||||||
if (vcd_fd != NULL)
|
if (vcd_fd != NULL)
|
||||||
@@ -298,6 +334,7 @@ void *vcd_dumper_thread_rt(void *args)
|
|||||||
eurecomVariablesNames[variable_name]);
|
eurecomVariablesNames[variable_name]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VCD_SIGNAL_DUMPER_MODULE_FUNCTIONS:
|
case VCD_SIGNAL_DUMPER_MODULE_FUNCTIONS:
|
||||||
if (vcd_fd != NULL)
|
if (vcd_fd != NULL)
|
||||||
{
|
{
|
||||||
@@ -315,10 +352,13 @@ void *vcd_dumper_thread_rt(void *args)
|
|||||||
fflush(vcd_fd);
|
fflush(vcd_fd);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
DevParam(data->module, 0, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
free(data);
|
data->module = VCD_SIGNAL_DUMPER_MODULE_FREE;
|
||||||
|
vcd_fifo.read_index = (vcd_fifo.read_index + 1) & VCD_FIFO_MASK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -345,14 +385,10 @@ void vcd_signal_dumper_init(char *filename)
|
|||||||
vcd_signal_dumper_create_header();
|
vcd_signal_dumper_create_header();
|
||||||
|
|
||||||
#if defined(ENABLE_VCD_FIFO)
|
#if defined(ENABLE_VCD_FIFO)
|
||||||
fprintf(stderr, "[VCD] Creating new stack for inter-thread\n");
|
vcd_fifo.write_index = 0;
|
||||||
|
vcd_fifo.read_index = 0;
|
||||||
|
|
||||||
/* Creating wait-free stack between OAI and dumper thread */
|
fprintf(stderr, "[VCD] Creating dumper thread\n");
|
||||||
if (lfds611_queue_new(&vcd_queue, VCD_STACK_NB_ELEMENTS) < 0) {
|
|
||||||
fprintf(stderr, "vcd_signal_dumper_init: Failed to create stack\n");
|
|
||||||
ouput_vcd = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pthread_create(&vcd_dumper_thread, NULL, vcd_dumper_thread_rt, NULL) < 0)
|
if (pthread_create(&vcd_dumper_thread, NULL, vcd_dumper_thread_rt, NULL) < 0)
|
||||||
{
|
{
|
||||||
@@ -490,18 +526,15 @@ void vcd_signal_dumper_dump_variable_by_name(vcd_signal_dump_variables variable_
|
|||||||
{
|
{
|
||||||
if (ouput_vcd) {
|
if (ouput_vcd) {
|
||||||
#if defined(ENABLE_VCD_FIFO)
|
#if defined(ENABLE_VCD_FIFO)
|
||||||
vcd_queue_user_data_t *new_data;
|
uint32_t write_index = vcd_get_write_index();
|
||||||
|
|
||||||
assert(variable_name < VCD_SIGNAL_DUMPER_VARIABLES_END);
|
assert(variable_name < VCD_SIGNAL_DUMPER_VARIABLES_END);
|
||||||
assert(variable_name >= 0);
|
assert(variable_name >= 0);
|
||||||
|
|
||||||
new_data = malloc(sizeof(vcd_queue_user_data_t));
|
vcd_fifo.user_data[write_index].time = vcd_get_time();
|
||||||
|
vcd_fifo.user_data[write_index].data.variable.variable_name = variable_name;
|
||||||
new_data->module = VCD_SIGNAL_DUMPER_MODULE_VARIABLES;
|
vcd_fifo.user_data[write_index].data.variable.value = value;
|
||||||
new_data->time = vcd_get_time();
|
vcd_fifo.user_data[write_index].module = VCD_SIGNAL_DUMPER_MODULE_VARIABLES; // Set when all other fields are set to validate the user_data
|
||||||
new_data->data.variable.variable_name = variable_name;
|
|
||||||
new_data->data.variable.value = value;
|
|
||||||
lfds611_queue_enqueue(vcd_queue, new_data);
|
|
||||||
#else
|
#else
|
||||||
char binary_string[(sizeof (uint64_t) * BYTE_SIZE) + 1];
|
char binary_string[(sizeof (uint64_t) * BYTE_SIZE) + 1];
|
||||||
|
|
||||||
@@ -526,18 +559,15 @@ void vcd_signal_dumper_dump_function_by_name(vcd_signal_dump_functions function
|
|||||||
{
|
{
|
||||||
if (ouput_vcd) {
|
if (ouput_vcd) {
|
||||||
#if defined(ENABLE_VCD_FIFO)
|
#if defined(ENABLE_VCD_FIFO)
|
||||||
vcd_queue_user_data_t *new_data;
|
uint32_t write_index = vcd_get_write_index();
|
||||||
|
|
||||||
assert(function_name < VCD_SIGNAL_DUMPER_FUNCTIONS_END);
|
assert(function_name < VCD_SIGNAL_DUMPER_FUNCTIONS_END);
|
||||||
assert(function_name >= 0);
|
assert(function_name >= 0);
|
||||||
|
|
||||||
new_data = malloc(sizeof(vcd_queue_user_data_t));
|
vcd_fifo.user_data[write_index].time = vcd_get_time();
|
||||||
|
vcd_fifo.user_data[write_index].data.function.function_name = function_name;
|
||||||
new_data->module = VCD_SIGNAL_DUMPER_MODULE_FUNCTIONS;
|
vcd_fifo.user_data[write_index].data.function.in_out = in_out;
|
||||||
new_data->time = vcd_get_time();
|
vcd_fifo.user_data[write_index].module = VCD_SIGNAL_DUMPER_MODULE_FUNCTIONS; // Set when all other fields are set to validate the user_data
|
||||||
new_data->data.function.function_name = function_name;
|
|
||||||
new_data->data.function.in_out = in_out;
|
|
||||||
lfds611_queue_enqueue(vcd_queue, new_data);
|
|
||||||
#else
|
#else
|
||||||
assert(function_name < VCD_SIGNAL_DUMPER_FUNCTIONS_END);
|
assert(function_name < VCD_SIGNAL_DUMPER_FUNCTIONS_END);
|
||||||
assert(function_name >= 0);
|
assert(function_name >= 0);
|
||||||
|
|||||||
@@ -146,6 +146,8 @@ typedef enum
|
|||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
|
VCD_SIGNAL_DUMPER_MODULE_FREE = 0,
|
||||||
|
|
||||||
VCD_SIGNAL_DUMPER_MODULE_VARIABLES,
|
VCD_SIGNAL_DUMPER_MODULE_VARIABLES,
|
||||||
VCD_SIGNAL_DUMPER_MODULE_FUNCTIONS,
|
VCD_SIGNAL_DUMPER_MODULE_FUNCTIONS,
|
||||||
// VCD_SIGNAL_DUMPER_MODULE_UE_PROCEDURES_FUNCTIONS,
|
// VCD_SIGNAL_DUMPER_MODULE_UE_PROCEDURES_FUNCTIONS,
|
||||||
|
|||||||
Reference in New Issue
Block a user