Commit 3d4d85a8 authored by winckel's avatar winckel

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
parent 91287abe
/******************************************************************************* /*******************************************************************************
* *
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 @@ ...@@ -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; ...@@ -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 { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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_ ...@@ -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 ...@@ -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 ...@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment