Merge remote-tracking branch 'origin/develop' into ru_rau_enhancement-external-timing
This commit is contained in:
+139
-101
@@ -54,7 +54,6 @@
|
||||
|
||||
mapping log_level_names[] = {
|
||||
{"error", OAILOG_ERR},
|
||||
{"file", OAILOG_FILE},
|
||||
{"warn", OAILOG_WARNING},
|
||||
{"info", OAILOG_INFO},
|
||||
{"debug", OAILOG_DEBUG},
|
||||
@@ -70,18 +69,10 @@ mapping log_options[] = {
|
||||
};
|
||||
|
||||
|
||||
mapping log_maskmap[] = {
|
||||
{"prach", DEBUG_PRACH},
|
||||
{"RU", DEBUG_RU},
|
||||
{"LTEESTIM", DEBUG_LTEESTIM},
|
||||
{"ctrlsocket", DEBUG_CTRLSOCKET},
|
||||
{"UE_PHYPROC", DEBUG_UE_PHYPROC},
|
||||
{"UE_TIMING", UE_TIMING},
|
||||
{NULL,-1}
|
||||
};
|
||||
mapping log_maskmap[] = LOG_MASKMAP_INIT;
|
||||
|
||||
char *log_level_highlight_start[] = {LOG_RED, LOG_GREEN, LOG_ORANGE, "", LOG_BLUE, LOG_CYBL}; /*!< \brief Optional start-format strings for highlighting */
|
||||
char *log_level_highlight_end[] = {LOG_RESET,LOG_RESET,LOG_RESET,LOG_RESET, LOG_RESET,LOG_RESET}; /*!< \brief Optional end-format strings for highlighting */
|
||||
char *log_level_highlight_start[] = {LOG_RED, LOG_ORANGE, "", LOG_BLUE, LOG_CYBL}; /*!< \brief Optional start-format strings for highlighting */
|
||||
char *log_level_highlight_end[] = {LOG_RESET,LOG_RESET,LOG_RESET, LOG_RESET,LOG_RESET}; /*!< \brief Optional end-format strings for highlighting */
|
||||
|
||||
|
||||
int write_file_matlab(const char *fname,const char *vname,void *data,int length,int dec,char format)
|
||||
@@ -243,14 +234,14 @@ int write_file_matlab(const char *fname,const char *vname,void *data,int length,
|
||||
/* get log parameters from configuration file */
|
||||
void log_getconfig(log_t *g_log) {
|
||||
char *gloglevel = NULL;
|
||||
int level;
|
||||
int consolelog ;
|
||||
|
||||
|
||||
paramdef_t logparams_defaults[] = LOG_GLOBALPARAMS_DESC;
|
||||
paramdef_t logparams_level[MAX_LOG_PREDEF_COMPONENTS];
|
||||
paramdef_t logparams_logfile[MAX_LOG_PREDEF_COMPONENTS];
|
||||
paramdef_t logparams_debug[sizeof(log_maskmap)/sizeof(mapping)];
|
||||
paramdef_t logparams_matlab[sizeof(log_maskmap)/sizeof(mapping)];
|
||||
paramdef_t logparams_dump[sizeof(log_maskmap)/sizeof(mapping)];
|
||||
|
||||
int ret = config_get( logparams_defaults,sizeof(logparams_defaults)/sizeof(paramdef_t),CONFIG_STRING_LOG_PREFIX);
|
||||
if (ret <0) {
|
||||
@@ -258,6 +249,7 @@ void log_getconfig(log_t *g_log) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* set LOG display options (enable/disable color, thread name, level ) */
|
||||
for(int i=0; i<logparams_defaults[LOG_OPTIONS_IDX].numelt ; i++) {
|
||||
for(int j=0; log_options[j].name != NULL ; j++) {
|
||||
if (strcmp(logparams_defaults[LOG_OPTIONS_IDX].strlistptr[i],log_options[j].name) == 0) {
|
||||
@@ -303,38 +295,40 @@ void log_getconfig(log_t *g_log) {
|
||||
config_get( logparams_logfile, MAX_LOG_PREDEF_COMPONENTS,CONFIG_STRING_LOG_PREFIX);
|
||||
/* now set the log levels and infile option, according to what we read */
|
||||
for (int i=MIN_LOG_COMPONENTS; i < MAX_LOG_PREDEF_COMPONENTS; i++) {
|
||||
level = map_str_to_int(log_level_names, *(logparams_level[i].strptr));
|
||||
set_log(i, level,1);
|
||||
g_log->log_component[i].level = map_str_to_int(log_level_names, *(logparams_level[i].strptr));
|
||||
set_log(i, g_log->log_component[i].level);
|
||||
if (*(logparams_logfile[i].uptr) == 1)
|
||||
set_component_filelog(i);
|
||||
}
|
||||
|
||||
/* build then read the debug and matlab parameter array */
|
||||
/* build then read the debug and dump parameter array */
|
||||
for (int i=0;log_maskmap[i].name != NULL ; i++) {
|
||||
sprintf(logparams_debug[i].optname, LOG_CONFIG_DEBUG_FORMAT, log_maskmap[i].name);
|
||||
sprintf(logparams_matlab[i].optname, LOG_CONFIG_MATLAB_FORMAT, log_maskmap[i].name);
|
||||
sprintf(logparams_debug[i].optname, LOG_CONFIG_DEBUG_FORMAT, log_maskmap[i].name);
|
||||
sprintf(logparams_dump[i].optname, LOG_CONFIG_DUMP_FORMAT, log_maskmap[i].name);
|
||||
logparams_debug[i].defuintval = 0;
|
||||
logparams_debug[i].type = TYPE_UINT;
|
||||
logparams_debug[i].paramflags = PARAMFLAG_BOOL;
|
||||
logparams_debug[i].uptr = NULL;
|
||||
logparams_debug[i].chkPptr = NULL;
|
||||
logparams_debug[i].numelt = 0;
|
||||
logparams_matlab[i].defuintval = 0;
|
||||
logparams_matlab[i].type = TYPE_UINT;
|
||||
logparams_matlab[i].paramflags = PARAMFLAG_BOOL;
|
||||
logparams_matlab[i].uptr = NULL;
|
||||
logparams_matlab[i].chkPptr = NULL;
|
||||
logparams_matlab[i].numelt = 0;
|
||||
logparams_dump[i].defuintval = 0;
|
||||
logparams_dump[i].type = TYPE_UINT;
|
||||
logparams_dump[i].paramflags = PARAMFLAG_BOOL;
|
||||
logparams_dump[i].uptr = NULL;
|
||||
logparams_dump[i].chkPptr = NULL;
|
||||
logparams_dump[i].numelt = 0;
|
||||
}
|
||||
config_get( logparams_debug,(sizeof(log_maskmap)/sizeof(mapping)) - 1 ,CONFIG_STRING_LOG_PREFIX);
|
||||
config_get( logparams_matlab,(sizeof(log_maskmap)/sizeof(mapping)) - 1 ,CONFIG_STRING_LOG_PREFIX);
|
||||
config_get( logparams_dump,(sizeof(log_maskmap)/sizeof(mapping)) - 1 ,CONFIG_STRING_LOG_PREFIX);
|
||||
/* set the debug mask according to the debug parameters values */
|
||||
for (int i=0; log_maskmap[i].name != NULL ; i++) {
|
||||
if (*(logparams_debug[i].uptr) )
|
||||
g_log->debug_mask = g_log->debug_mask | log_maskmap[i].value;
|
||||
if (*(logparams_matlab[i].uptr) )
|
||||
g_log->matlab_mask = g_log->matlab_mask | log_maskmap[i].value;
|
||||
if (*(logparams_dump[i].uptr) )
|
||||
g_log->dump_mask = g_log->dump_mask | log_maskmap[i].value;
|
||||
}
|
||||
/* log globally enabled/disabled */
|
||||
set_glog_onlinelog(consolelog);
|
||||
}
|
||||
|
||||
int register_log_component(char *name, char *fext, int compidx)
|
||||
@@ -354,11 +348,9 @@ int computed_compidx=compidx;
|
||||
}
|
||||
if (computed_compidx >= 0 && computed_compidx <MAX_LOG_COMPONENTS) {
|
||||
g_log->log_component[computed_compidx].name = strdup(name);
|
||||
g_log->log_component[computed_compidx].level = LOG_ERR;
|
||||
g_log->log_component[computed_compidx].interval = 1;
|
||||
g_log->log_component[computed_compidx].stream = NULL;
|
||||
g_log->log_component[computed_compidx].stream = stdout;
|
||||
g_log->log_component[computed_compidx].filelog = 0;
|
||||
g_log->log_component[computed_compidx].filelog_name = malloc(strlen(name)+16);/* /tmp/<name>.%s rounded to ^2 */
|
||||
g_log->log_component[computed_compidx].filelog_name = malloc(strlen(name)+16);/* /tmp/<name>.%s */
|
||||
sprintf(g_log->log_component[computed_compidx].filelog_name,"/tmp/%s.%s",name,fext);
|
||||
} else {
|
||||
fprintf(stderr,"{LOG} %s %d Couldn't register componemt %s\n",__FILE__,__LINE__,name);
|
||||
@@ -418,26 +410,20 @@ int logInit (void)
|
||||
|
||||
|
||||
register_log_component("S1AP","",S1AP);
|
||||
register_log_component("X2AP","",X2AP);
|
||||
|
||||
|
||||
register_log_component("SCTP","",SCTP);
|
||||
register_log_component("RRH","",RRH);
|
||||
|
||||
|
||||
register_log_component("X2AP","",X2AP);
|
||||
register_log_component("LOADER","log",LOADER);
|
||||
register_log_component("ASN","log",ASN);
|
||||
|
||||
|
||||
|
||||
for (int i=0 ; log_level_names[i].name != NULL ; i++)
|
||||
g_log->level2string[i] = toupper(log_level_names[i].name[0]); // uppercased first letter of level name
|
||||
|
||||
g_log->level2string[OAILOG_ERR] = "E"; // ERROR
|
||||
g_log->level2string[OAILOG_WARNING] = "W"; // WARNING
|
||||
g_log->level2string[OAILOG_INFO] = "I"; //INFO
|
||||
g_log->level2string[OAILOG_DEBUG] = "D"; // DEBUG
|
||||
g_log->level2string[OAILOG_FILE] = "F"; // file
|
||||
g_log->level2string[OAILOG_TRACE] = "T"; // TRACE
|
||||
|
||||
|
||||
g_log->onlinelog = 1; //online log file
|
||||
g_log->filelog = 0;
|
||||
|
||||
|
||||
|
||||
@@ -446,19 +432,6 @@ int logInit (void)
|
||||
log_getconfig(g_log);
|
||||
|
||||
|
||||
// could put a loop here to check for all comps
|
||||
for (i=MIN_LOG_COMPONENTS; i < MAX_LOG_COMPONENTS; i++) {
|
||||
if (g_log->log_component[i].filelog == 1 ) {
|
||||
g_log->log_component[i].stream = fopen(g_log->log_component[i].filelog_name,"w");
|
||||
g_log->log_component[i].fwrite = vfprintf;
|
||||
} else if (g_log->log_component[i].filelog == 1 ) {
|
||||
g_log->log_component[i].stream = fopen(g_log->filelog_name,"w");
|
||||
g_log->log_component[i].fwrite = vfprintf;
|
||||
} else if (g_log->onlinelog == 1 ) {
|
||||
g_log->log_component[i].stream = stdout;
|
||||
g_log->log_component[i].fwrite = vfprintf;
|
||||
}
|
||||
}
|
||||
|
||||
// set all unused component items to 0, they are for non predefined components
|
||||
for (i=MAX_LOG_PREDEF_COMPONENTS; i < MAX_LOG_COMPONENTS; i++) {
|
||||
@@ -470,8 +443,6 @@ int logInit (void)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
char *log_getthreadname(char *threadname, int bufsize) {
|
||||
|
||||
int rt = pthread_getname_np(pthread_self(), threadname,bufsize) ;
|
||||
@@ -483,11 +454,20 @@ int rt = pthread_getname_np(pthread_self(), threadname,bufsize) ;
|
||||
}
|
||||
}
|
||||
|
||||
static int log_header(char *log_buffer, int buffsize, int comp, int level,const char *format) {
|
||||
char threadname[PR_SET_NAME];
|
||||
return snprintf(log_buffer, buffsize , "%s%s[%s]%c %s %s%s",
|
||||
log_level_highlight_end[level],
|
||||
( (g_log->flag & FLAG_NOCOLOR)?"":log_level_highlight_start[level]),
|
||||
g_log->log_component[comp].name,
|
||||
( (g_log->flag & FLAG_LEVEL)?g_log->level2string[level]:' '),
|
||||
( (g_log->flag & FLAG_THREAD)?log_getthreadname(threadname,PR_SET_NAME+1):""),
|
||||
format,
|
||||
log_level_highlight_end[level]);
|
||||
}
|
||||
|
||||
void logRecord_mt(const char *file, const char *func, int line, int comp, int level, const char* format, ... )
|
||||
{
|
||||
|
||||
char threadname[PR_SET_NAME];
|
||||
char log_buffer[MAX_LOG_TOTAL];
|
||||
va_list args;
|
||||
|
||||
@@ -496,38 +476,63 @@ void logRecord_mt(const char *file, const char *func, int line, int comp, int le
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
snprintf(log_buffer, MAX_LOG_TOTAL , "%s%s[%s]%s %s %s",
|
||||
log_level_highlight_end[level],
|
||||
( (g_log->flag & FLAG_NOCOLOR)?"":log_level_highlight_start[level]),
|
||||
g_log->log_component[comp].name,
|
||||
( (g_log->flag & FLAG_LEVEL)?g_log->level2string[level]:""),
|
||||
( (g_log->flag & FLAG_THREAD)?log_getthreadname(threadname,PR_SET_NAME+1):""),
|
||||
format);
|
||||
|
||||
g_log->log_component[comp].fwrite(g_log->log_component[comp].stream,log_buffer, args);
|
||||
log_header(log_buffer,MAX_LOG_TOTAL ,comp, level,format);
|
||||
g_log->log_component[comp].vprint(g_log->log_component[comp].stream,log_buffer, args);
|
||||
va_end(args);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void log_dump(int component, void *buffer, int buffsize,int datatype, const char* format, ... ) {
|
||||
va_list args;
|
||||
char *wbuf;
|
||||
|
||||
|
||||
int set_log(int component, int level, int interval)
|
||||
switch(datatype) {
|
||||
case LOG_DUMP_DOUBLE:
|
||||
wbuf=malloc((buffsize * 10) + 64 + MAX_LOG_TOTAL);
|
||||
break;
|
||||
case LOG_DUMP_CHAR:
|
||||
default:
|
||||
wbuf=malloc((buffsize * 3 ) + 64 + MAX_LOG_TOTAL);
|
||||
break;
|
||||
}
|
||||
if (wbuf != NULL) {
|
||||
va_start(args, format);
|
||||
int pos=log_header(wbuf,MAX_LOG_TOTAL ,component, OAILOG_INFO,"");
|
||||
int pos2=vsprintf(wbuf+pos,format, args);
|
||||
pos=pos+pos2;
|
||||
va_end(args);
|
||||
|
||||
for (int i=0; i<buffsize; i++) {
|
||||
switch(datatype) {
|
||||
case LOG_DUMP_DOUBLE:
|
||||
pos = pos + sprintf(wbuf+pos,"%04.4lf ", (double)((double *)buffer)[i]);
|
||||
break;
|
||||
case LOG_DUMP_CHAR:
|
||||
default:
|
||||
pos = pos + sprintf(wbuf+pos,"%02x ", (unsigned char)((unsigned char *)buffer)[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
sprintf(wbuf+pos,"\n");
|
||||
g_log->log_component[component].print(g_log->log_component[component].stream,wbuf);
|
||||
free(wbuf);
|
||||
}
|
||||
}
|
||||
|
||||
int set_log(int component, int level)
|
||||
{
|
||||
/* Checking parameters */
|
||||
DevCheck((component >= MIN_LOG_COMPONENTS) && (component < MAX_LOG_COMPONENTS),
|
||||
component, MIN_LOG_COMPONENTS, MAX_LOG_COMPONENTS);
|
||||
DevCheck((level < NUM_LOG_LEVEL) && (level >= OAILOG_ERR), level, NUM_LOG_LEVEL,
|
||||
DevCheck((level < NUM_LOG_LEVEL) && (level >= OAILOG_DISABLE), level, NUM_LOG_LEVEL,
|
||||
OAILOG_ERR);
|
||||
DevCheck((interval >= 0) && (interval <= 0xFF), interval, 0, 0xFF);
|
||||
|
||||
if ( g_log->log_component[component].level != OAILOG_DISABLE )
|
||||
g_log->log_component[component].savedlevel = g_log->log_component[component].level;
|
||||
g_log->log_component[component].level = level;
|
||||
|
||||
|
||||
g_log->log_component[component].interval = interval;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -536,32 +541,67 @@ int set_log(int component, int level, int interval)
|
||||
void set_glog(int level)
|
||||
{
|
||||
for (int c=0; c< MAX_LOG_COMPONENTS; c++ ) {
|
||||
g_log->log_component[c].level = level;
|
||||
set_log(c, level);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void set_glog_onlinelog(int enable)
|
||||
{
|
||||
g_log->onlinelog = enable;
|
||||
for (int c=0; c< MAX_LOG_COMPONENTS; c++ ) {
|
||||
if ( enable ) {
|
||||
g_log->log_component[c].level = g_log->log_component[c].savedlevel;
|
||||
g_log->log_component[c].vprint = vfprintf;
|
||||
g_log->log_component[c].print = fprintf;
|
||||
g_log->log_component[c].stream = stdout;
|
||||
} else {
|
||||
g_log->log_component[c].level = OAILOG_DISABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
void set_glog_filelog(int enable)
|
||||
{
|
||||
g_log->filelog = enable;
|
||||
static FILE *fptr;
|
||||
|
||||
if ( enable ) {
|
||||
fptr = fopen(g_log->filelog_name,"w");
|
||||
|
||||
for (int c=0; c< MAX_LOG_COMPONENTS; c++ ) {
|
||||
close_component_filelog(c);
|
||||
g_log->log_component[c].stream = fptr;
|
||||
g_log->log_component[c].filelog = 1;
|
||||
}
|
||||
} else {
|
||||
for (int c=0; c< MAX_LOG_COMPONENTS; c++ ) {
|
||||
g_log->log_component[c].filelog = 0;
|
||||
if (fptr != NULL) {
|
||||
fclose(fptr);
|
||||
}
|
||||
g_log->log_component[c].stream = stdout;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void set_component_filelog(int comp)
|
||||
{
|
||||
if (g_log->log_component[comp].filelog == 0) {
|
||||
g_log->log_component[comp].filelog = 1;
|
||||
|
||||
if (g_log->log_component[comp].stream == NULL) {
|
||||
if (g_log->log_component[comp].stream == NULL || g_log->log_component[comp].stream == stdout) {
|
||||
g_log->log_component[comp].stream = fopen(g_log->log_component[comp].filelog_name,"w");
|
||||
}
|
||||
}
|
||||
g_log->log_component[comp].vprint = vfprintf;
|
||||
g_log->log_component[comp].print = fprintf;
|
||||
g_log->log_component[comp].filelog = 1;
|
||||
}
|
||||
void close_component_filelog(int comp)
|
||||
{
|
||||
g_log->log_component[comp].filelog = 0;
|
||||
if (g_log->log_component[comp].stream != NULL && g_log->log_component[comp].stream != stdout ) {
|
||||
fclose(g_log->log_component[comp].stream);
|
||||
g_log->log_component[comp].stream = stdout;
|
||||
}
|
||||
g_log->log_component[comp].vprint = vfprintf;
|
||||
g_log->log_component[comp].print = fprintf;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* for the two functions below, the passed array must have a final entry
|
||||
@@ -616,15 +656,13 @@ int is_newline( char *str, int size)
|
||||
void logClean (void)
|
||||
{
|
||||
int i;
|
||||
LOG_I(PHY,"\n");
|
||||
LOG_UI(PHY,"\n");
|
||||
|
||||
|
||||
|
||||
|
||||
for (i=MIN_LOG_COMPONENTS; i < MAX_LOG_COMPONENTS; i++) {
|
||||
if (g_log->log_component[i].stream != NULL) {
|
||||
fclose(g_log->log_component[i].stream);
|
||||
}
|
||||
close_component_filelog(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -650,8 +688,8 @@ int test_log(void)
|
||||
LOG_D(MAC, "1 debug MAC \n");
|
||||
LOG_W(MAC, "1 warning MAC \n");
|
||||
|
||||
set_log(EMU, OAILOG_INFO, FLAG_ONLINE);
|
||||
set_log(MAC, OAILOG_WARNING, 0);
|
||||
set_log(EMU, OAILOG_INFO);
|
||||
set_log(MAC, OAILOG_WARNING);
|
||||
|
||||
LOG_I(EMU, "2 Starting OAI logs version %s Build date: %s on %s\n",
|
||||
BUILD_VERSION, BUILD_DATE, BUILD_HOST);
|
||||
@@ -661,7 +699,7 @@ int test_log(void)
|
||||
LOG_I(MAC, "2 info MAC \n");
|
||||
|
||||
|
||||
set_log(MAC, OAILOG_NOTICE, 1);
|
||||
set_log(MAC, OAILOG_NOTICE);
|
||||
|
||||
LOG_ENTER(MAC);
|
||||
LOG_I(EMU, "3 Starting OAI logs version %s Build date: %s on %s\n",
|
||||
@@ -670,8 +708,8 @@ int test_log(void)
|
||||
LOG_W(MAC, "3 warning MAC \n");
|
||||
LOG_I(MAC, "3 info MAC \n");
|
||||
|
||||
set_log(MAC, LOG_DEBUG,1);
|
||||
set_log(EMU, LOG_DEBUG,1);
|
||||
set_log(MAC, LOG_DEBUG);
|
||||
set_log(EMU, LOG_DEBUG);
|
||||
|
||||
LOG_ENTER(MAC);
|
||||
LOG_I(EMU, "4 Starting OAI logs version %s Build date: %s on %s\n",
|
||||
@@ -681,8 +719,8 @@ int test_log(void)
|
||||
LOG_I(MAC, "4 info MAC \n");
|
||||
|
||||
|
||||
set_log(MAC, LOG_DEBUG,0);
|
||||
set_log(EMU, LOG_DEBUG,0);
|
||||
set_log(MAC, LOG_DEBUG);
|
||||
set_log(EMU, LOG_DEBUG);
|
||||
|
||||
LOG_I(LOG, "5 Starting OAI logs version %s Build date: %s on %s\n",
|
||||
BUILD_VERSION, BUILD_DATE, BUILD_HOST);
|
||||
@@ -691,8 +729,8 @@ int test_log(void)
|
||||
LOG_I(MAC, "5 info MAC \n");
|
||||
|
||||
|
||||
set_log(MAC, LOG_TRACE,0X07F);
|
||||
set_log(EMU, LOG_TRACE,0X07F);
|
||||
set_log(MAC, LOG_TRACE);
|
||||
set_log(EMU, LOG_TRACE);
|
||||
|
||||
LOG_ENTER(MAC);
|
||||
LOG_I(LOG, "6 Starting OAI logs version %s Build date: %s on %s\n",
|
||||
|
||||
+89
-53
@@ -81,15 +81,14 @@ extern "C" {
|
||||
* @ingroup _macro
|
||||
* @brief LOG defines 9 levels of messages for users. Importance of these levels decrease gradually from 0 to 8
|
||||
* @{*/
|
||||
# define OAILOG_DISABLE -1 /*!< \brief disable all LOG messages, cannot be used in LOG macros, use only in LOG module */
|
||||
# define OAILOG_ERR 0 /*!< \brief critical error conditions, impact on "must have" fuctinalities */
|
||||
# define OAILOG_WARNING 1 /*!< \brief warning conditions, shouldn't happen but doesn't impact "must have" functionalities */
|
||||
# define OAILOG_INFO 2 /*!< \brief informational messages most people don't need, shouldn't impact real-time behavior */
|
||||
# define OAILOG_DEBUG 3 /*!< \brief first level debug-level messages, for developers , may impact real-time behavior */
|
||||
# define OAILOG_TRACE 4 /*!< \brief second level debug-level messages, for developers ,likely impact real-time behavior*/
|
||||
|
||||
# define OAILOG_ERR 0 /*!< \brief critical error conditions, impact on "must have" fuctinalities */
|
||||
# define OAILOG_FILE 1 /*!< \brief important informational messages, but everything OK */
|
||||
# define OAILOG_WARNING 2 /*!< \brief warning conditions, shouldn't happen but doesn't impact "must have" functionalities */
|
||||
# define OAILOG_INFO 3 /*!< \brief informational messages most people don't need, shouldn't impact real-time behavior */
|
||||
# define OAILOG_DEBUG 4 /*!< \brief first level debug-level messages, for developers , may impact real-time behavior */
|
||||
# define OAILOG_TRACE 5 /*!< \brief second level debug-level messages, for developers ,likely impact real-time behavior*/
|
||||
|
||||
#define NUM_LOG_LEVEL 6 /*!< \brief the number of message levels users have with LOG */
|
||||
#define NUM_LOG_LEVEL 5 /*!< \brief the number of message levels users have with LOG (OAILOG_DISABLE is not available to user as a level, so it is not included)*/
|
||||
/* @}*/
|
||||
|
||||
|
||||
@@ -128,21 +127,53 @@ extern "C" {
|
||||
|
||||
/** @defgroup macros to identify a debug entity
|
||||
* @ingroup each macro is a bit mask where the unique bit set identifies an entity to be debugged
|
||||
* it allows to dynamically activate or not blocks of code
|
||||
* it allows to dynamically activate or not blocks of code. The LOG_MASKMAP_INIT macro
|
||||
* is used to map a character string name to each debug bit, it allows to set or clear
|
||||
* the corresponding bit via the defined name, from the configuration or from the telnet
|
||||
* server.
|
||||
* @brief
|
||||
* @{*/
|
||||
#define DEBUG_PRACH (1<<0)
|
||||
#define DEBUG_RU (1<<1)
|
||||
#define DEBUG_UE_PHYPROC (1<<2)
|
||||
#define DEBUG_LTEESTIM (1<<3)
|
||||
#define DEBUG_DLCELLSPEC (1<<4)
|
||||
#define DEBUG_ULSCH (1<<5)
|
||||
#define DEBUG_RRC (1<<6)
|
||||
#define DEBUG_PDCP (1<<7)
|
||||
#define DEBUG_DFT (1<<8)
|
||||
#define DEBUG_ASN1 (1<<9)
|
||||
#define DEBUG_CTRLSOCKET (1<<10)
|
||||
#define DEBUG_SECURITY (1<<11)
|
||||
#define DEBUG_NAS (1<<12)
|
||||
#define UE_TIMING (1<<20)
|
||||
|
||||
#define SET_LOG_DEBUG(O) g_log->debug_mask = (g_log->debug_mask | O)
|
||||
#define CLEAR_LOG_DEBUG(O) g_log->debug_mask = (g_log->debug_mask & (~O))
|
||||
|
||||
#define SET_LOG_MATLAB(O) g_log->matlab_mask = (g_log->matlab_mask | O)
|
||||
#define CLEAR_LOG_MATLAB(O) g_log->matlab_mask = (g_log->matlab_mask & (~O))
|
||||
#define LOG_MASKMAP_INIT {\
|
||||
{"PRACH", DEBUG_PRACH},\
|
||||
{"RU", DEBUG_RU},\
|
||||
{"UE_PHYPROC", DEBUG_UE_PHYPROC},\
|
||||
{"LTEESTIM", DEBUG_LTEESTIM},\
|
||||
{"DLCELLSPEC", DEBUG_DLCELLSPEC},\
|
||||
{"ULSCH", DEBUG_ULSCH},\
|
||||
{"RRC", DEBUG_RRC},\
|
||||
{"PDCP", DEBUG_PDCP},\
|
||||
{"DFT", DEBUG_DFT},\
|
||||
{"ASN1", DEBUG_ASN1},\
|
||||
{"CTRLSOCKET", DEBUG_CTRLSOCKET},\
|
||||
{"SECURITY", DEBUG_SECURITY},\
|
||||
{"NAS", DEBUG_NAS},\
|
||||
{"UE_TIMING", UE_TIMING},\
|
||||
{NULL,-1}\
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define SET_LOG_DEBUG(B) g_log->debug_mask = (g_log->debug_mask | B)
|
||||
#define CLEAR_LOG_DEBUG(B) g_log->debug_mask = (g_log->debug_mask & (~B))
|
||||
|
||||
#define SET_LOG_DUMP(B) g_log->dump_mask = (g_log->dump_mask | B)
|
||||
#define CLEAR_LOG_DUMP(B) g_log->dump_mask = (g_log->dump_mask & (~B))
|
||||
|
||||
|
||||
|
||||
@@ -183,9 +214,9 @@ typedef enum {
|
||||
TMR,
|
||||
USIM,
|
||||
LOCALIZE,
|
||||
RRH,
|
||||
X2AP,
|
||||
LOADER,
|
||||
ASN,
|
||||
MAX_LOG_PREDEF_COMPONENTS,
|
||||
}
|
||||
comp_name_t;
|
||||
@@ -199,17 +230,18 @@ typedef struct {
|
||||
int value; /*!< \brief integer value of mapping */
|
||||
} mapping;
|
||||
|
||||
typedef int(*log_write_func_t)(FILE *stream, const char *format, va_list ap );
|
||||
|
||||
typedef int(*log_vprint_func_t)(FILE *stream, const char *format, va_list ap );
|
||||
typedef int(*log_print_func_t)(FILE *stream, const char *format, ... );
|
||||
typedef struct {
|
||||
const char *name;
|
||||
int level;
|
||||
int flag;
|
||||
int interval;
|
||||
int filelog;
|
||||
char *filelog_name;
|
||||
FILE *stream;
|
||||
log_write_func_t fwrite;
|
||||
const char *name;
|
||||
int level;
|
||||
int savedlevel;
|
||||
int flag;
|
||||
int filelog;
|
||||
char *filelog_name;
|
||||
FILE *stream;
|
||||
log_vprint_func_t vprint;
|
||||
log_print_func_t print;
|
||||
/* SR: make the log buffer component relative */
|
||||
char log_buffer[MAX_LOG_TOTAL];
|
||||
} log_component_t;
|
||||
@@ -217,13 +249,11 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
log_component_t log_component[MAX_LOG_COMPONENTS];
|
||||
char* level2string[NUM_LOG_LEVEL];
|
||||
int onlinelog;
|
||||
char level2string[NUM_LOG_LEVEL];
|
||||
int flag;
|
||||
int filelog;
|
||||
char* filelog_name;
|
||||
uint64_t debug_mask;
|
||||
uint64_t matlab_mask;
|
||||
uint64_t dump_mask;
|
||||
} log_t;
|
||||
|
||||
|
||||
@@ -254,14 +284,15 @@ extern log_t *g_log;
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int logInit (void);
|
||||
void logRecord_mt(const char *file, const char *func, int line,int comp, int level, const char *format, ...) __attribute__ ((format (printf, 6, 7)));
|
||||
|
||||
int set_log(int component, int level, int interval);
|
||||
void log_dump(int component, void *buffer, int buffsize,int datatype, const char* format, ... );
|
||||
int set_log(int component, int level);
|
||||
void set_glog(int level);
|
||||
|
||||
void set_glog_onlinelog(int enable);
|
||||
void set_glog_filelog(int enable);
|
||||
void set_component_filelog(int comp);
|
||||
|
||||
void close_component_filelog(int comp);
|
||||
void set_component_consolelog(int comp);
|
||||
int map_str_to_int(mapping *map, const char *str);
|
||||
char *map_int_to_str(mapping *map, int val);
|
||||
void logClean (void);
|
||||
@@ -293,7 +324,7 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int
|
||||
#define LOG_CONFIG_LEVEL_FORMAT "%s_log_level"
|
||||
#define LOG_CONFIG_LOGFILE_FORMAT "%s_log_infile"
|
||||
#define LOG_CONFIG_DEBUG_FORMAT "%s_debug"
|
||||
#define LOG_CONFIG_MATLAB_FORMAT "%s_matlab"
|
||||
#define LOG_CONFIG_DUMP_FORMAT "%s_dump"
|
||||
|
||||
#define LOG_CONFIG_HELP_OPTIONS " list of comma separated options to enable log module behavior. Available options: \n"\
|
||||
" nocolor: disable color usage in log messages\n"\
|
||||
@@ -309,7 +340,7 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int
|
||||
/*------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
#define LOG_GLOBALPARAMS_DESC { \
|
||||
{LOG_CONFIG_STRING_GLOBAL_LOG_LEVEL, "Default log level for all componemts\n", 0, strptr:(char **)&gloglevel, defstrval:log_level_names[2].name, TYPE_STRING, 0}, \
|
||||
{LOG_CONFIG_STRING_GLOBAL_LOG_ONLINE, "Default console output option, for all components\n", 0, iptr:&(g_log->onlinelog), defintval:1, TYPE_INT, 0}, \
|
||||
{LOG_CONFIG_STRING_GLOBAL_LOG_ONLINE, "Default console output option, for all components\n", 0, iptr:&(consolelog), defintval:1, TYPE_INT, 0}, \
|
||||
{LOG_CONFIG_STRING_GLOBAL_LOG_OPTIONS, LOG_CONFIG_HELP_OPTIONS, 0, strlistptr:NULL, defstrlistval:NULL, TYPE_STRINGLIST,0} \
|
||||
}
|
||||
|
||||
@@ -319,23 +350,25 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int
|
||||
* @ingroup _macro
|
||||
* @brief Macro used to call logIt function with different message levels
|
||||
* @{*/
|
||||
|
||||
// debugging macros(g_log->log_component[component].interval?logRecord_mt(__FILE__, __FUNCTION__, __LINE__, component, level, format, ##args):(void)0)
|
||||
#define LOG_DUMP_CHAR 0
|
||||
#define LOG_DUMP_DOUBLE 1
|
||||
// debugging macros
|
||||
#define LOG_F LOG_I /* because LOG_F was originaly to dump a message or buffer but is also used as a regular level...., to dump use LOG_DUMPMSG */
|
||||
# if T_TRACER
|
||||
/* per component, level dependant macros */
|
||||
# define LOG_I(c, x...) do { if (T_stdout) { if( g_log->log_component[c].level >= OAILOG_INFO ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_INFO, x) ;} else { T(T_LEGACY_ ## c ## _INFO, T_PRINTF(x)) ;}} while (0)
|
||||
# define LOG_W(c, x...) do { if (T_stdout) { if( g_log->log_component[c].level >= OAILOG_WARNING) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_WARNING, x) ;} else { T(T_LEGACY_ ## c ## _WARNING, T_PRINTF(x)) ;}} while (0)
|
||||
# define LOG_E(c, x...) do { if (T_stdout) { if( g_log->log_component[c].level >= OAILOG_ERR ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_ERR, x) ;} else { T(T_LEGACY_ ## c ## _ERROR, T_PRINTF(x)) ;}} while (0)
|
||||
# define LOG_W(c, x...) do { if (T_stdout) { if( g_log->log_component[c].level >= OAILOG_WARNING) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_WARNING, x) ;} else { T(T_LEGACY_ ## c ## _WARNING, T_PRINTF(x)) ;}} while (0)
|
||||
# define LOG_I(c, x...) do { if (T_stdout) { if( g_log->log_component[c].level >= OAILOG_INFO ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_INFO, x) ;} else { T(T_LEGACY_ ## c ## _INFO, T_PRINTF(x)) ;}} while (0)
|
||||
# define LOG_D(c, x...) do { if (T_stdout) { if( g_log->log_component[c].level >= OAILOG_DEBUG ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_DEBUG, x) ;} else { T(T_LEGACY_ ## c ## _DEBUG, T_PRINTF(x)) ;}} while (0)
|
||||
# define LOG_T(c, x...) do { if (T_stdout) { if( g_log->log_component[c].level >= OAILOG_TRACE ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_TRACE, x) ;} else { T(T_LEGACY_ ## c ## _TRACE, T_PRINTF(x)) ;}} while (0)
|
||||
# define LOG_F(c, x...) do { if (T_stdout) { if( g_log->log_component[c].level >= OAILOG_FILE ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_FILE, x) ;}} while (0) /* */
|
||||
/* macro used to dump a buffer or a message as in openair2/RRC/LTE/RRC_eNB.c, replaces LOG_F macro */
|
||||
# define LOG_DUMPMSG(c, f, b, s, x...) do { if(g_log->dump_mask & f) log_dump(c, b, s, LOG_DUMP_CHAR, x) ;} while (0) /* */
|
||||
# define nfapi_log(FILE, FNC, LN, COMP, LVL, F...) do { if (T_stdout) { logRecord_mt(__FILE__, __FUNCTION__, __LINE__,COMP, LVL, F) ;}} while (0) /* */
|
||||
/* bitmask dependant macros, to isolate debugging code */
|
||||
# define LOG_DEBUG_BEGIN(D) if (g_log->debug_mask & D) {
|
||||
# define LOG_DEBUG_END }
|
||||
/* bitmask dependant macros, to generate matlab files */
|
||||
# define LOG_M_BEGIN(D) if (g_log->matlab_mask & D) {
|
||||
# define LOG_M_END }
|
||||
# define LOG_DEBUGFLAG(D) (g_log->debug_mask & D)
|
||||
|
||||
/* bitmask dependant macros, to generate debug file such as matlab file or message dump */
|
||||
# define LOG_DUMPFLAG(D) (g_log->dump_mask & D)
|
||||
# define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format);} while(0)/* */
|
||||
/* define variable only used in LOG macro's */
|
||||
# define LOG_VAR(A,B) A B
|
||||
@@ -345,22 +378,22 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int
|
||||
# define LOG_E(c, x...) /* */
|
||||
# define LOG_D(c, x...) /* */
|
||||
# define LOG_T(c, x...) /* */
|
||||
# define LOG_F(c, x...) /* */
|
||||
|
||||
# define LOG_DUMPMSG(c, b, s, x...) /* */
|
||||
# define nfapi_log(FILE, FNC, LN, COMP, LVL, FMT...)
|
||||
# define LOG_DEBUG_BEGIN(D) if (0) {
|
||||
# define LOG_DEBUG_END }
|
||||
# define LOG_M_BEGIN(D) if (0) {
|
||||
# define LOG_M_END }
|
||||
# define LOG_DEBUGFLAG(D) ( 0 )
|
||||
# define LOG_DUMPFLAG(D) ( 0 )
|
||||
# define LOG_M(file, vector, data, len, dec, format)
|
||||
# define LOG_VAR(A,B)
|
||||
# endif /* T_TRACER */
|
||||
/* avoid warnings for variables only used in LOG macro's but set outside debug section */
|
||||
#define LOG_USEDINLOG_VAR(A,B) __attribute__((unused)) A B
|
||||
#define GCC_NOTUSED __attribute__((unused))
|
||||
#define LOG_USEDINLOG_VAR(A,B) GCC_NOTUSED A B
|
||||
|
||||
/* unfiltered macros, usefull for simulators or messages at init time, before log is configured */
|
||||
#define LOG_UM(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format);} while(0)
|
||||
|
||||
#define LOG_UI(c, x...) do {logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_INFO, x) ; } while(0)
|
||||
#define LOG_UDUMPMSG(c, b, s, f, x...) do { log_dump(c, b, s, f, x) ;} while (0) /* */
|
||||
/* @}*/
|
||||
|
||||
|
||||
@@ -368,9 +401,12 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int
|
||||
* @ingroup _macro
|
||||
* @brief Macro of some useful functions defined by LOG
|
||||
* @{*/
|
||||
#define LOG_ENTER(c) do {LOG_T(c, "Entering\n");}while(0) /*!< \brief Macro to log a message with severity DEBUG when entering a function */
|
||||
#define LOG_EXIT(c) do {LOG_T(c,"Exiting\n"); return;}while(0) /*!< \brief Macro to log a message with severity TRACE when exiting a function */
|
||||
#define LOG_RETURN(c,x) do {uint32_t __rv;__rv=(unsigned int)(x);LOG_T(c,"Returning %08x\n", __rv);return((typeof(x))__rv);}while(0) /*!< \brief Macro to log a function exit, including integer value, then to return a value to the calling function */
|
||||
#define LOG_ENTER(c) do {LOG_T(c, "Entering %s\n",__FUNCTION__);}while(0) /*!< \brief Macro to log a message with severity DEBUG when entering a function */
|
||||
#define LOG_END(c) do {LOG_T(c, "End of %s\n",__FUNCTION__);}while(0) /*!< \brief Macro to log a message with severity DEBUG when entering a function */
|
||||
#define LOG_EXIT(c) do { LOG_END(c); return;}while(0) /*!< \brief Macro to log a message with severity TRACE when exiting a function */
|
||||
#define LOG_RETURN(c,r) do {LOG_T(c,"Leaving %s (rc = %08lx)\n", __FUNCTION__ , (unsigned long)(r) );return(r);}while(0) /*!< \brief Macro to log a function exit, including integer value, then to return a value to the calling function */
|
||||
|
||||
|
||||
/* @}*/
|
||||
|
||||
static __inline__ uint64_t rdtsc(void) {
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "assertions.h"
|
||||
#include "signals.h"
|
||||
|
||||
#include "vcd_signal_dumper.h"
|
||||
|
||||
|
||||
@@ -750,6 +750,27 @@ ID = LEGACY_OSA_TRACE
|
||||
GROUP = ALL:LEGACY_OSA:LEGACY_GROUP_TRACE:LEGACY
|
||||
FORMAT = string,log
|
||||
|
||||
ID = LEGACY_ASN_INFO
|
||||
DESC = ASN legacy logs - info level
|
||||
GROUP = ALL:LEGACY_ASN:LEGACY_GROUP_INFO:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_ASN_ERROR
|
||||
DESC = ASN legacy logs - error level
|
||||
GROUP = ALL:LEGACY_ASN:LEGACY_GROUP_ERROR:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_ASN_WARNING
|
||||
DESC = ASN legacy logs - warning level
|
||||
GROUP = ALL:LEGACY_ASN:LEGACY_GROUP_WARNING:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_ASN_DEBUG
|
||||
DESC = ASN legacy logs - debug level
|
||||
GROUP = ALL:LEGACY_ASN:LEGACY_GROUP_DEBUG:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_ASN_TRACE
|
||||
DESC = ASN legacy logs - trace level
|
||||
GROUP = ALL:LEGACY_ASN:LEGACY_GROUP_TRACE:LEGACY
|
||||
FORMAT = string,log
|
||||
|
||||
ID = LEGACY_SIM_INFO
|
||||
DESC = SIM legacy logs - info level
|
||||
GROUP = ALL:LEGACY_SIM:LEGACY_GROUP_INFO:LEGACY
|
||||
|
||||
@@ -150,7 +150,17 @@ x_image *x_create_image(x_connection *_x, unsigned char *data,
|
||||
vs = XGetVisualInfo(x->d, VisualDepthMask | VisualClassMask |
|
||||
VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask |
|
||||
VisualBitsPerRGBMask, &template, &nvs);
|
||||
if (vs == NULL || nvs == 0) ERR("no good visual found\n");
|
||||
|
||||
if (vs == NULL) {
|
||||
/* try again with 32 bpp */
|
||||
template.depth = 32;
|
||||
vs = XGetVisualInfo(x->d, VisualDepthMask | VisualClassMask |
|
||||
VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask |
|
||||
VisualBitsPerRGBMask, &template, &nvs);
|
||||
}
|
||||
|
||||
if (vs == NULL) ERR("no good visual found\n");
|
||||
|
||||
v = vs[0].visual;
|
||||
XFree(vs);
|
||||
|
||||
|
||||
@@ -19,9 +19,72 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef UTILS_ASSERTIONS_H_
|
||||
#define UTILS_ASSERTIONS_H_
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#ifdef CMAKER
|
||||
#include <platform_types.h>
|
||||
#endif
|
||||
|
||||
#include "./itti/assertions.h"
|
||||
#if defined(ENB_MODE)
|
||||
# define display_backtrace()
|
||||
#else
|
||||
# include "backtrace.h"
|
||||
#endif
|
||||
|
||||
#endif /* UTILS_ASSERTIONS_H_ */
|
||||
#ifndef ASSERTIONS_H_
|
||||
#define ASSERTIONS_H_
|
||||
|
||||
void output_log_mem(void);
|
||||
#define _Assert_Exit_ \
|
||||
{ \
|
||||
fprintf(stderr, "\nExiting execution\n"); \
|
||||
display_backtrace(); \
|
||||
fflush(stdout); \
|
||||
fflush(stderr); \
|
||||
exit(EXIT_FAILURE); \
|
||||
}
|
||||
|
||||
#define _Assert_(cOND, aCTION, fORMAT, aRGS...) \
|
||||
do { \
|
||||
if (!(cOND)) { \
|
||||
fprintf(stderr, "\nAssertion ("#cOND") failed!\n" \
|
||||
"In %s() %s:%d\n" fORMAT, \
|
||||
__FUNCTION__, __FILE__, __LINE__, ##aRGS); \
|
||||
aCTION; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define AssertFatal(cOND, fORMAT, aRGS...) _Assert_(cOND, _Assert_Exit_, fORMAT, ##aRGS)
|
||||
|
||||
#define AssertError(cOND, aCTION, fORMAT, aRGS...) _Assert_(cOND, aCTION, fORMAT, ##aRGS)
|
||||
|
||||
|
||||
|
||||
#define DevCheck(cOND, vALUE1, vALUE2, vALUE3) \
|
||||
_Assert_(cOND, _Assert_Exit_, #vALUE1 ": %" PRIdMAX "\n" #vALUE2 ": %" PRIdMAX "\n" #vALUE3 ": %" PRIdMAX "\n\n", \
|
||||
(intmax_t)vALUE1, (intmax_t)vALUE2, (intmax_t)vALUE3)
|
||||
|
||||
#define DevCheck4(cOND, vALUE1, vALUE2, vALUE3, vALUE4) \
|
||||
_Assert_(cOND, _Assert_Exit_, #vALUE1": %" PRIdMAX "\n" #vALUE2 ": %" PRIdMAX "\n" #vALUE3 ": %" PRIdMAX "\n" #vALUE4 ": %" PRIdMAX "\n\n", \
|
||||
(intmax_t)vALUE1, (intmax_t)vALUE2, (intmax_t)vALUE3, (intmax_t)vALUE4)
|
||||
|
||||
#define DevParam(vALUE1, vALUE2, vALUE3) DevCheck(0, vALUE1, vALUE2, vALUE3)
|
||||
|
||||
#define DevAssert(cOND) _Assert_(cOND, _Assert_Exit_, "")
|
||||
|
||||
#define DevMessage(mESSAGE) _Assert_(0, _Assert_Exit_, #mESSAGE)
|
||||
|
||||
#define CHECK_INIT_RETURN(fCT) \
|
||||
do { \
|
||||
int fct_ret; \
|
||||
if ((fct_ret = (fCT)) != 0) { \
|
||||
fprintf(stderr, "Function "#fCT" has failed\n" \
|
||||
"returning %d\n", fct_ret); \
|
||||
fflush(stdout); \
|
||||
fflush(stderr); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#endif /* ASSERTIONS_H_ */
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
AM_CFLAGS = @ADD_CFLAGS@ \
|
||||
-I$(top_srcdir)/UTILS \
|
||||
-I$(top_srcdir)/COMMON \
|
||||
-I$(OPENAIR2_DIR)/UTIL/LFDS/liblfds6.1.1/liblfds611/inc \
|
||||
-DENABLE_EVENT_FD
|
||||
|
||||
noinst_LTLIBRARIES = libitti.la
|
||||
|
||||
BUILT_SOURCES = $(abs_top_builddir)/INTERTASK_INTERFACE/UTIL/LFDS/liblfds6.1.1/liblfds611/bin/liblfds611.a
|
||||
|
||||
$(abs_top_builddir)/INTERTASK_INTERFACE/UTIL/LFDS/liblfds6.1.1/liblfds611/bin/liblfds611.a:
|
||||
@if [ ! -d $(abs_top_builddir)/INTERTASK_INTERFACE/UTIL/LFDS/liblfds6.1.1/liblfds611/bin ]; then mkdir -p $(abs_top_builddir)/INTERTASK_INTERFACE/UTIL/LFDS/liblfds6.1.1/liblfds611/bin; fi;
|
||||
@if [ ! -d $(abs_top_builddir)/INTERTASK_INTERFACE/UTIL/LFDS/liblfds6.1.1/liblfds611/obj ]; then mkdir -p $(abs_top_builddir)/INTERTASK_INTERFACE/UTIL/LFDS/liblfds6.1.1/liblfds611/obj; fi;
|
||||
@$(MAKE) -C $(OPENAIR2_DIR)/UTIL/LFDS/liblfds6.1.1/liblfds611/ -f makefile.linux OUTDIR=$(abs_top_builddir)/INTERTASK_INTERFACE/UTIL/LFDS/liblfds6.1.1/liblfds611
|
||||
|
||||
libitti_la_LDFLAGS = -all-static
|
||||
libitti_la_SOURCES = \
|
||||
gtpv1_u_messages_def.h gtpv1_u_messages_types.h \
|
||||
nas_messages_def.h nas_messages_types.h \
|
||||
timer_messages_def.h timer_messages_types.h \
|
||||
s11_messages_def.h s11_messages_types.h \
|
||||
s1ap_messages_def.h s1ap_messages_types.h \
|
||||
s6a_messages_def.h s6a_messages_types.h \
|
||||
sgw_lite_def.h sgw_lite_messages_types.h \
|
||||
sctp_messages_def.h sctp_messages_types.h \
|
||||
udp_message_def.h udp_messages_types.h \
|
||||
intertask_interface.c intertask_interface.h \
|
||||
intertask_interface_dump.c intertask_interface_dump.h \
|
||||
assertions.h \
|
||||
backtrace.c backtrace.h \
|
||||
signals.c signals.h \
|
||||
timer.c timer.h
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#ifdef CMAKER
|
||||
#include <platform_types.h>
|
||||
#endif
|
||||
|
||||
#if defined(ENB_MODE)
|
||||
# define display_backtrace()
|
||||
#else
|
||||
# include "backtrace.h"
|
||||
#endif
|
||||
|
||||
#ifndef ASSERTIONS_H_
|
||||
#define ASSERTIONS_H_
|
||||
|
||||
void output_log_mem(void);
|
||||
#define _Assert_Exit_ \
|
||||
{ \
|
||||
fprintf(stderr, "\nExiting execution\n"); \
|
||||
display_backtrace(); \
|
||||
fflush(stdout); \
|
||||
fflush(stderr); \
|
||||
exit(EXIT_FAILURE); \
|
||||
}
|
||||
|
||||
#define _Assert_(cOND, aCTION, fORMAT, aRGS...) \
|
||||
do { \
|
||||
if (!(cOND)) { \
|
||||
fprintf(stderr, "\nAssertion ("#cOND") failed!\n" \
|
||||
"In %s() %s:%d\n" fORMAT, \
|
||||
__FUNCTION__, __FILE__, __LINE__, ##aRGS); \
|
||||
aCTION; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define AssertFatal(cOND, fORMAT, aRGS...) _Assert_(cOND, _Assert_Exit_, fORMAT, ##aRGS)
|
||||
|
||||
#define AssertError(cOND, aCTION, fORMAT, aRGS...) _Assert_(cOND, aCTION, fORMAT, ##aRGS)
|
||||
|
||||
|
||||
|
||||
#define DevCheck(cOND, vALUE1, vALUE2, vALUE3) \
|
||||
_Assert_(cOND, _Assert_Exit_, #vALUE1 ": %" PRIdMAX "\n" #vALUE2 ": %" PRIdMAX "\n" #vALUE3 ": %" PRIdMAX "\n\n", \
|
||||
(intmax_t)vALUE1, (intmax_t)vALUE2, (intmax_t)vALUE3)
|
||||
|
||||
#define DevCheck4(cOND, vALUE1, vALUE2, vALUE3, vALUE4) \
|
||||
_Assert_(cOND, _Assert_Exit_, #vALUE1": %" PRIdMAX "\n" #vALUE2 ": %" PRIdMAX "\n" #vALUE3 ": %" PRIdMAX "\n" #vALUE4 ": %" PRIdMAX "\n\n", \
|
||||
(intmax_t)vALUE1, (intmax_t)vALUE2, (intmax_t)vALUE3, (intmax_t)vALUE4)
|
||||
|
||||
#define DevParam(vALUE1, vALUE2, vALUE3) DevCheck(0, vALUE1, vALUE2, vALUE3)
|
||||
|
||||
#define DevAssert(cOND) _Assert_(cOND, _Assert_Exit_, "")
|
||||
|
||||
#define DevMessage(mESSAGE) _Assert_(0, _Assert_Exit_, #mESSAGE)
|
||||
|
||||
#define CHECK_INIT_RETURN(fCT) \
|
||||
do { \
|
||||
int fct_ret; \
|
||||
if ((fct_ret = (fCT)) != 0) { \
|
||||
fprintf(stderr, "Function "#fCT" has failed\n" \
|
||||
"returning %d\n", fct_ret); \
|
||||
fflush(stdout); \
|
||||
fflush(stderr); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#endif /* ASSERTIONS_H_ */
|
||||
@@ -1,930 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/eventfd.h>
|
||||
|
||||
#if !defined(TRUE)
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#include "liblfds611.h"
|
||||
|
||||
#include "assertions.h"
|
||||
#include "intertask_interface.h"
|
||||
|
||||
#if T_TRACER
|
||||
#include "T.h"
|
||||
#endif
|
||||
|
||||
/* Includes "intertask_interface_init.h" to check prototype coherence, but
|
||||
* disable threads and messages information generation.
|
||||
*/
|
||||
#define CHECK_PROTOTYPE_ONLY
|
||||
#include "intertask_interface_init.h"
|
||||
#undef CHECK_PROTOTYPE_ONLY
|
||||
|
||||
#include "signals.h"
|
||||
#include "timer.h"
|
||||
|
||||
/* ITTI DEBUG groups */
|
||||
#define ITTI_DEBUG_POLL (1<<0)
|
||||
#define ITTI_DEBUG_SEND (1<<1)
|
||||
#define ITTI_DEBUG_EVEN_FD (1<<2)
|
||||
#define ITTI_DEBUG_INIT (1<<3)
|
||||
#define ITTI_DEBUG_EXIT (1<<4)
|
||||
#define ITTI_DEBUG_ISSUES (1<<5)
|
||||
#define ITTI_DEBUG_MP_STATISTICS (1<<6)
|
||||
|
||||
const int itti_debug = (ITTI_DEBUG_ISSUES | ITTI_DEBUG_MP_STATISTICS);
|
||||
|
||||
# define ITTI_DEBUG(m, x, args...) do { if ((m) & itti_debug) {fprintf(stdout, "[ITTI][D]"x, ##args); fflush (stdout);} } while(0);
|
||||
#define ITTI_ERROR(x, args...) do { fprintf(stdout, "[ITTI][E]"x, ##args); fflush (stdout); } while(0);
|
||||
|
||||
/* Global message size */
|
||||
#define MESSAGE_SIZE(mESSAGEiD) (sizeof(MessageHeader) + itti_desc.messages_info[mESSAGEiD].size)
|
||||
|
||||
|
||||
extern int emulate_rf;
|
||||
|
||||
typedef enum task_state_s {
|
||||
TASK_STATE_NOT_CONFIGURED, TASK_STATE_STARTING, TASK_STATE_READY, TASK_STATE_ENDED, TASK_STATE_MAX,
|
||||
} task_state_t;
|
||||
|
||||
/* This list acts as a FIFO of messages received by tasks (RRC, NAS, ...) */
|
||||
typedef struct message_list_s {
|
||||
MessageDef *msg; ///< Pointer to the message
|
||||
|
||||
message_number_t message_number; ///< Unique message number
|
||||
uint32_t message_priority; ///< Message priority
|
||||
} message_list_t;
|
||||
|
||||
typedef struct thread_desc_s {
|
||||
/* pthread associated with the thread */
|
||||
pthread_t task_thread;
|
||||
|
||||
/* State of the thread */
|
||||
volatile task_state_t task_state;
|
||||
|
||||
/* This fd is used internally by ITTI. */
|
||||
int epoll_fd;
|
||||
|
||||
/* The thread fd */
|
||||
int task_event_fd;
|
||||
|
||||
/* Number of events to monitor */
|
||||
uint16_t nb_events;
|
||||
|
||||
|
||||
/* Array of events monitored by the task.
|
||||
* By default only one fd is monitored (the one used to received messages
|
||||
* from other tasks).
|
||||
* More events can be suscribed later by the task itself.
|
||||
*/
|
||||
struct epoll_event *events;
|
||||
|
||||
int epoll_nb_events;
|
||||
|
||||
/* Flag to mark real time thread */
|
||||
unsigned real_time;
|
||||
|
||||
/* Counter to indicate that messages are pending for the thread */
|
||||
unsigned messages_pending;
|
||||
} thread_desc_t;
|
||||
|
||||
typedef struct task_desc_s {
|
||||
/* Queue of messages belonging to the task */
|
||||
struct lfds611_queue_state *message_queue;
|
||||
} task_desc_t;
|
||||
|
||||
typedef struct itti_desc_s {
|
||||
thread_desc_t *threads;
|
||||
task_desc_t *tasks;
|
||||
|
||||
/* Current message number. Incremented every call to send_msg_to_task */
|
||||
message_number_t message_number __attribute__((aligned(8)));
|
||||
|
||||
thread_id_t thread_max;
|
||||
task_id_t task_max;
|
||||
MessagesIds messages_id_max;
|
||||
|
||||
boolean_t thread_handling_signals;
|
||||
pthread_t thread_ref;
|
||||
|
||||
const task_info_t *tasks_info;
|
||||
const message_info_t *messages_info;
|
||||
|
||||
itti_lte_time_t lte_time;
|
||||
|
||||
int running;
|
||||
|
||||
volatile uint32_t created_tasks;
|
||||
volatile uint32_t ready_tasks;
|
||||
volatile int wait_tasks;
|
||||
} itti_desc_t;
|
||||
|
||||
static itti_desc_t itti_desc;
|
||||
|
||||
void *itti_malloc(task_id_t origin_task_id, task_id_t destination_task_id, ssize_t size)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
|
||||
ptr = malloc (size);
|
||||
if (ptr) memset(ptr,0,size);
|
||||
|
||||
AssertFatal (ptr != NULL, "Memory allocation of %d bytes failed (%d -> %d)!\n", (int) size, origin_task_id, destination_task_id);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int itti_free(task_id_t task_id, void *ptr)
|
||||
{
|
||||
int result = EXIT_SUCCESS;
|
||||
AssertFatal (ptr != NULL, "Trying to free a NULL pointer (%d)!\n", task_id);
|
||||
|
||||
free (ptr);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static inline message_number_t itti_increment_message_number(void)
|
||||
{
|
||||
/* Atomic operation supported by GCC: returns the current message number
|
||||
* and then increment it by 1.
|
||||
* This can be done without mutex.
|
||||
*/
|
||||
return __sync_fetch_and_add (&itti_desc.message_number, 1);
|
||||
}
|
||||
|
||||
static inline uint32_t itti_get_message_priority(MessagesIds message_id)
|
||||
{
|
||||
AssertFatal (message_id < itti_desc.messages_id_max, "Message id (%d) is out of range (%d)!\n", message_id, itti_desc.messages_id_max);
|
||||
|
||||
return (itti_desc.messages_info[message_id].priority);
|
||||
}
|
||||
|
||||
const char *itti_get_message_name(MessagesIds message_id)
|
||||
{
|
||||
AssertFatal (message_id < itti_desc.messages_id_max, "Message id (%d) is out of range (%d)!\n", message_id, itti_desc.messages_id_max);
|
||||
|
||||
return (itti_desc.messages_info[message_id].name);
|
||||
}
|
||||
|
||||
const char *itti_get_task_name(task_id_t task_id)
|
||||
{
|
||||
if (itti_desc.task_max > 0) {
|
||||
AssertFatal (task_id < itti_desc.task_max, "Task id (%d) is out of range (%d)!\n", task_id, itti_desc.task_max);
|
||||
} else {
|
||||
return ("ITTI NOT INITIALIZED !!!");
|
||||
}
|
||||
|
||||
return (itti_desc.tasks_info[task_id].name);
|
||||
}
|
||||
|
||||
static task_id_t itti_get_current_task_id(void)
|
||||
{
|
||||
task_id_t task_id;
|
||||
thread_id_t thread_id;
|
||||
pthread_t thread = pthread_self ();
|
||||
|
||||
for (task_id = TASK_FIRST; task_id < itti_desc.task_max; task_id++) {
|
||||
thread_id = TASK_GET_THREAD_ID(task_id);
|
||||
|
||||
if (itti_desc.threads[thread_id].task_thread == thread) {
|
||||
return task_id;
|
||||
}
|
||||
}
|
||||
|
||||
return TASK_UNKNOWN;
|
||||
}
|
||||
|
||||
void itti_update_lte_time(uint32_t frame, uint8_t slot)
|
||||
{
|
||||
itti_desc.lte_time.frame = frame;
|
||||
itti_desc.lte_time.slot = slot;
|
||||
}
|
||||
|
||||
int itti_send_broadcast_message(MessageDef *message_p)
|
||||
{
|
||||
task_id_t destination_task_id;
|
||||
task_id_t origin_task_id;
|
||||
thread_id_t origin_thread_id;
|
||||
uint32_t thread_id;
|
||||
int ret = 0;
|
||||
int result;
|
||||
|
||||
AssertFatal (message_p != NULL, "Trying to broadcast a NULL message!\n");
|
||||
|
||||
origin_task_id = message_p->ittiMsgHeader.originTaskId;
|
||||
origin_thread_id = TASK_GET_THREAD_ID(origin_task_id);
|
||||
|
||||
destination_task_id = TASK_FIRST;
|
||||
|
||||
for (thread_id = THREAD_FIRST; thread_id < itti_desc.thread_max; thread_id++) {
|
||||
MessageDef *new_message_p;
|
||||
|
||||
while (thread_id != TASK_GET_THREAD_ID(destination_task_id)) {
|
||||
destination_task_id++;
|
||||
}
|
||||
|
||||
/* Skip task that broadcast the message */
|
||||
if (thread_id != origin_thread_id) {
|
||||
/* Skip tasks which are not running */
|
||||
if (itti_desc.threads[thread_id].task_state == TASK_STATE_READY) {
|
||||
size_t size = sizeof(MessageHeader) + message_p->ittiMsgHeader.ittiMsgSize;
|
||||
new_message_p = itti_malloc( origin_task_id, destination_task_id, size );
|
||||
AssertFatal (new_message_p != NULL, "New message allocation failed!\n");
|
||||
|
||||
memcpy( new_message_p, message_p, size );
|
||||
result = itti_send_msg_to_task (destination_task_id, INSTANCE_DEFAULT, new_message_p);
|
||||
AssertFatal (result >= 0, "Failed to send message %d to thread %d (task %d)!\n", message_p->ittiMsgHeader.messageId, thread_id, destination_task_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
|
||||
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
MessageDef *itti_alloc_new_message_sized(task_id_t origin_task_id, MessagesIds message_id, MessageHeaderSize size)
|
||||
{
|
||||
MessageDef *temp = NULL;
|
||||
|
||||
AssertFatal (message_id < itti_desc.messages_id_max, "Message id (%d) is out of range (%d)!\n", message_id, itti_desc.messages_id_max);
|
||||
|
||||
if (origin_task_id == TASK_UNKNOWN) {
|
||||
/* Try to identify real origin task ID */
|
||||
origin_task_id = itti_get_current_task_id();
|
||||
}
|
||||
|
||||
temp = itti_malloc (origin_task_id, TASK_UNKNOWN, sizeof(MessageHeader) + size);
|
||||
|
||||
temp->ittiMsgHeader.messageId = message_id;
|
||||
temp->ittiMsgHeader.originTaskId = origin_task_id;
|
||||
temp->ittiMsgHeader.ittiMsgSize = size;
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
MessageDef *itti_alloc_new_message(task_id_t origin_task_id, MessagesIds message_id)
|
||||
{
|
||||
return itti_alloc_new_message_sized(origin_task_id, message_id, itti_desc.messages_info[message_id].size);
|
||||
}
|
||||
|
||||
int itti_send_msg_to_task(task_id_t destination_task_id, instance_t instance, MessageDef *message)
|
||||
{
|
||||
thread_id_t destination_thread_id;
|
||||
task_id_t origin_task_id;
|
||||
message_list_t *new;
|
||||
uint32_t priority;
|
||||
message_number_t message_number;
|
||||
uint32_t message_id;
|
||||
|
||||
AssertFatal (message != NULL, "Message is NULL!\n");
|
||||
AssertFatal (destination_task_id < itti_desc.task_max, "Destination task id (%d) is out of range (%d)\n", destination_task_id, itti_desc.task_max);
|
||||
|
||||
destination_thread_id = TASK_GET_THREAD_ID(destination_task_id);
|
||||
message->ittiMsgHeader.destinationTaskId = destination_task_id;
|
||||
message->ittiMsgHeader.instance = instance;
|
||||
message->ittiMsgHeader.lte_time.frame = itti_desc.lte_time.frame;
|
||||
message->ittiMsgHeader.lte_time.slot = itti_desc.lte_time.slot;
|
||||
message_id = message->ittiMsgHeader.messageId;
|
||||
AssertFatal (message_id < itti_desc.messages_id_max, "Message id (%d) is out of range (%d)!\n", message_id, itti_desc.messages_id_max);
|
||||
|
||||
origin_task_id = ITTI_MSG_ORIGIN_ID(message);
|
||||
|
||||
priority = itti_get_message_priority (message_id);
|
||||
|
||||
/* Increment the global message number */
|
||||
message_number = itti_increment_message_number ();
|
||||
|
||||
if (destination_task_id != TASK_UNKNOWN) {
|
||||
|
||||
if (itti_desc.threads[destination_thread_id].task_state == TASK_STATE_ENDED ||
|
||||
itti_desc.threads[destination_thread_id].task_state == TASK_STATE_NOT_CONFIGURED) {
|
||||
ITTI_DEBUG(ITTI_DEBUG_ISSUES, " Message %s, number %lu with priority %d can not be sent from %s to queue (%u:%s), unconfigured or ended destination task!\n",
|
||||
itti_desc.messages_info[message_id].name,
|
||||
message_number,
|
||||
priority,
|
||||
itti_get_task_name(origin_task_id),
|
||||
destination_task_id,
|
||||
itti_get_task_name(destination_task_id));
|
||||
} else {
|
||||
if(!emulate_rf){
|
||||
/* We cannot send a message if the task is not running */
|
||||
AssertFatal (itti_desc.threads[destination_thread_id].task_state == TASK_STATE_READY,
|
||||
"Task %s Cannot send message %s (%d) to thread %d, it is not in ready state (%d)!\n",
|
||||
itti_get_task_name(origin_task_id),
|
||||
itti_desc.messages_info[message_id].name,
|
||||
message_id,
|
||||
destination_thread_id,
|
||||
itti_desc.threads[destination_thread_id].task_state);
|
||||
}
|
||||
|
||||
/* Allocate new list element */
|
||||
new = (message_list_t *) itti_malloc (origin_task_id, destination_task_id, sizeof(struct message_list_s));
|
||||
|
||||
/* Fill in members */
|
||||
new->msg = message;
|
||||
new->message_number = message_number;
|
||||
new->message_priority = priority;
|
||||
|
||||
/* Enqueue message in destination task queue */
|
||||
if (lfds611_queue_enqueue(itti_desc.tasks[destination_task_id].message_queue, new) == 0) {
|
||||
AssertFatal(0, "Error: lfds611_queue_enqueue returns 0, queue is full, exiting\n");
|
||||
}
|
||||
|
||||
{
|
||||
/* Only use event fd for tasks, subtasks will pool the queue */
|
||||
if (TASK_GET_PARENT_TASK_ID(destination_task_id) == TASK_UNKNOWN) {
|
||||
ssize_t write_ret;
|
||||
eventfd_t sem_counter = 1;
|
||||
|
||||
/* Call to write for an event fd must be of 8 bytes */
|
||||
write_ret = write (itti_desc.threads[destination_thread_id].task_event_fd, &sem_counter, sizeof(sem_counter));
|
||||
AssertFatal (write_ret == sizeof(sem_counter), "Write to task message FD (%d) failed (%d/%d)\n",
|
||||
destination_thread_id, (int) write_ret, (int) sizeof(sem_counter));
|
||||
}
|
||||
}
|
||||
|
||||
ITTI_DEBUG(ITTI_DEBUG_SEND, " Message %s, number %lu with priority %d successfully sent from %s to queue (%u:%s)\n",
|
||||
itti_desc.messages_info[message_id].name,
|
||||
message_number,
|
||||
priority,
|
||||
itti_get_task_name(origin_task_id),
|
||||
destination_task_id,
|
||||
itti_get_task_name(destination_task_id));
|
||||
}
|
||||
} else {
|
||||
/* This is a debug message to TASK_UNKNOWN, we can release safely release it */
|
||||
int result = itti_free(origin_task_id, message);
|
||||
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* same as itti_send_msg_to_task but returns -1 in case of failure instead of crashing */
|
||||
/* TODO: this is a hack - the whole logic needs a proper rework. */
|
||||
/* look for HACK_RLC_UM_LIMIT for others places related to the hack. Please do not remove this comment. */
|
||||
int itti_try_send_msg_to_task(task_id_t destination_task_id, instance_t instance, MessageDef *message)
|
||||
{
|
||||
thread_id_t destination_thread_id;
|
||||
task_id_t origin_task_id;
|
||||
message_list_t *new;
|
||||
uint32_t priority;
|
||||
message_number_t message_number;
|
||||
uint32_t message_id;
|
||||
|
||||
AssertFatal (message != NULL, "Message is NULL!\n");
|
||||
AssertFatal (destination_task_id < itti_desc.task_max, "Destination task id (%d) is out of range (%d)\n", destination_task_id, itti_desc.task_max);
|
||||
|
||||
destination_thread_id = TASK_GET_THREAD_ID(destination_task_id);
|
||||
message->ittiMsgHeader.destinationTaskId = destination_task_id;
|
||||
message->ittiMsgHeader.instance = instance;
|
||||
message->ittiMsgHeader.lte_time.frame = itti_desc.lte_time.frame;
|
||||
message->ittiMsgHeader.lte_time.slot = itti_desc.lte_time.slot;
|
||||
message_id = message->ittiMsgHeader.messageId;
|
||||
AssertFatal (message_id < itti_desc.messages_id_max, "Message id (%d) is out of range (%d)!\n", message_id, itti_desc.messages_id_max);
|
||||
|
||||
origin_task_id = ITTI_MSG_ORIGIN_ID(message);
|
||||
|
||||
priority = itti_get_message_priority (message_id);
|
||||
|
||||
/* Increment the global message number */
|
||||
message_number = itti_increment_message_number ();
|
||||
|
||||
if (destination_task_id != TASK_UNKNOWN) {
|
||||
|
||||
if (itti_desc.threads[destination_thread_id].task_state == TASK_STATE_ENDED ||
|
||||
itti_desc.threads[destination_thread_id].task_state == TASK_STATE_NOT_CONFIGURED) {
|
||||
ITTI_DEBUG(ITTI_DEBUG_ISSUES, " Message %s, number %lu with priority %d can not be sent from %s to queue (%u:%s), unconfigured or ended destination task!\n",
|
||||
itti_desc.messages_info[message_id].name,
|
||||
message_number,
|
||||
priority,
|
||||
itti_get_task_name(origin_task_id),
|
||||
destination_task_id,
|
||||
itti_get_task_name(destination_task_id));
|
||||
} else {
|
||||
/* We cannot send a message if the task is not running */
|
||||
AssertFatal (itti_desc.threads[destination_thread_id].task_state == TASK_STATE_READY,
|
||||
"Task %s Cannot send message %s (%d) to thread %d, it is not in ready state (%d)!\n",
|
||||
itti_get_task_name(origin_task_id),
|
||||
itti_desc.messages_info[message_id].name,
|
||||
message_id,
|
||||
destination_thread_id,
|
||||
itti_desc.threads[destination_thread_id].task_state);
|
||||
|
||||
/* Allocate new list element */
|
||||
new = (message_list_t *) itti_malloc (origin_task_id, destination_task_id, sizeof(struct message_list_s));
|
||||
|
||||
/* Fill in members */
|
||||
new->msg = message;
|
||||
new->message_number = message_number;
|
||||
new->message_priority = priority;
|
||||
|
||||
/* Enqueue message in destination task queue */
|
||||
if (lfds611_queue_enqueue(itti_desc.tasks[destination_task_id].message_queue, new) == 0) {
|
||||
itti_free(origin_task_id, new);
|
||||
return -1;
|
||||
}
|
||||
|
||||
{
|
||||
/* Only use event fd for tasks, subtasks will pool the queue */
|
||||
if (TASK_GET_PARENT_TASK_ID(destination_task_id) == TASK_UNKNOWN) {
|
||||
ssize_t write_ret;
|
||||
eventfd_t sem_counter = 1;
|
||||
|
||||
/* Call to write for an event fd must be of 8 bytes */
|
||||
write_ret = write (itti_desc.threads[destination_thread_id].task_event_fd, &sem_counter, sizeof(sem_counter));
|
||||
AssertFatal (write_ret == sizeof(sem_counter), "Write to task message FD (%d) failed (%d/%d)\n",
|
||||
destination_thread_id, (int) write_ret, (int) sizeof(sem_counter));
|
||||
}
|
||||
}
|
||||
|
||||
ITTI_DEBUG(ITTI_DEBUG_SEND, " Message %s, number %lu with priority %d successfully sent from %s to queue (%u:%s)\n",
|
||||
itti_desc.messages_info[message_id].name,
|
||||
message_number,
|
||||
priority,
|
||||
itti_get_task_name(origin_task_id),
|
||||
destination_task_id,
|
||||
itti_get_task_name(destination_task_id));
|
||||
}
|
||||
} else {
|
||||
/* This is a debug message to TASK_UNKNOWN, we can release safely release it */
|
||||
int result = itti_free(origin_task_id, message);
|
||||
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void itti_subscribe_event_fd(task_id_t task_id, int fd)
|
||||
{
|
||||
thread_id_t thread_id;
|
||||
struct epoll_event event;
|
||||
|
||||
AssertFatal (task_id < itti_desc.task_max, "Task id (%d) is out of range (%d)!\n", task_id, itti_desc.task_max);
|
||||
|
||||
thread_id = TASK_GET_THREAD_ID(task_id);
|
||||
itti_desc.threads[thread_id].nb_events++;
|
||||
|
||||
/* Reallocate the events */
|
||||
itti_desc.threads[thread_id].events = realloc(
|
||||
itti_desc.threads[thread_id].events,
|
||||
itti_desc.threads[thread_id].nb_events * sizeof(struct epoll_event));
|
||||
|
||||
event.events = EPOLLIN | EPOLLERR;
|
||||
event.data.u64 = 0;
|
||||
event.data.fd = fd;
|
||||
|
||||
/* Add the event fd to the list of monitored events */
|
||||
if (epoll_ctl(itti_desc.threads[thread_id].epoll_fd, EPOLL_CTL_ADD, fd,
|
||||
&event) != 0) {
|
||||
/* Always assert on this condition */
|
||||
AssertFatal (0, "epoll_ctl (EPOLL_CTL_ADD) failed for task %s, fd %d: %s!\n",
|
||||
itti_get_task_name(task_id), fd, strerror(errno));
|
||||
}
|
||||
|
||||
ITTI_DEBUG(ITTI_DEBUG_EVEN_FD, " Successfully subscribed fd %d for task %s\n", fd, itti_get_task_name(task_id));
|
||||
}
|
||||
|
||||
void itti_unsubscribe_event_fd(task_id_t task_id, int fd)
|
||||
{
|
||||
thread_id_t thread_id;
|
||||
|
||||
AssertFatal (task_id < itti_desc.task_max, "Task id (%d) is out of range (%d)!\n", task_id, itti_desc.task_max);
|
||||
AssertFatal (fd >= 0, "File descriptor (%d) is invalid!\n", fd);
|
||||
|
||||
thread_id = TASK_GET_THREAD_ID(task_id);
|
||||
|
||||
/* Add the event fd to the list of monitored events */
|
||||
if (epoll_ctl(itti_desc.threads[thread_id].epoll_fd, EPOLL_CTL_DEL, fd, NULL) != 0) {
|
||||
/* Always assert on this condition */
|
||||
AssertFatal (0, "epoll_ctl (EPOLL_CTL_DEL) failed for task %s, fd %d: %s!\n",
|
||||
itti_get_task_name(task_id), fd, strerror(errno));
|
||||
}
|
||||
|
||||
itti_desc.threads[thread_id].nb_events--;
|
||||
itti_desc.threads[thread_id].events = realloc(
|
||||
itti_desc.threads[thread_id].events,
|
||||
itti_desc.threads[thread_id].nb_events * sizeof(struct epoll_event));
|
||||
}
|
||||
|
||||
int itti_get_events(task_id_t task_id, struct epoll_event **events)
|
||||
{
|
||||
thread_id_t thread_id;
|
||||
|
||||
AssertFatal (task_id < itti_desc.task_max, "Task id (%d) is out of range (%d)\n", task_id, itti_desc.task_max);
|
||||
|
||||
thread_id = TASK_GET_THREAD_ID(task_id);
|
||||
*events = itti_desc.threads[thread_id].events;
|
||||
|
||||
return itti_desc.threads[thread_id].epoll_nb_events;
|
||||
}
|
||||
|
||||
static inline void itti_receive_msg_internal_event_fd(task_id_t task_id, uint8_t polling, MessageDef **received_msg)
|
||||
{
|
||||
thread_id_t thread_id;
|
||||
int epoll_ret = 0;
|
||||
int epoll_timeout = 0;
|
||||
int i;
|
||||
|
||||
AssertFatal (task_id < itti_desc.task_max, "Task id (%d) is out of range (%d)!\n", task_id, itti_desc.task_max);
|
||||
AssertFatal (received_msg != NULL, "Received message is NULL!\n");
|
||||
|
||||
thread_id = TASK_GET_THREAD_ID(task_id);
|
||||
*received_msg = NULL;
|
||||
|
||||
if (polling) {
|
||||
/* In polling mode we set the timeout to 0 causing epoll_wait to return
|
||||
* immediately.
|
||||
*/
|
||||
epoll_timeout = 0;
|
||||
} else {
|
||||
/* timeout = -1 causes the epoll_wait to wait indefinitely.
|
||||
*/
|
||||
epoll_timeout = -1;
|
||||
}
|
||||
|
||||
do {
|
||||
epoll_ret = epoll_wait(itti_desc.threads[thread_id].epoll_fd,
|
||||
itti_desc.threads[thread_id].events,
|
||||
itti_desc.threads[thread_id].nb_events,
|
||||
epoll_timeout);
|
||||
} while (epoll_ret < 0 && errno == EINTR);
|
||||
|
||||
if (epoll_ret < 0) {
|
||||
AssertFatal (0, "epoll_wait failed for task %s: %s!\n", itti_get_task_name(task_id), strerror(errno));
|
||||
}
|
||||
|
||||
if (epoll_ret == 0 && polling) {
|
||||
/* No data to read -> return */
|
||||
return;
|
||||
}
|
||||
|
||||
itti_desc.threads[thread_id].epoll_nb_events = epoll_ret;
|
||||
|
||||
for (i = 0; i < epoll_ret; i++) {
|
||||
/* Check if there is an event for ITTI for the event fd */
|
||||
if ((itti_desc.threads[thread_id].events[i].events & EPOLLIN) &&
|
||||
(itti_desc.threads[thread_id].events[i].data.fd == itti_desc.threads[thread_id].task_event_fd)) {
|
||||
struct message_list_s *message = NULL;
|
||||
eventfd_t sem_counter;
|
||||
ssize_t read_ret;
|
||||
int result;
|
||||
|
||||
/* Read will always return 1 */
|
||||
read_ret = read (itti_desc.threads[thread_id].task_event_fd, &sem_counter, sizeof(sem_counter));
|
||||
AssertFatal (read_ret == sizeof(sem_counter), "Read from task message FD (%d) failed (%d/%d)!\n", thread_id, (int) read_ret, (int) sizeof(sem_counter));
|
||||
|
||||
if (lfds611_queue_dequeue (itti_desc.tasks[task_id].message_queue, (void **) &message) == 0) {
|
||||
/* No element in list -> this should not happen */
|
||||
AssertFatal (0, "No message in queue for task %d while there are %d events and some for the messages queue!\n", task_id, epoll_ret);
|
||||
}
|
||||
|
||||
AssertFatal(message != NULL, "Message from message queue is NULL!\n");
|
||||
*received_msg = message->msg;
|
||||
|
||||
|
||||
result = itti_free (ITTI_MSG_ORIGIN_ID(*received_msg), message);
|
||||
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
||||
|
||||
|
||||
/* Mark that the event has been processed */
|
||||
itti_desc.threads[thread_id].events[i].events &= ~EPOLLIN;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void itti_receive_msg(task_id_t task_id, MessageDef **received_msg)
|
||||
{
|
||||
|
||||
itti_receive_msg_internal_event_fd(task_id, 0, received_msg);
|
||||
|
||||
}
|
||||
|
||||
void itti_poll_msg(task_id_t task_id, MessageDef **received_msg)
|
||||
{
|
||||
AssertFatal (task_id < itti_desc.task_max, "Task id (%d) is out of range (%d)!\n", task_id, itti_desc.task_max);
|
||||
|
||||
*received_msg = NULL;
|
||||
|
||||
{
|
||||
struct message_list_s *message;
|
||||
|
||||
if (lfds611_queue_dequeue (itti_desc.tasks[task_id].message_queue, (void **) &message) == 1) {
|
||||
int result;
|
||||
|
||||
*received_msg = message->msg;
|
||||
result = itti_free (ITTI_MSG_ORIGIN_ID(*received_msg), message);
|
||||
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
||||
}
|
||||
}
|
||||
|
||||
if (*received_msg == NULL) {
|
||||
ITTI_DEBUG(ITTI_DEBUG_POLL, " No message in queue[(%u:%s)]\n", task_id, itti_get_task_name(task_id));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int itti_create_task(task_id_t task_id, void *(*start_routine)(void *), void *args_p)
|
||||
{
|
||||
thread_id_t thread_id = TASK_GET_THREAD_ID(task_id);
|
||||
int result;
|
||||
|
||||
AssertFatal (start_routine != NULL, "Start routine is NULL!\n");
|
||||
AssertFatal (thread_id < itti_desc.thread_max, "Thread id (%d) is out of range (%d)!\n", thread_id, itti_desc.thread_max);
|
||||
AssertFatal (itti_desc.threads[thread_id].task_state == TASK_STATE_NOT_CONFIGURED, "Task %d, thread %d state is not correct (%d)!\n",
|
||||
task_id, thread_id, itti_desc.threads[thread_id].task_state);
|
||||
|
||||
itti_desc.threads[thread_id].task_state = TASK_STATE_STARTING;
|
||||
|
||||
ITTI_DEBUG(ITTI_DEBUG_INIT, " Creating thread for task %s ...\n", itti_get_task_name(task_id));
|
||||
|
||||
result = pthread_create (&itti_desc.threads[thread_id].task_thread, NULL, start_routine, args_p);
|
||||
AssertFatal (result >= 0, "Thread creation for task %d, thread %d failed (%d)!\n", task_id, thread_id, result);
|
||||
char name[16];
|
||||
snprintf( name, sizeof(name), "ITTI %d", thread_id );
|
||||
pthread_setname_np( itti_desc.threads[thread_id].task_thread, name );
|
||||
|
||||
itti_desc.created_tasks ++;
|
||||
|
||||
/* Wait till the thread is completely ready */
|
||||
while (itti_desc.threads[thread_id].task_state != TASK_STATE_READY)
|
||||
usleep (1000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void itti_set_task_real_time(task_id_t task_id)
|
||||
{
|
||||
thread_id_t thread_id = TASK_GET_THREAD_ID(task_id);
|
||||
|
||||
DevCheck(thread_id < itti_desc.thread_max, thread_id, itti_desc.thread_max, 0);
|
||||
|
||||
itti_desc.threads[thread_id].real_time = TRUE;
|
||||
}
|
||||
|
||||
void itti_wait_ready(int wait_tasks)
|
||||
{
|
||||
itti_desc.wait_tasks = wait_tasks;
|
||||
|
||||
ITTI_DEBUG(ITTI_DEBUG_INIT,
|
||||
" wait for tasks: %s, created tasks %d, ready tasks %d\n",
|
||||
itti_desc.wait_tasks ? "yes" : "no",
|
||||
itti_desc.created_tasks,
|
||||
itti_desc.ready_tasks);
|
||||
|
||||
AssertFatal (itti_desc.created_tasks == itti_desc.ready_tasks, "Number of created tasks (%d) does not match ready tasks (%d), wait task %d!\n",
|
||||
itti_desc.created_tasks, itti_desc.ready_tasks, itti_desc.wait_tasks);
|
||||
}
|
||||
|
||||
void itti_mark_task_ready(task_id_t task_id)
|
||||
{
|
||||
thread_id_t thread_id = TASK_GET_THREAD_ID(task_id);
|
||||
|
||||
AssertFatal (thread_id < itti_desc.thread_max, "Thread id (%d) is out of range (%d)!\n", thread_id, itti_desc.thread_max);
|
||||
|
||||
/* Mark the thread as using LFDS queue */
|
||||
lfds611_queue_use(itti_desc.tasks[task_id].message_queue);
|
||||
|
||||
#if defined(UE_EXPANSION) || defined(RTAI)
|
||||
/* Assign low priority to created threads */
|
||||
{
|
||||
struct sched_param sched_param;
|
||||
sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO) + 1;
|
||||
sched_setscheduler(0, SCHED_FIFO, &sched_param);
|
||||
}
|
||||
#endif
|
||||
|
||||
itti_desc.threads[thread_id].task_state = TASK_STATE_READY;
|
||||
itti_desc.ready_tasks ++;
|
||||
|
||||
while (itti_desc.wait_tasks != 0) {
|
||||
usleep (10000);
|
||||
}
|
||||
|
||||
ITTI_DEBUG(ITTI_DEBUG_INIT, " task %s started\n", itti_get_task_name(task_id));
|
||||
}
|
||||
|
||||
void itti_exit_task(void)
|
||||
{
|
||||
task_id_t task_id = itti_get_current_task_id();
|
||||
thread_id_t thread_id = TASK_GET_THREAD_ID(task_id);
|
||||
|
||||
#if defined(OAI_EMU) || defined(RTAI)
|
||||
if (task_id > TASK_UNKNOWN) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_ITTI_RECV_MSG,
|
||||
__sync_and_and_fetch (&itti_desc.vcd_receive_msg, ~(1L << task_id)));
|
||||
}
|
||||
#endif
|
||||
|
||||
itti_desc.threads[thread_id].task_state = TASK_STATE_NOT_CONFIGURED;
|
||||
itti_desc.created_tasks--;
|
||||
ITTI_DEBUG(ITTI_DEBUG_EXIT, "Thread for task %s (%d) exits\n", itti_get_task_name(task_id), task_id);
|
||||
pthread_exit (NULL);
|
||||
}
|
||||
|
||||
void itti_terminate_tasks(task_id_t task_id)
|
||||
{
|
||||
// Sends Terminate signals to all tasks.
|
||||
itti_send_terminate_message (task_id);
|
||||
|
||||
if (itti_desc.thread_handling_signals) {
|
||||
pthread_kill (itti_desc.thread_ref, SIGUSR1);
|
||||
}
|
||||
|
||||
pthread_exit (NULL);
|
||||
}
|
||||
|
||||
int itti_init(task_id_t task_max, thread_id_t thread_max, MessagesIds messages_id_max, const task_info_t *tasks_info,
|
||||
const message_info_t *messages_info)
|
||||
{
|
||||
task_id_t task_id;
|
||||
thread_id_t thread_id;
|
||||
int ret;
|
||||
|
||||
itti_desc.message_number = 1;
|
||||
|
||||
ITTI_DEBUG(ITTI_DEBUG_INIT, " Init: %d tasks, %d threads, %d messages\n", task_max, thread_max, messages_id_max);
|
||||
|
||||
CHECK_INIT_RETURN(signal_mask());
|
||||
|
||||
/* Saves threads and messages max values */
|
||||
itti_desc.task_max = task_max;
|
||||
itti_desc.thread_max = thread_max;
|
||||
itti_desc.messages_id_max = messages_id_max;
|
||||
itti_desc.thread_handling_signals = FALSE;
|
||||
itti_desc.tasks_info = tasks_info;
|
||||
itti_desc.messages_info = messages_info;
|
||||
|
||||
/* Allocates memory for tasks info */
|
||||
itti_desc.tasks = calloc (itti_desc.task_max, sizeof(task_desc_t));
|
||||
|
||||
/* Allocates memory for threads info */
|
||||
itti_desc.threads = calloc (itti_desc.thread_max, sizeof(thread_desc_t));
|
||||
|
||||
/* Initializing each queue and related stuff */
|
||||
for (task_id = TASK_FIRST; task_id < itti_desc.task_max; task_id++) {
|
||||
ITTI_DEBUG(ITTI_DEBUG_INIT, " Initializing %stask %s%s%s\n",
|
||||
itti_desc.tasks_info[task_id].parent_task != TASK_UNKNOWN ? "sub-" : "",
|
||||
itti_desc.tasks_info[task_id].name,
|
||||
itti_desc.tasks_info[task_id].parent_task != TASK_UNKNOWN ? " with parent " : "",
|
||||
itti_desc.tasks_info[task_id].parent_task != TASK_UNKNOWN ?
|
||||
itti_get_task_name(itti_desc.tasks_info[task_id].parent_task) : "");
|
||||
|
||||
ITTI_DEBUG(ITTI_DEBUG_INIT, " Creating queue of message of size %u\n", itti_desc.tasks_info[task_id].queue_size);
|
||||
|
||||
ret = lfds611_queue_new(&itti_desc.tasks[task_id].message_queue, itti_desc.tasks_info[task_id].queue_size);
|
||||
|
||||
if (0 == ret) {
|
||||
AssertFatal (0, "lfds611_queue_new failed for task %s!\n", itti_get_task_name(task_id));
|
||||
}
|
||||
}
|
||||
|
||||
/* Initializing each thread */
|
||||
for (thread_id = THREAD_FIRST; thread_id < itti_desc.thread_max; thread_id++) {
|
||||
itti_desc.threads[thread_id].task_state = TASK_STATE_NOT_CONFIGURED;
|
||||
|
||||
itti_desc.threads[thread_id].epoll_fd = epoll_create1(0);
|
||||
|
||||
if (itti_desc.threads[thread_id].epoll_fd == -1) {
|
||||
/* Always assert on this condition */
|
||||
AssertFatal (0, "Failed to create new epoll fd: %s!\n", strerror(errno));
|
||||
}
|
||||
|
||||
itti_desc.threads[thread_id].task_event_fd = eventfd(0, EFD_SEMAPHORE);
|
||||
|
||||
if (itti_desc.threads[thread_id].task_event_fd == -1) {
|
||||
/* Always assert on this condition */
|
||||
AssertFatal (0, " eventfd failed: %s!\n", strerror(errno));
|
||||
}
|
||||
|
||||
itti_desc.threads[thread_id].nb_events = 1;
|
||||
|
||||
itti_desc.threads[thread_id].events = calloc(1, sizeof(struct epoll_event));
|
||||
|
||||
itti_desc.threads[thread_id].events->events = EPOLLIN | EPOLLERR;
|
||||
itti_desc.threads[thread_id].events->data.fd = itti_desc.threads[thread_id].task_event_fd;
|
||||
|
||||
/* Add the event fd to the list of monitored events */
|
||||
if (epoll_ctl(itti_desc.threads[thread_id].epoll_fd, EPOLL_CTL_ADD,
|
||||
itti_desc.threads[thread_id].task_event_fd, itti_desc.threads[thread_id].events) != 0) {
|
||||
/* Always assert on this condition */
|
||||
AssertFatal (0, " epoll_ctl (EPOLL_CTL_ADD) failed: %s!\n", strerror(errno));
|
||||
}
|
||||
|
||||
ITTI_DEBUG(ITTI_DEBUG_EVEN_FD, " Successfully subscribed fd %d for thread %d\n",
|
||||
itti_desc.threads[thread_id].task_event_fd, thread_id);
|
||||
|
||||
}
|
||||
|
||||
itti_desc.running = 1;
|
||||
itti_desc.wait_tasks = 0;
|
||||
itti_desc.created_tasks = 0;
|
||||
itti_desc.ready_tasks = 0;
|
||||
CHECK_INIT_RETURN(timer_init ());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void itti_wait_tasks_end(void)
|
||||
{
|
||||
int end = 0;
|
||||
int thread_id;
|
||||
task_id_t task_id;
|
||||
int ready_tasks;
|
||||
int result;
|
||||
int retries = 10;
|
||||
|
||||
itti_desc.thread_handling_signals = TRUE;
|
||||
itti_desc.thread_ref=pthread_self ();
|
||||
|
||||
/* Handle signals here */
|
||||
while (end == 0) {
|
||||
signal_handle (&end);
|
||||
}
|
||||
|
||||
printf("closing all tasks\n");
|
||||
sleep(1);
|
||||
|
||||
do {
|
||||
ready_tasks = 0;
|
||||
|
||||
task_id = TASK_FIRST;
|
||||
|
||||
for (thread_id = THREAD_FIRST; thread_id < itti_desc.thread_max; thread_id++) {
|
||||
/* Skip tasks which are not running */
|
||||
if (itti_desc.threads[thread_id].task_state == TASK_STATE_READY) {
|
||||
while (thread_id != TASK_GET_THREAD_ID(task_id)) {
|
||||
task_id++;
|
||||
}
|
||||
|
||||
result = pthread_tryjoin_np (itti_desc.threads[thread_id].task_thread, NULL);
|
||||
|
||||
ITTI_DEBUG(ITTI_DEBUG_EXIT, " Thread %s join status %d\n", itti_get_task_name(task_id), result);
|
||||
|
||||
if (result == 0) {
|
||||
/* Thread has terminated */
|
||||
itti_desc.threads[thread_id].task_state = TASK_STATE_ENDED;
|
||||
} else {
|
||||
/* Thread is still running, count it */
|
||||
ready_tasks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ready_tasks > 0) {
|
||||
usleep (100 * 1000);
|
||||
}
|
||||
} while ((ready_tasks > 0) && (retries--)&& (!end) );
|
||||
|
||||
printf("ready_tasks %d\n",ready_tasks);
|
||||
|
||||
itti_desc.running = 0;
|
||||
|
||||
if (ready_tasks > 0) {
|
||||
ITTI_DEBUG(ITTI_DEBUG_ISSUES, " Some threads are still running, force exit\n");
|
||||
exit (0);
|
||||
}
|
||||
}
|
||||
|
||||
void itti_send_terminate_message(task_id_t task_id)
|
||||
{
|
||||
MessageDef *terminate_message_p;
|
||||
|
||||
terminate_message_p = itti_alloc_new_message (task_id, TERMINATE_MESSAGE);
|
||||
|
||||
itti_send_broadcast_message (terminate_message_p);
|
||||
}
|
||||
@@ -1,235 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/** @defgroup _intertask_interface_impl_ Intertask Interface Mechanisms
|
||||
* Implementation
|
||||
* @ingroup _ref_implementation_
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <sys/epoll.h>
|
||||
|
||||
#ifndef INTERTASK_INTERFACE_H_
|
||||
#define INTERTASK_INTERFACE_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "intertask_interface_conf.h"
|
||||
#include "intertask_interface_types.h"
|
||||
|
||||
#define ITTI_MSG_ID(mSGpTR) ((mSGpTR)->ittiMsgHeader.messageId)
|
||||
#define ITTI_MSG_ORIGIN_ID(mSGpTR) ((mSGpTR)->ittiMsgHeader.originTaskId)
|
||||
#define ITTI_MSG_DESTINATION_ID(mSGpTR) ((mSGpTR)->ittiMsgHeader.destinationTaskId)
|
||||
#define ITTI_MSG_INSTANCE(mSGpTR) ((mSGpTR)->ittiMsgHeader.instance)
|
||||
#define ITTI_MSG_NAME(mSGpTR) itti_get_message_name(ITTI_MSG_ID(mSGpTR))
|
||||
#define ITTI_MSG_ORIGIN_NAME(mSGpTR) itti_get_task_name(ITTI_MSG_ORIGIN_ID(mSGpTR))
|
||||
#define ITTI_MSG_DESTINATION_NAME(mSGpTR) itti_get_task_name(ITTI_MSG_DESTINATION_ID(mSGpTR))
|
||||
|
||||
/* Make the message number platform specific */
|
||||
typedef unsigned long message_number_t;
|
||||
#define MESSAGE_NUMBER_SIZE (sizeof(unsigned long))
|
||||
|
||||
typedef enum message_priorities_e {
|
||||
MESSAGE_PRIORITY_MAX = 100,
|
||||
MESSAGE_PRIORITY_MAX_LEAST = 85,
|
||||
MESSAGE_PRIORITY_MED_PLUS = 70,
|
||||
MESSAGE_PRIORITY_MED = 55,
|
||||
MESSAGE_PRIORITY_MED_LEAST = 40,
|
||||
MESSAGE_PRIORITY_MIN_PLUS = 25,
|
||||
MESSAGE_PRIORITY_MIN = 10,
|
||||
} message_priorities_t;
|
||||
|
||||
typedef struct message_info_s {
|
||||
task_id_t id;
|
||||
message_priorities_t priority;
|
||||
/* Message payload size */
|
||||
MessageHeaderSize size;
|
||||
/* Printable name */
|
||||
const char * const name;
|
||||
} message_info_t;
|
||||
|
||||
typedef enum task_priorities_e {
|
||||
TASK_PRIORITY_MAX = 100,
|
||||
TASK_PRIORITY_MAX_LEAST = 85,
|
||||
TASK_PRIORITY_MED_PLUS = 70,
|
||||
TASK_PRIORITY_MED = 55,
|
||||
TASK_PRIORITY_MED_LEAST = 40,
|
||||
TASK_PRIORITY_MIN_PLUS = 25,
|
||||
TASK_PRIORITY_MIN = 10,
|
||||
} task_priorities_t;
|
||||
|
||||
typedef struct task_info_s {
|
||||
thread_id_t thread;
|
||||
task_id_t parent_task;
|
||||
task_priorities_t priority;
|
||||
unsigned int queue_size;
|
||||
/* Printable name */
|
||||
const char * const name;
|
||||
} task_info_t;
|
||||
|
||||
/** \brief Update the itti LTE time reference for messages
|
||||
\param current reference frame
|
||||
\param current reference slot
|
||||
@returns < 0 on failure, 0 otherwise
|
||||
**/
|
||||
void itti_update_lte_time(uint32_t frame, uint8_t slot);
|
||||
|
||||
/** \brief Send a broadcast message to every task
|
||||
\param message_p Pointer to the message to send
|
||||
@returns < 0 on failure, 0 otherwise
|
||||
**/
|
||||
int itti_send_broadcast_message(MessageDef *message_p);
|
||||
|
||||
/** \brief Send a message to a task (could be itself)
|
||||
\param task_id Task ID
|
||||
\param instance Instance of the task used for virtualization
|
||||
\param message Pointer to the message to send
|
||||
@returns -1 on failure, 0 otherwise
|
||||
**/
|
||||
int itti_send_msg_to_task(task_id_t task_id, instance_t instance, MessageDef *message);
|
||||
|
||||
/* TODO: this is a hack. Almost no caller of itti_send_msg_to_task checks
|
||||
* the return value so it has been changed to crash the program in case
|
||||
* of failure instead of returning -1 as the documentation above says.
|
||||
* The RLC UM code may receive too much data when doing UDP at a higher
|
||||
* throughput than the link allows and so for this specific case we need
|
||||
* a version that actually returns -1 on failure.
|
||||
*
|
||||
* This needs to be cleaned at some point.
|
||||
*/
|
||||
/* look for HACK_RLC_UM_LIMIT for others places related to the hack. Please do not remove this comment. */
|
||||
int itti_try_send_msg_to_task(task_id_t task_id, instance_t instance, MessageDef *message);
|
||||
|
||||
/** \brief Add a new fd to monitor.
|
||||
* NOTE: it is up to the user to read data associated with the fd
|
||||
* \param task_id Task ID of the receiving task
|
||||
* \param fd The file descriptor to monitor
|
||||
**/
|
||||
void itti_subscribe_event_fd(task_id_t task_id, int fd);
|
||||
|
||||
/** \brief Remove a fd from the list of fd to monitor
|
||||
* \param task_id Task ID of the task
|
||||
* \param fd The file descriptor to remove
|
||||
**/
|
||||
void itti_unsubscribe_event_fd(task_id_t task_id, int fd);
|
||||
|
||||
/** \brief Return the list of events excluding the fd associated with itti
|
||||
* \param task_id Task ID of the task
|
||||
* \param events events list
|
||||
* @returns number of events to handle
|
||||
**/
|
||||
int itti_get_events(task_id_t task_id, struct epoll_event **events);
|
||||
|
||||
/** \brief Retrieves a message in the queue associated to task_id.
|
||||
* If the queue is empty, the thread is blocked till a new message arrives.
|
||||
\param task_id Task ID of the receiving task
|
||||
\param received_msg Pointer to the allocated message
|
||||
**/
|
||||
void itti_receive_msg(task_id_t task_id, MessageDef **received_msg);
|
||||
|
||||
/** \brief Try to retrieves a message in the queue associated to task_id.
|
||||
\param task_id Task ID of the receiving task
|
||||
\param received_msg Pointer to the allocated message
|
||||
**/
|
||||
void itti_poll_msg(task_id_t task_id, MessageDef **received_msg);
|
||||
|
||||
/** \brief Start thread associated to the task
|
||||
* \param task_id task to start
|
||||
* \param start_routine entry point for the task
|
||||
* \param args_p Optional argument to pass to the start routine
|
||||
* @returns -1 on failure, 0 otherwise
|
||||
**/
|
||||
int itti_create_task(task_id_t task_id,
|
||||
void *(*start_routine) (void *),
|
||||
void *args_p);
|
||||
|
||||
/** \brief Mark the task as a real time task
|
||||
* \param task_id task to mark as real time
|
||||
**/
|
||||
void itti_set_task_real_time(task_id_t task_id);
|
||||
|
||||
/** \brief Indicates to ITTI if newly created tasks should wait for all tasks to be ready
|
||||
* \param wait_tasks non 0 to make new created tasks to wait, 0 to let created tasks to run
|
||||
**/
|
||||
void itti_wait_ready(int wait_tasks);
|
||||
|
||||
/** \brief Mark the task as in ready state
|
||||
* \param task_id task to mark as ready
|
||||
**/
|
||||
void itti_mark_task_ready(task_id_t task_id);
|
||||
|
||||
/** \brief Exit the current task.
|
||||
**/
|
||||
void itti_exit_task(void);
|
||||
|
||||
/** \brief Indicate that the task is completed and initiate termination of all tasks.
|
||||
* \param task_id task that is completed
|
||||
**/
|
||||
void itti_terminate_tasks(task_id_t task_id);
|
||||
|
||||
/** \brief Return the printable string associated with the message
|
||||
* \param message_id Id of the message
|
||||
**/
|
||||
const char *itti_get_message_name(MessagesIds message_id);
|
||||
|
||||
/** \brief Return the printable string associated with a task id
|
||||
* \param thread_id Id of the task
|
||||
**/
|
||||
const char *itti_get_task_name(task_id_t task_id);
|
||||
|
||||
/** \brief Alloc and memset(0) a new itti message.
|
||||
* \param origin_task_id Task ID of the sending task
|
||||
* \param message_id Message ID
|
||||
* @returns NULL in case of failure or newly allocated mesage ref
|
||||
**/
|
||||
MessageDef *itti_alloc_new_message(
|
||||
task_id_t origin_task_id,
|
||||
MessagesIds message_id);
|
||||
|
||||
/** \brief Alloc and memset(0) a new itti message.
|
||||
* \param origin_task_id Task ID of the sending task
|
||||
* \param message_id Message ID
|
||||
* \param size size of the payload to send
|
||||
* @returns NULL in case of failure or newly allocated mesage ref
|
||||
**/
|
||||
MessageDef *itti_alloc_new_message_sized(
|
||||
task_id_t origin_task_id,
|
||||
MessagesIds message_id,
|
||||
MessageHeaderSize size);
|
||||
|
||||
/** \brief handle signals and wait for all threads to join when the process complete.
|
||||
* This function should be called from the main thread after having created all ITTI tasks.
|
||||
**/
|
||||
void itti_wait_tasks_end(void);
|
||||
|
||||
/** \brief Send a termination message to all tasks.
|
||||
* \param task_id task that is broadcasting the message.
|
||||
**/
|
||||
void itti_send_terminate_message(task_id_t task_id);
|
||||
|
||||
void *itti_malloc(task_id_t origin_task_id, task_id_t destination_task_id, ssize_t size);
|
||||
|
||||
int itti_free(task_id_t task_id, void *ptr);
|
||||
|
||||
#endif /* INTERTASK_INTERFACE_H_ */
|
||||
/* @} */
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/** @defgroup _intertask_interface_impl_ Intertask Interface Mechanisms
|
||||
* Implementation
|
||||
* @ingroup _ref_implementation_
|
||||
* @{
|
||||
*/
|
||||
|
||||
/********************************************************************************
|
||||
*
|
||||
* !!! This header should only be included by the file that initialize
|
||||
* the intertask interface module for the process !!!
|
||||
*
|
||||
* Other files should include "intertask_interface.h"
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef INTERTASK_INTERFACE_INIT_H_
|
||||
#define INTERTASK_INTERFACE_INIT_H_
|
||||
|
||||
#include "intertask_interface.h"
|
||||
|
||||
#ifndef CHECK_PROTOTYPE_ONLY
|
||||
|
||||
/* Map task id to printable name. */
|
||||
const task_info_t tasks_info[] = {
|
||||
{0, TASK_UNKNOWN, 0, 0, "TASK_UNKNOWN"},
|
||||
#define TASK_DEF(tHREADiD, pRIO, qUEUEsIZE) { tHREADiD##_THREAD, TASK_UNKNOWN, pRIO, qUEUEsIZE, #tHREADiD },
|
||||
#define SUB_TASK_DEF(tHREADiD, sUBtASKiD, qUEUEsIZE) { sUBtASKiD##_THREAD, tHREADiD##_THREAD, 0, qUEUEsIZE, #sUBtASKiD },
|
||||
#include <tasks_def.h>
|
||||
#undef SUB_TASK_DEF
|
||||
#undef TASK_DEF
|
||||
};
|
||||
|
||||
/* Map message id to message information */
|
||||
const message_info_t messages_info[] = {
|
||||
#define MESSAGE_DEF(iD, pRIO, sTRUCT, fIELDnAME) { iD, pRIO, sizeof(sTRUCT), #iD },
|
||||
#include <messages_def.h>
|
||||
#undef MESSAGE_DEF
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/** \brief Init function for the intertask interface. Init queues, Mutexes and Cond vars.
|
||||
* \param thread_max Maximum number of threads
|
||||
* \param messages_id_max Maximum message id
|
||||
* \param threads_name Pointer on the threads name information as created by this include file
|
||||
* \param messages_info Pointer on messages information as created by this include file
|
||||
**/
|
||||
int itti_init(task_id_t task_max, thread_id_t thread_max, MessagesIds messages_id_max, const task_info_t *tasks_info,
|
||||
const message_info_t *messages_info);
|
||||
|
||||
#endif /* INTERTASK_INTERFACE_INIT_H_ */
|
||||
/* @} */
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/** @defgroup _intertask_interface_impl_ Intertask Interface Mechanisms
|
||||
* Implementation
|
||||
* @ingroup _ref_implementation_
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef INTERTASK_INTERFACE_TYPES_H_
|
||||
#define INTERTASK_INTERFACE_TYPES_H_
|
||||
|
||||
#include "itti_types.h"
|
||||
#include "platform_types.h"
|
||||
|
||||
/* Defines to handle bit fields on unsigned long values */
|
||||
#define UL_BIT_MASK(lENGTH) ((1UL << (lENGTH)) - 1UL)
|
||||
#define UL_BIT_SHIFT(vALUE, oFFSET) ((vALUE) << (oFFSET))
|
||||
#define UL_BIT_UNSHIFT(vALUE, oFFSET) ((vALUE) >> (oFFSET))
|
||||
|
||||
#define UL_FIELD_MASK(oFFSET, lENGTH) UL_BIT_SHIFT(UL_BIT_MASK(lENGTH), (oFFSET))
|
||||
#define UL_FIELD_INSERT(vALUE, fIELD, oFFSET, lENGTH) (((vALUE) & (~UL_FIELD_MASK(oFFSET, lENGTH))) | UL_BIT_SHIFT(((fIELD) & UL_BIT_MASK(lENGTH)), oFFSET))
|
||||
#define UL_FIELD_EXTRACT(vALUE, oFFSET, lENGTH) (UL_BIT_UNSHIFT((vALUE), (oFFSET)) & UL_BIT_MASK(lENGTH))
|
||||
|
||||
/* Definitions of task ID fields */
|
||||
#define TASK_THREAD_ID_OFFSET 8
|
||||
#define TASK_THREAD_ID_LENGTH 8
|
||||
|
||||
#define TASK_SUB_TASK_ID_OFFSET 0
|
||||
#define TASK_SUB_TASK_ID_LENGTH 8
|
||||
|
||||
/* Defines to extract task ID fields */
|
||||
#define TASK_GET_THREAD_ID(tASKiD) (itti_desc.tasks_info[tASKiD].thread)
|
||||
#define TASK_GET_PARENT_TASK_ID(tASKiD) (itti_desc.tasks_info[tASKiD].parent_task)
|
||||
/* Extract the instance from a message */
|
||||
#define ITTI_MESSAGE_GET_INSTANCE(mESSAGE) ((mESSAGE)->ittiMsgHeader.instance)
|
||||
|
||||
#include <messages_types.h>
|
||||
|
||||
/* This enum defines messages ids. Each one is unique. */
|
||||
typedef enum {
|
||||
#define MESSAGE_DEF(iD, pRIO, sTRUCT, fIELDnAME) iD,
|
||||
#include <messages_def.h>
|
||||
#undef MESSAGE_DEF
|
||||
|
||||
MESSAGES_ID_MAX,
|
||||
} MessagesIds;
|
||||
|
||||
//! Thread id of each task
|
||||
typedef enum {
|
||||
THREAD_NULL = 0,
|
||||
|
||||
#define TASK_DEF(tHREADiD, pRIO, qUEUEsIZE) THREAD_##tHREADiD,
|
||||
#define SUB_TASK_DEF(tHREADiD, sUBtASKiD, qUEUEsIZE)
|
||||
#include <tasks_def.h>
|
||||
#undef SUB_TASK_DEF
|
||||
#undef TASK_DEF
|
||||
|
||||
THREAD_MAX,
|
||||
THREAD_FIRST = 1,
|
||||
} thread_id_t;
|
||||
|
||||
//! Sub-tasks id, to defined offset form thread id
|
||||
typedef enum {
|
||||
#define TASK_DEF(tHREADiD, pRIO, qUEUEsIZE) tHREADiD##_THREAD = THREAD_##tHREADiD,
|
||||
#define SUB_TASK_DEF(tHREADiD, sUBtASKiD, qUEUEsIZE) sUBtASKiD##_THREAD = THREAD_##tHREADiD,
|
||||
#include <tasks_def.h>
|
||||
#undef SUB_TASK_DEF
|
||||
#undef TASK_DEF
|
||||
} task_thread_id_t;
|
||||
|
||||
//! Tasks id of each task
|
||||
typedef enum {
|
||||
TASK_UNKNOWN = 0,
|
||||
|
||||
#define TASK_DEF(tHREADiD, pRIO, qUEUEsIZE) tHREADiD,
|
||||
#define SUB_TASK_DEF(tHREADiD, sUBtASKiD, qUEUEsIZE) sUBtASKiD,
|
||||
#include <tasks_def.h>
|
||||
#undef SUB_TASK_DEF
|
||||
#undef TASK_DEF
|
||||
|
||||
TASK_MAX,
|
||||
TASK_FIRST = 1,
|
||||
} task_id_t;
|
||||
|
||||
typedef union msg_s {
|
||||
#define MESSAGE_DEF(iD, pRIO, sTRUCT, fIELDnAME) sTRUCT fIELDnAME;
|
||||
#include <messages_def.h>
|
||||
#undef MESSAGE_DEF
|
||||
} msg_t;
|
||||
|
||||
typedef uint16_t MessageHeaderSize;
|
||||
|
||||
typedef struct itti_lte_time_s {
|
||||
uint32_t frame;
|
||||
uint8_t slot;
|
||||
} itti_lte_time_t;
|
||||
|
||||
/** @struct MessageHeader
|
||||
* @brief Message Header structure for inter-task communication.
|
||||
*/
|
||||
typedef struct MessageHeader_s {
|
||||
MessagesIds messageId; /**< Unique message id as referenced in enum MessagesIds */
|
||||
|
||||
task_id_t originTaskId; /**< ID of the sender task */
|
||||
task_id_t destinationTaskId; /**< ID of the destination task */
|
||||
instance_t instance; /**< Task instance for virtualization */
|
||||
|
||||
MessageHeaderSize ittiMsgSize; /**< Message size (not including header size) */
|
||||
|
||||
itti_lte_time_t lte_time; /**< Reference LTE time */
|
||||
} MessageHeader;
|
||||
|
||||
/** @struct MessageDef
|
||||
* @brief Message structure for inter-task communication.
|
||||
* \internal
|
||||
* The attached attribute \c __packed__ is neccessary, because the memory allocation code expects \ref ittiMsg directly following \ref ittiMsgHeader.
|
||||
*/
|
||||
typedef struct __attribute__ ((__packed__)) MessageDef_s {
|
||||
MessageHeader ittiMsgHeader; /**< Message header */
|
||||
msg_t ittiMsg; /**< Union of payloads as defined in x_messages_def.h headers */
|
||||
} MessageDef;
|
||||
|
||||
#endif /* INTERTASK_INTERFACE_TYPES_H_ */
|
||||
/* @} */
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/* This message asks for task initialization */
|
||||
MESSAGE_DEF(INITIALIZE_MESSAGE, MESSAGE_PRIORITY_MED, IttiMsgEmpty, initialize_message)
|
||||
|
||||
/* This message asks for task activation */
|
||||
MESSAGE_DEF(ACTIVATE_MESSAGE, MESSAGE_PRIORITY_MED, IttiMsgEmpty, activate_message)
|
||||
|
||||
/* This message asks for task deactivation */
|
||||
MESSAGE_DEF(DEACTIVATE_MESSAGE, MESSAGE_PRIORITY_MED, IttiMsgEmpty, deactivate_message)
|
||||
|
||||
/* This message asks for task termination */
|
||||
MESSAGE_DEF(TERMINATE_MESSAGE, MESSAGE_PRIORITY_MAX, IttiMsgEmpty, terminate_message)
|
||||
|
||||
/* Test message used for debug */
|
||||
MESSAGE_DEF(MESSAGE_TEST, MESSAGE_PRIORITY_MED, IttiMsgEmpty, message_test)
|
||||
|
||||
/* Error message */
|
||||
MESSAGE_DEF(ERROR_LOG, MESSAGE_PRIORITY_MAX, IttiMsgEmpty, error_log)
|
||||
/* Warning message */
|
||||
MESSAGE_DEF(WARNING_LOG, MESSAGE_PRIORITY_MAX, IttiMsgEmpty, warning_log)
|
||||
/* Notice message */
|
||||
MESSAGE_DEF(NOTICE_LOG, MESSAGE_PRIORITY_MED, IttiMsgEmpty, notice_log)
|
||||
/* Info message */
|
||||
MESSAGE_DEF(INFO_LOG, MESSAGE_PRIORITY_MED, IttiMsgEmpty, info_log)
|
||||
/* Debug message */
|
||||
MESSAGE_DEF(DEBUG_LOG, MESSAGE_PRIORITY_MED, IttiMsgEmpty, debug_log)
|
||||
|
||||
/* Generic log message for text */
|
||||
MESSAGE_DEF(GENERIC_LOG, MESSAGE_PRIORITY_MED, IttiMsgEmpty, generic_log)
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*
|
||||
* intertask_messages_types.h
|
||||
*
|
||||
* Created on: Jan 14, 2014
|
||||
* Author: laurent winckel
|
||||
*/
|
||||
|
||||
#ifndef INTERTASK_MESSAGES_TYPES_H_
|
||||
#define INTERTASK_MESSAGES_TYPES_H_
|
||||
|
||||
typedef struct IttiMsgEmpty_s {
|
||||
} IttiMsgEmpty;
|
||||
|
||||
typedef struct IttiMsgText_s {
|
||||
uint32_t size;
|
||||
char text[];
|
||||
} IttiMsgText;
|
||||
|
||||
#endif /* INTERTASK_MESSAGES_TYPES_H_ */
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/** @brief Intertask Interface common types
|
||||
* Contains type definitions used for generating and parsing ITTI messages.
|
||||
* @author Laurent Winckel <laurent.winckel@eurecom.fr>
|
||||
*/
|
||||
|
||||
#ifndef _ITTI_TYPES_H_
|
||||
#define _ITTI_TYPES_H_
|
||||
|
||||
/* The current file is included in the ue_ip.ko compilation.
|
||||
* For it to work we need to include linux/types.h and
|
||||
* not stdint.h.
|
||||
* A solution to this problem is to use #ifndef __KERNEL__.
|
||||
* Maybe a better solution would be to clean things up
|
||||
* so that ue_ip.ko does not include the current file.
|
||||
*/
|
||||
#ifndef __KERNEL__
|
||||
# include <stdint.h>
|
||||
#else
|
||||
# include <linux/types.h>
|
||||
#endif
|
||||
|
||||
#define CHARS_TO_UINT32(c1, c2, c3, c4) (((c4) << 24) | ((c3) << 16) | ((c2) << 8) | (c1))
|
||||
|
||||
#define MESSAGE_NUMBER_CHAR_FORMAT "%11u"
|
||||
|
||||
/* Intertask message types */
|
||||
enum itti_message_types_e {
|
||||
ITTI_DUMP_XML_DEFINITION = CHARS_TO_UINT32 ('\n', 'I', 'x', 'd'),
|
||||
ITTI_DUMP_XML_DEFINITION_END = CHARS_TO_UINT32 ('i', 'X', 'D', '\n'),
|
||||
|
||||
ITTI_DUMP_MESSAGE_TYPE = CHARS_TO_UINT32 ('\n', 'I', 'm', 's'),
|
||||
ITTI_DUMP_MESSAGE_TYPE_END = CHARS_TO_UINT32 ('i', 'M', 'S', '\n'),
|
||||
|
||||
ITTI_STATISTIC_MESSAGE_TYPE = CHARS_TO_UINT32 ('\n', 'I', 's', 't'),
|
||||
ITTI_STATISTIC_MESSAGE_TYPE_END = CHARS_TO_UINT32 ('i', 'S', 'T', '\n'),
|
||||
|
||||
/* This signal is not meant to be used by remote analyzer */
|
||||
ITTI_DUMP_EXIT_SIGNAL = CHARS_TO_UINT32 ('e', 'X', 'I', 'T'),
|
||||
};
|
||||
|
||||
typedef uint32_t itti_message_types_t;
|
||||
|
||||
/* Message header is the common part that should never change between
|
||||
* remote process and this one.
|
||||
*/
|
||||
typedef struct {
|
||||
/* The size of this structure */
|
||||
uint32_t message_size;
|
||||
itti_message_types_t message_type;
|
||||
} itti_socket_header_t;
|
||||
|
||||
typedef struct {
|
||||
char message_number_char[12]; /* 9 chars are needed to store an unsigned 32 bits value in decimal, but must be a multiple of 32 bits to avoid alignment issues */
|
||||
} itti_signal_header_t;
|
||||
|
||||
|
||||
#define INSTANCE_DEFAULT (UINT16_MAX - 1)
|
||||
#define INSTANCE_ALL (UINT16_MAX)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
// These messages files are mandatory and must always be placed in first position
|
||||
#include "intertask_messages_def.h"
|
||||
#include "timer_messages_def.h"
|
||||
|
||||
// Dummy file for the generic intertask interface definition. Actual definition should be in top level build directory.
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*
|
||||
* messages_types.h
|
||||
*
|
||||
* Created on: Oct 14, 2013
|
||||
* Author: winckel
|
||||
*/
|
||||
|
||||
#ifndef MESSAGES_TYPES_H_
|
||||
#define MESSAGES_TYPES_H_
|
||||
|
||||
#include "intertask_messages_types.h"
|
||||
#include "timer_messages_types.h"
|
||||
|
||||
// Dummy file for the generic intertask interface definition. Actual definition should be in top level build directory.
|
||||
|
||||
#endif /* MESSAGES_TYPES_H_ */
|
||||
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "intertask_interface.h"
|
||||
#include "timer.h"
|
||||
#include "backtrace.h"
|
||||
#include "assertions.h"
|
||||
|
||||
#include "signals.h"
|
||||
#include "log.h"
|
||||
|
||||
#if defined (LOG_D) && defined (LOG_E)
|
||||
# define SIG_DEBUG(x, args...) LOG_D(RRC, x, ##args)
|
||||
# define SIG_ERROR(x, args...) LOG_E(RRC, x, ##args)
|
||||
#endif
|
||||
|
||||
#ifndef SIG_DEBUG
|
||||
# define SIG_DEBUG(x, args...) do { fprintf(stdout, "[SIG][D]"x, ##args); } while(0)
|
||||
#endif
|
||||
#ifndef SIG_ERROR
|
||||
# define SIG_ERROR(x, args...) do { fprintf(stdout, "[SIG][E]"x, ##args); } while(0)
|
||||
#endif
|
||||
|
||||
static sigset_t set;
|
||||
|
||||
int signal_mask(void)
|
||||
{
|
||||
/* We set the signal mask to avoid threads other than the main thread
|
||||
* to receive the timer signal. Note that threads created will inherit this
|
||||
* configuration.
|
||||
*/
|
||||
sigemptyset(&set);
|
||||
|
||||
sigaddset (&set, SIGTIMER);
|
||||
sigaddset (&set, SIGUSR1);
|
||||
sigaddset (&set, SIGABRT);
|
||||
sigaddset (&set, SIGSEGV);
|
||||
sigaddset (&set, SIGINT);
|
||||
|
||||
if (sigprocmask(SIG_BLOCK, &set, NULL) < 0) {
|
||||
perror ("sigprocmask");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int signal_handle(int *end)
|
||||
{
|
||||
int ret;
|
||||
siginfo_t info;
|
||||
|
||||
sigemptyset(&set);
|
||||
|
||||
sigaddset (&set, SIGTIMER);
|
||||
sigaddset (&set, SIGUSR1);
|
||||
sigaddset (&set, SIGABRT);
|
||||
sigaddset (&set, SIGSEGV);
|
||||
sigaddset (&set, SIGINT);
|
||||
|
||||
if (sigprocmask(SIG_BLOCK, &set, NULL) < 0) {
|
||||
perror ("sigprocmask");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Block till a signal is received.
|
||||
* NOTE: The signals defined by set are required to be blocked at the time
|
||||
* of the call to sigwait() otherwise sigwait() is not successful.
|
||||
*/
|
||||
if ((ret = sigwaitinfo(&set, &info)) == -1) {
|
||||
perror ("sigwait");
|
||||
return ret;
|
||||
}
|
||||
|
||||
//printf("Received signal %d\n", info.si_signo);
|
||||
|
||||
/* Real-time signals are non constant and are therefore not suitable for
|
||||
* use in switch.
|
||||
*/
|
||||
if (info.si_signo == SIGTIMER) {
|
||||
timer_handle_signal(&info);
|
||||
} else {
|
||||
/* Dispatch the signal to sub-handlers */
|
||||
switch(info.si_signo) {
|
||||
case SIGUSR1:
|
||||
SIG_DEBUG("Received SIGUSR1\n");
|
||||
*end = 1;
|
||||
break;
|
||||
|
||||
case SIGSEGV: /* Fall through */
|
||||
case SIGABRT:
|
||||
SIG_DEBUG("Received SIGABORT\n");
|
||||
backtrace_handle_signal(&info);
|
||||
break;
|
||||
|
||||
case SIGINT:
|
||||
printf("Received SIGINT\n");
|
||||
itti_send_terminate_message(TASK_UNKNOWN);
|
||||
*end = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
SIG_ERROR("Received unknown signal %d\n", info.si_signo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef SIGNALS_H_
|
||||
#define SIGNALS_H_
|
||||
|
||||
int signal_mask(void);
|
||||
|
||||
int signal_handle(int *end);
|
||||
|
||||
#endif /* SIGNALS_H_ */
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
// This task is mandatory and must always be placed in first position
|
||||
TASK_DEF(TASK_TIMER, TASK_PRIORITY_MED, 10)
|
||||
|
||||
// Dummy file for the generic intertask interface definition. Actual definition should be in top level build directory.
|
||||
@@ -1,255 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "assertions.h"
|
||||
#include "intertask_interface.h"
|
||||
#include "timer.h"
|
||||
#include "log.h"
|
||||
#include "queue.h"
|
||||
|
||||
#if defined (LOG_D) && defined (LOG_E)
|
||||
# define TMR_DEBUG(x, args...) LOG_D(TMR, x, ##args)
|
||||
# define TMR_ERROR(x, args...) LOG_E(TMR, x, ##args)
|
||||
#endif
|
||||
|
||||
#ifndef TMR_DEBUG
|
||||
# define TMR_DEBUG(x, args...) do { fprintf(stdout, "[TMR][D]"x, ##args); } while(0)
|
||||
#endif
|
||||
#ifndef TMR_ERROR
|
||||
# define TMR_ERROR(x, args...) do { fprintf(stdout, "[TMR][E]"x, ##args); } while(0)
|
||||
#endif
|
||||
|
||||
int timer_handle_signal(siginfo_t *info);
|
||||
|
||||
struct timer_elm_s {
|
||||
task_id_t task_id; ///< Task ID which has requested the timer
|
||||
int32_t instance; ///< Instance of the task which has requested the timer
|
||||
timer_t timer; ///< Unique timer id
|
||||
timer_type_t type; ///< Timer type
|
||||
void *timer_arg; ///< Optional argument that will be passed when timer expires
|
||||
STAILQ_ENTRY(timer_elm_s) entries; ///< Pointer to next element
|
||||
};
|
||||
|
||||
typedef struct timer_desc_s {
|
||||
STAILQ_HEAD(timer_list_head, timer_elm_s) timer_queue;
|
||||
pthread_mutex_t timer_list_mutex;
|
||||
struct timespec timeout;
|
||||
} timer_desc_t;
|
||||
|
||||
static timer_desc_t timer_desc;
|
||||
|
||||
#define TIMER_SEARCH(vAR, tIMERfIELD, tIMERvALUE, tIMERqUEUE) \
|
||||
do { \
|
||||
STAILQ_FOREACH(vAR, tIMERqUEUE, entries) { \
|
||||
if (((vAR)->tIMERfIELD == tIMERvALUE)) \
|
||||
break; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
int timer_handle_signal(siginfo_t *info)
|
||||
{
|
||||
struct timer_elm_s *timer_p;
|
||||
MessageDef *message_p;
|
||||
timer_has_expired_t *timer_expired_p;
|
||||
task_id_t task_id;
|
||||
int32_t instance;
|
||||
|
||||
/* Get back pointer to timer list element */
|
||||
timer_p = (struct timer_elm_s *)info->si_ptr;
|
||||
|
||||
// LG: To many traces for msc timer:
|
||||
TMR_DEBUG("Timer with id 0x%lx has expired\n", (long)timer_p->timer);
|
||||
|
||||
task_id = timer_p->task_id;
|
||||
instance = timer_p->instance;
|
||||
message_p = itti_alloc_new_message(TASK_TIMER, TIMER_HAS_EXPIRED);
|
||||
|
||||
timer_expired_p = &message_p->ittiMsg.timer_has_expired;
|
||||
|
||||
timer_expired_p->timer_id = (long)timer_p->timer;
|
||||
timer_expired_p->arg = timer_p->timer_arg;
|
||||
|
||||
/* Timer is a one shot timer, remove it */
|
||||
if (timer_p->type == TIMER_ONE_SHOT) {
|
||||
// if (timer_delete(timer_p->timer) < 0) {
|
||||
// TMR_DEBUG("Failed to delete timer 0x%lx\n", (long)timer_p->timer);
|
||||
// }
|
||||
// TMR_DEBUG("Removed timer 0x%lx\n", (long)timer_p->timer);
|
||||
// pthread_mutex_lock(&timer_desc.timer_list_mutex);
|
||||
// STAILQ_REMOVE(&timer_desc.timer_queue, timer_p, timer_elm_s, entries);
|
||||
// pthread_mutex_unlock(&timer_desc.timer_list_mutex);
|
||||
// free(timer_p);
|
||||
// timer_p = NULL;
|
||||
if (timer_remove((long)timer_p->timer) != 0) {
|
||||
TMR_DEBUG("Failed to delete timer 0x%lx\n", (long)timer_p->timer);
|
||||
}
|
||||
}
|
||||
|
||||
/* Notify task of timer expiry */
|
||||
if (itti_send_msg_to_task(task_id, instance, message_p) < 0) {
|
||||
TMR_DEBUG("Failed to send msg TIMER_HAS_EXPIRED to task %u\n", task_id);
|
||||
free(message_p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(ENB_AGENT_SB_IF)
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_setup(
|
||||
uint32_t interval_sec,
|
||||
uint32_t interval_us,
|
||||
task_id_t task_id,
|
||||
int32_t instance,
|
||||
timer_type_t type,
|
||||
void *timer_arg,
|
||||
long *timer_id)
|
||||
{
|
||||
struct sigevent se;
|
||||
struct itimerspec its;
|
||||
struct timer_elm_s *timer_p;
|
||||
timer_t timer;
|
||||
|
||||
if (timer_id == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
AssertFatal (type < TIMER_TYPE_MAX, "Invalid timer type (%d/%d)!\n", type, TIMER_TYPE_MAX);
|
||||
|
||||
/* Allocate new timer list element */
|
||||
timer_p = malloc(sizeof(struct timer_elm_s));
|
||||
|
||||
if (timer_p == NULL) {
|
||||
TMR_ERROR("Failed to create new timer element\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&timer, 0, sizeof(timer_t));
|
||||
memset(&se, 0, sizeof(struct sigevent));
|
||||
|
||||
timer_p->task_id = task_id;
|
||||
timer_p->instance = instance;
|
||||
timer_p->type = type;
|
||||
timer_p->timer_arg = timer_arg;
|
||||
|
||||
/* Setting up alarm */
|
||||
/* Set and enable alarm */
|
||||
se.sigev_notify = SIGEV_SIGNAL;
|
||||
se.sigev_signo = SIGTIMER;
|
||||
se.sigev_value.sival_ptr = timer_p;
|
||||
|
||||
/* At the timer creation, the timer structure will be filled in with timer_id,
|
||||
* which is unique for this process. This id is allocated by kernel and the
|
||||
* value might be used to distinguish timers.
|
||||
*/
|
||||
if (timer_create(CLOCK_REALTIME, &se, &timer) < 0) {
|
||||
TMR_ERROR("Failed to create timer: (%s:%d)\n", strerror(errno), errno);
|
||||
free(timer_p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Fill in the first expiration value. */
|
||||
its.it_value.tv_sec = interval_sec;
|
||||
its.it_value.tv_nsec = interval_us * 1000;
|
||||
|
||||
if (type == TIMER_PERIODIC) {
|
||||
/* Asked for periodic timer. We set the interval time */
|
||||
its.it_interval.tv_sec = interval_sec;
|
||||
its.it_interval.tv_nsec = interval_us * 1000;
|
||||
} else {
|
||||
/* Asked for one-shot timer. Do not set the interval field */
|
||||
its.it_interval.tv_sec = 0;
|
||||
its.it_interval.tv_nsec = 0;
|
||||
}
|
||||
|
||||
timer_settime(timer, 0, &its, NULL);
|
||||
/* Simply set the timer_id argument. so it can be used by caller */
|
||||
*timer_id = (long)timer;
|
||||
TMR_DEBUG("Requesting new %s timer with id 0x%lx that expires within "
|
||||
"%d sec and %d usec\n",
|
||||
type == TIMER_PERIODIC ? "periodic" : "single shot",
|
||||
*timer_id, interval_sec, interval_us);
|
||||
|
||||
timer_p->timer = timer;
|
||||
|
||||
/* Lock the queue and insert the timer at the tail */
|
||||
pthread_mutex_lock(&timer_desc.timer_list_mutex);
|
||||
STAILQ_INSERT_TAIL(&timer_desc.timer_queue, timer_p, entries);
|
||||
pthread_mutex_unlock(&timer_desc.timer_list_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_remove(long timer_id)
|
||||
{
|
||||
int rc = 0;
|
||||
struct timer_elm_s *timer_p;
|
||||
|
||||
TMR_DEBUG("Removing timer 0x%lx\n", timer_id);
|
||||
|
||||
pthread_mutex_lock(&timer_desc.timer_list_mutex);
|
||||
TIMER_SEARCH(timer_p, timer, ((timer_t)timer_id), &timer_desc.timer_queue);
|
||||
|
||||
/* We didn't find the timer in list */
|
||||
if (timer_p == NULL) {
|
||||
pthread_mutex_unlock(&timer_desc.timer_list_mutex);
|
||||
TMR_ERROR("Didn't find timer 0x%lx in list\n", timer_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
STAILQ_REMOVE(&timer_desc.timer_queue, timer_p, timer_elm_s, entries);
|
||||
pthread_mutex_unlock(&timer_desc.timer_list_mutex);
|
||||
|
||||
if (timer_delete(timer_p->timer) < 0) {
|
||||
TMR_ERROR("Failed to delete timer 0x%lx\n", (long)timer_p->timer);
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
free(timer_p);
|
||||
timer_p = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int timer_init(void)
|
||||
{
|
||||
TMR_DEBUG("Initializing TIMER task interface\n");
|
||||
|
||||
memset(&timer_desc, 0, sizeof(timer_desc_t));
|
||||
|
||||
STAILQ_INIT(&timer_desc.timer_queue);
|
||||
pthread_mutex_init(&timer_desc.timer_list_mutex, NULL);
|
||||
|
||||
TMR_DEBUG("Initializing TIMER task interface: DONE\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef TIMER_H_
|
||||
#define TIMER_H_
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#define SIGTIMER SIGRTMIN
|
||||
|
||||
typedef enum timer_type_s {
|
||||
TIMER_PERIODIC,
|
||||
TIMER_ONE_SHOT,
|
||||
TIMER_TYPE_MAX,
|
||||
} timer_type_t;
|
||||
|
||||
int timer_handle_signal(siginfo_t *info);
|
||||
|
||||
/** \brief Request a new timer
|
||||
* \param interval_sec timer interval in seconds
|
||||
* \param interval_us timer interval in micro seconds
|
||||
* \param task_id task id of the task requesting the timer
|
||||
* \param instance instance of the task requesting the timer
|
||||
* \param type timer type
|
||||
* \param timer_id unique timer identifier
|
||||
* @returns -1 on failure, 0 otherwise
|
||||
**/
|
||||
int timer_setup(
|
||||
uint32_t interval_sec,
|
||||
uint32_t interval_us,
|
||||
task_id_t task_id,
|
||||
int32_t instance,
|
||||
timer_type_t type,
|
||||
void *timer_arg,
|
||||
long *timer_id);
|
||||
|
||||
/** \brief Remove the timer from list
|
||||
* \param timer_id unique timer id
|
||||
* @returns -1 on failure, 0 otherwise
|
||||
**/
|
||||
|
||||
int timer_remove(long timer_id);
|
||||
#define timer_stop timer_remove
|
||||
|
||||
/** \brief Initialize timer task and its API
|
||||
* \param mme_config MME common configuration
|
||||
* @returns -1 on failure, 0 otherwise
|
||||
**/
|
||||
int timer_init(void);
|
||||
|
||||
#endif
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
MESSAGE_DEF(TIMER_HAS_EXPIRED, MESSAGE_PRIORITY_MED_PLUS, timer_has_expired_t, timer_has_expired)
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef TIMER_MESSAGES_TYPES_H_
|
||||
#define TIMER_MESSAGES_TYPES_H_
|
||||
|
||||
//-------------------------------------------------------------------------------------------//
|
||||
// Defines to access message fields.
|
||||
#define TIMER_HAS_EXPIRED(mSGpTR) (mSGpTR)->ittiMsg.timer_has_expired
|
||||
|
||||
//-------------------------------------------------------------------------------------------//
|
||||
typedef struct {
|
||||
void *arg;
|
||||
long timer_id;
|
||||
} timer_has_expired_t;
|
||||
|
||||
#endif /* TIMER_MESSAGES_TYPES_H_ */
|
||||
@@ -70,8 +70,8 @@ char *tmpstr;
|
||||
char *shlibpath =NULL;
|
||||
char *shlibversion=NULL;
|
||||
char *cfgprefix;
|
||||
paramdef_t LoaderParams[] ={{"shlibpath", NULL, 0, strptr:&shlibpath, defstrval:NULL, TYPE_STRING, 0},
|
||||
{"shlibversion", NULL, 0, strptr:&shlibversion, defstrval:"", TYPE_STRING, 0}};
|
||||
paramdef_t LoaderParams[] ={{"shlibpath", NULL, 0, strptr:&shlibpath, defstrval:NULL, TYPE_STRING, 0, NULL},
|
||||
{"shlibversion", NULL, 0, strptr:&shlibversion, defstrval:"", TYPE_STRING, 0, NULL}};
|
||||
|
||||
int ret;
|
||||
|
||||
@@ -118,77 +118,118 @@ int ret;
|
||||
return tmpstr;
|
||||
}
|
||||
|
||||
int load_module_shlib(char *modname,loader_shlibfunc_t *farray, int numf)
|
||||
int load_module_shlib(char *modname,loader_shlibfunc_t *farray, int numf, void *autoinit_arg)
|
||||
{
|
||||
void *lib_handle;
|
||||
initfunc_t fpi;
|
||||
checkverfunc_t fpc;
|
||||
getfarrayfunc_t fpg;
|
||||
char *shlib_path;
|
||||
char *afname=NULL;
|
||||
int ret=0;
|
||||
void *lib_handle = NULL;
|
||||
initfunc_t fpi;
|
||||
checkverfunc_t fpc;
|
||||
getfarrayfunc_t fpg;
|
||||
char *shlib_path = NULL;
|
||||
char *afname = NULL;
|
||||
int ret = 0;
|
||||
int lib_idx = -1;
|
||||
|
||||
if (loader_data.shlibpath == NULL) {
|
||||
loader_init();
|
||||
}
|
||||
if (!modname) {
|
||||
fprintf(stderr, "[LOADER] load_module_shlib(): no library name given\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
shlib_path = loader_format_shlibpath(modname);
|
||||
if (!loader_data.shlibpath) {
|
||||
loader_init();
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
lib_handle = dlopen(shlib_path, RTLD_LAZY|RTLD_NODELETE|RTLD_GLOBAL);
|
||||
if (!lib_handle) {
|
||||
fprintf(stderr,"[LOADER] library %s is not loaded: %s\n", shlib_path,dlerror());
|
||||
shlib_path = loader_format_shlibpath(modname);
|
||||
|
||||
for (int i = 0; i < loader_data.numshlibs; i++) {
|
||||
if (strcmp(loader_data.shlibs[i].name, modname) == 0) {
|
||||
printf("[LOADER] library %s has been loaded previously, reloading function pointers\n",
|
||||
shlib_path);
|
||||
lib_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lib_idx < 0) {
|
||||
lib_idx = loader_data.numshlibs;
|
||||
++loader_data.numshlibs;
|
||||
if (loader_data.numshlibs > loader_data.maxshlibs) {
|
||||
fprintf(stderr, "[LOADER] can not load more than %d shlibs\n",
|
||||
loader_data.maxshlibs);
|
||||
ret = -1;
|
||||
} else {
|
||||
printf("[LOADER] library %s successfully loaded\n", shlib_path);
|
||||
afname=malloc(strlen(modname)+15);
|
||||
sprintf(afname,"%s_checkbuildver",modname);
|
||||
fpc = dlsym(lib_handle,afname);
|
||||
if (fpc != NULL ){
|
||||
int chkver_ret = fpc(loader_data.mainexec_buildversion, &(loader_data.shlibs[loader_data.numshlibs].shlib_buildversion));
|
||||
if (chkver_ret < 0) {
|
||||
fprintf(stderr,"[LOADER] %s %d lib %s, version mismatch",__FILE__, __LINE__, modname);
|
||||
exit_fun("[LOADER] unrecoverable error");
|
||||
}
|
||||
goto load_module_shlib_exit;
|
||||
}
|
||||
loader_data.shlibs[lib_idx].name = strdup(modname);
|
||||
loader_data.shlibs[lib_idx].thisshlib_path = strdup(shlib_path);
|
||||
}
|
||||
|
||||
lib_handle = dlopen(shlib_path, RTLD_LAZY|RTLD_NODELETE|RTLD_GLOBAL);
|
||||
if (!lib_handle) {
|
||||
fprintf(stderr,"[LOADER] library %s is not loaded: %s\n", shlib_path,dlerror());
|
||||
ret = -1;
|
||||
goto load_module_shlib_exit;
|
||||
}
|
||||
|
||||
printf("[LOADER] library %s successfully loaded\n", shlib_path);
|
||||
afname = malloc(strlen(modname)+15);
|
||||
if (!afname) {
|
||||
fprintf(stderr, "[LOADER] unable to allocate memory for library %s\n", shlib_path);
|
||||
ret = -1;
|
||||
goto load_module_shlib_exit;
|
||||
}
|
||||
sprintf(afname,"%s_checkbuildver",modname);
|
||||
fpc = dlsym(lib_handle,afname);
|
||||
if (fpc) {
|
||||
int chkver_ret = fpc(loader_data.mainexec_buildversion,
|
||||
&(loader_data.shlibs[lib_idx].shlib_buildversion));
|
||||
if (chkver_ret < 0) {
|
||||
fprintf(stderr, "[LOADER] %s %d lib %s, version mismatch",
|
||||
__FILE__, __LINE__, modname);
|
||||
ret = -1;
|
||||
goto load_module_shlib_exit;
|
||||
}
|
||||
}
|
||||
sprintf(afname,"%s_autoinit",modname);
|
||||
fpi = dlsym(lib_handle,afname);
|
||||
|
||||
if (fpi) {
|
||||
fpi(autoinit_arg);
|
||||
}
|
||||
|
||||
if (farray) {
|
||||
if (!loader_data.shlibs[lib_idx].funcarray) {
|
||||
loader_data.shlibs[lib_idx].funcarray = malloc(numf*sizeof(loader_shlibfunc_t));
|
||||
if (!loader_data.shlibs[lib_idx].funcarray) {
|
||||
fprintf(stderr, "[LOADER] load_module_shlib(): unable to allocate memory\n");
|
||||
ret = -1;
|
||||
goto load_module_shlib_exit;
|
||||
}
|
||||
sprintf(afname,"%s_autoinit",modname);
|
||||
fpi = dlsym(lib_handle,afname);
|
||||
|
||||
if (fpi != NULL ) {
|
||||
fpi();
|
||||
}
|
||||
loader_data.shlibs[lib_idx].numfunc = 0;
|
||||
for (int i = 0; i < numf; i++) {
|
||||
farray[i].fptr = dlsym(lib_handle,farray[i].fname);
|
||||
if (!farray[i].fptr) {
|
||||
fprintf(stderr, "[LOADER] load_module_shlib(): function %s not found: %s\n",
|
||||
farray[i].fname, dlerror());
|
||||
ret = -1;
|
||||
goto load_module_shlib_exit;
|
||||
}
|
||||
loader_data.shlibs[lib_idx].funcarray[i].fname=strdup(farray[i].fname);
|
||||
loader_data.shlibs[lib_idx].funcarray[i].fptr = farray[i].fptr;
|
||||
loader_data.shlibs[lib_idx].numfunc++;
|
||||
} /* for int i... */
|
||||
} else { /* farray ! NULL */
|
||||
sprintf(afname,"%s_getfarray",modname);
|
||||
fpg = dlsym(lib_handle,afname);
|
||||
if (fpg) {
|
||||
loader_data.shlibs[lib_idx].numfunc =
|
||||
fpg(&(loader_data.shlibs[lib_idx].funcarray));
|
||||
}
|
||||
} /* farray ! NULL */
|
||||
|
||||
if (farray != NULL) {
|
||||
loader_data.shlibs[loader_data.numshlibs].funcarray=malloc(numf*sizeof(loader_shlibfunc_t));
|
||||
loader_data.shlibs[loader_data.numshlibs].numfunc=0;
|
||||
for (int i=0; i<numf; i++) {
|
||||
farray[i].fptr = dlsym(lib_handle,farray[i].fname);
|
||||
if (farray[i].fptr == NULL ) {
|
||||
fprintf(stderr,"[LOADER] %s %d %s function not found %s\n",__FILE__, __LINE__, dlerror(),farray[i].fname);
|
||||
ret= -1;
|
||||
} else { /* farray[i].fptr == NULL */
|
||||
loader_data.shlibs[loader_data.numshlibs].funcarray[i].fname=strdup(farray[i].fname);
|
||||
loader_data.shlibs[loader_data.numshlibs].funcarray[i].fptr = farray[i].fptr;
|
||||
loader_data.shlibs[loader_data.numshlibs].numfunc++;
|
||||
}/* farray[i].fptr != NULL */
|
||||
} /* for int i... */
|
||||
} else { /* farray ! NULL */
|
||||
sprintf(afname,"%s_getfarray",modname);
|
||||
fpg = dlsym(lib_handle,afname);
|
||||
if (fpg != NULL ) {
|
||||
loader_data.shlibs[loader_data.numshlibs].numfunc = fpg(&(loader_data.shlibs[loader_data.numshlibs].funcarray));
|
||||
}
|
||||
} /* farray ! NULL */
|
||||
loader_data.shlibs[loader_data.numshlibs].name=strdup(modname);
|
||||
loader_data.shlibs[loader_data.numshlibs].thisshlib_path=strdup(shlib_path);
|
||||
|
||||
(loader_data.numshlibs)++;
|
||||
} /* lib_handle != NULL */
|
||||
|
||||
if ( shlib_path!= NULL) free(shlib_path);
|
||||
if ( afname!= NULL) free(afname);
|
||||
if (lib_handle != NULL) dlclose(lib_handle);
|
||||
return ret;
|
||||
load_module_shlib_exit:
|
||||
if (shlib_path) free(shlib_path);
|
||||
if (afname) free(afname);
|
||||
if (lib_handle) dlclose(lib_handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void * get_shlibmodule_fptr(char *modname, char *fname)
|
||||
|
||||
@@ -59,7 +59,8 @@ typedef struct {
|
||||
|
||||
/* function type of functions which may be implemented by a module */
|
||||
/* 1: init function, called when loading, if found in the shared lib */
|
||||
typedef int(*initfunc_t)(void);
|
||||
typedef int(*initfunc_t)(void *);
|
||||
|
||||
/* 2: version checking function, called when loading, if it returns -1, trigger main exec abort */
|
||||
typedef int(*checkverfunc_t)(char * mainexec_version, char ** shlib_version);
|
||||
/* 3: get function array function, called when loading when a module doesn't provide */
|
||||
@@ -72,18 +73,18 @@ typedef int(*getfarrayfunc_t)(loader_shlibfunc_t **funcarray);
|
||||
#define DEFAULT_MAXSHLIBS 10
|
||||
loader_data_t loader_data;
|
||||
|
||||
/*------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* LOADER parameters */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
/*------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/*----------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* LOADER parameters */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt check func*/
|
||||
/*----------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
#define LOADER_PARAMS_DESC { \
|
||||
{"shlibpath", NULL, PARAMFLAG_NOFREE, strptr:(char **)&(loader_data.shlibpath), defstrval:DEFAULT_PATH, TYPE_STRING, 0}, \
|
||||
{"maxshlibs", NULL, 0, uptr:&(loader_data.maxshlibs), defintval:DEFAULT_MAXSHLIBS, TYPE_UINT32, 0}, \
|
||||
{"shlibpath", NULL, PARAMFLAG_NOFREE, strptr:(char **)&(loader_data.shlibpath), defstrval:DEFAULT_PATH, TYPE_STRING, 0, NULL},\
|
||||
{"maxshlibs", NULL, 0, uptr:&(loader_data.maxshlibs), defintval:DEFAULT_MAXSHLIBS, TYPE_UINT32, 0, NULL}\
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------------------*/
|
||||
#else /* LOAD_MODULE_SHLIB_MAIN */
|
||||
extern int load_module_shlib(char *modname, loader_shlibfunc_t *farray, int numf);
|
||||
extern int load_module_shlib(char *modname, loader_shlibfunc_t *farray, int numf, void *initfunc_arg);
|
||||
extern void * get_shlibmodule_fptr(char *modname, char *fname);
|
||||
extern loader_data_t loader_data;
|
||||
#endif /* LOAD_MODULE_SHLIB_MAIN */
|
||||
|
||||
+23
-7
@@ -32,11 +32,14 @@
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#define MSC_LIBRARY
|
||||
#include "msc.h"
|
||||
|
||||
#include "liblfds611.h"
|
||||
#include "intertask_interface.h"
|
||||
#include "timer.h"
|
||||
|
||||
#include "msc.h"
|
||||
|
||||
|
||||
#include "assertions.h"
|
||||
|
||||
//-------------------------------
|
||||
@@ -67,8 +70,8 @@ void *msc_task(void *args_p)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
MessageDef *received_message_p = NULL;
|
||||
const char *msg_name = NULL;
|
||||
instance_t instance = 0;
|
||||
// const char *msg_name = NULL;
|
||||
// instance_t instance = 0;
|
||||
long timer_id;
|
||||
|
||||
itti_mark_task_ready(TASK_MSC);
|
||||
@@ -88,9 +91,9 @@ void *msc_task(void *args_p)
|
||||
itti_receive_msg(TASK_MSC, &received_message_p);
|
||||
|
||||
if (received_message_p != NULL) {
|
||||
msg_name = ITTI_MSG_NAME (received_message_p);
|
||||
instance = ITTI_MSG_INSTANCE (received_message_p);
|
||||
|
||||
// msg_name = ITTI_MSG_NAME (received_message_p);
|
||||
// instance = ITTI_MSG_INSTANCE (received_message_p);
|
||||
|
||||
switch (ITTI_MSG_ID(received_message_p)) {
|
||||
|
||||
case TIMER_HAS_EXPIRED: {
|
||||
@@ -571,4 +574,17 @@ error_event:
|
||||
free(new_item_p);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// function called when oai loader loads the msc shared lib
|
||||
int msc_autoinit(msc_interface_t *msc_interface)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
|
||||
msc_interface->msc_init = msc_init;
|
||||
msc_interface->msc_start_use = msc_start_use;
|
||||
msc_interface->msc_end = msc_end;
|
||||
msc_interface->msc_log_event = msc_log_event;
|
||||
msc_interface->msc_log_message = msc_log_message;
|
||||
msc_interface->msc_loaded = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
+31
-18
@@ -63,6 +63,8 @@ typedef enum {
|
||||
MSC_S6A_MME,
|
||||
MSC_HSS,
|
||||
MAX_MSC_PROTOS,
|
||||
MSC_X2AP_SRC_ENB,
|
||||
MSC_X2AP_TARGET_ENB,
|
||||
} msc_proto_t;
|
||||
|
||||
|
||||
@@ -73,7 +75,23 @@ typedef enum {
|
||||
#define MSC_AS_TIME_ARGS(CTXT_Pp) \
|
||||
(CTXT_Pp)->frame, \
|
||||
(CTXT_Pp)->subframe
|
||||
#if defined(MESSAGE_CHART_GENERATOR)
|
||||
|
||||
typedef int(*msc_init_t)(const msc_env_t, const int );
|
||||
typedef void(*msc_start_use_t)(void );
|
||||
typedef void(*msc_end_t)(void);
|
||||
typedef void(*msc_log_event_t)(const msc_proto_t,char *, ...);
|
||||
typedef void(*msc_log_message_t)(const char * const, const msc_proto_t, const msc_proto_t,
|
||||
const uint8_t* const, const unsigned int, char * , ...);
|
||||
typedef struct msc_interface {
|
||||
int msc_loaded;
|
||||
msc_init_t msc_init;
|
||||
msc_start_use_t msc_start_use;
|
||||
msc_end_t msc_end;
|
||||
msc_log_event_t msc_log_event;
|
||||
msc_log_message_t msc_log_message;
|
||||
} msc_interface_t;
|
||||
|
||||
#ifdef MSC_LIBRARY
|
||||
int msc_init(const msc_env_t envP, const int max_threadsP);
|
||||
void msc_start_use(void);
|
||||
void msc_flush_messages(void);
|
||||
@@ -88,22 +106,17 @@ void msc_log_message(
|
||||
const unsigned int num_bytes,
|
||||
char *format, ...);
|
||||
|
||||
#define MSC_INIT(arg1,arg2) msc_init(arg1,arg2)
|
||||
#define MSC_START_USE msc_start_use
|
||||
#define MSC_END msc_end
|
||||
#define MSC_LOG_EVENT(mScPaRaMs, fORMAT, aRGS...) msc_log_event(mScPaRaMs, fORMAT, ##aRGS)
|
||||
#define MSC_LOG_RX_MESSAGE(rECEIVER, sENDER, bYTES, nUMbYTES, fORMAT, aRGS...) msc_log_message("<-",rECEIVER, sENDER, bYTES, nUMbYTES, fORMAT, ##aRGS)
|
||||
#define MSC_LOG_RX_DISCARDED_MESSAGE(rECEIVER, sENDER, bYTES, nUMbYTES, fORMAT, aRGS...) msc_log_message("x-",rECEIVER, sENDER, bYTES, nUMbYTES, fORMAT, ##aRGS)
|
||||
#define MSC_LOG_TX_MESSAGE(sENDER, rECEIVER, bYTES, nUMbYTES, fORMAT, aRGS...) msc_log_message("->",sENDER, rECEIVER, bYTES, nUMbYTES, fORMAT, ##aRGS)
|
||||
#define MSC_LOG_TX_MESSAGE_FAILED(sENDER, rECEIVER, bYTES, nUMbYTES, fORMAT, aRGS...) msc_log_message("-x",sENDER, rECEIVER, bYTES, nUMbYTES, fORMAT, ##aRGS)
|
||||
#else
|
||||
#define MSC_INIT(arg1,arg2)
|
||||
#define MSC_START_USE(mScPaRaMs)
|
||||
#define MSC_END(mScPaRaMs)
|
||||
#define MSC_LOG_EVENT(mScPaRaMs, fORMAT, aRGS...)
|
||||
#define MSC_LOG_RX_MESSAGE(mScPaRaMs, fORMAT, aRGS...)
|
||||
#define MSC_LOG_RX_DISCARDED_MESSAGE(mScPaRaMs, fORMAT, aRGS...)
|
||||
#define MSC_LOG_TX_MESSAGE(mScPaRaMs, fORMAT, aRGS...)
|
||||
#define MSC_LOG_TX_MESSAGE_FAILED(mScPaRaMs, fORMAT, aRGS...)
|
||||
#endif
|
||||
|
||||
msc_interface_t msc_interface;
|
||||
#define MSC_INIT(arg1,arg2) if(msc_interface.msc_loaded) msc_interface.msc_init(arg1,arg2)
|
||||
#define MSC_START_USE if(msc_interface.msc_loaded) msc_interface.msc_start_use
|
||||
#define MSC_END if(msc_interface.msc_loaded) msc_interface.msc_end
|
||||
#define MSC_LOG_EVENT(mScPaRaMs, fORMAT, aRGS...) if(msc_interface.msc_loaded) msc_interface.msc_log_event(mScPaRaMs, fORMAT, ##aRGS)
|
||||
#define MSC_LOG_RX_MESSAGE(rECEIVER, sENDER, bYTES, nUMbYTES, fORMAT, aRGS...) if(msc_interface.msc_loaded) msc_interface.msc_log_message("<-",rECEIVER, sENDER, (const uint8_t *)bYTES, nUMbYTES, fORMAT, ##aRGS)
|
||||
#define MSC_LOG_RX_DISCARDED_MESSAGE(rECEIVER, sENDER, bYTES, nUMbYTES, fORMAT, aRGS...) if(msc_interface.msc_loaded) msc_interface.msc_log_message("x-",rECEIVER, sENDER, (const uint8_t *)bYTES, nUMbYTES, fORMAT, ##aRGS)
|
||||
#define MSC_LOG_TX_MESSAGE(sENDER, rECEIVER, bYTES, nUMbYTES, fORMAT, aRGS...) if(msc_interface.msc_loaded) msc_interface.msc_log_message("->",sENDER, rECEIVER, (const uint8_t *)bYTES, nUMbYTES, fORMAT, ##aRGS)
|
||||
#define MSC_LOG_TX_MESSAGE_FAILED(sENDER, rECEIVER, bYTES, nUMbYTES, fORMAT, aRGS...) if(msc_interface.msc_loaded) msc_interface.msc_log_message("-x",sENDER, rECEIVER, (const uint8_t *)bYTES, nUMbYTES, fORMAT, ##aRGS)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "openair2/COMMON/phy_messages_def.h"
|
||||
#include "openair2/COMMON/mac_messages_def.h"
|
||||
#include "openair2/COMMON/rlc_messages_def.h"
|
||||
#include "openair2/COMMON/pdcp_messages_def.h"
|
||||
#include "openair2/COMMON/rrc_messages_def.h"
|
||||
#include "openair2/COMMON/nas_messages_def.h"
|
||||
#if ENABLE_RAL
|
||||
#include "openair2/COMMON/ral_messages_def.h"
|
||||
#endif
|
||||
#include "openair2/COMMON/s1ap_messages_def.h"
|
||||
#include "openair2/COMMON/x2ap_messages_def.h"
|
||||
#include "openair2/COMMON/sctp_messages_def.h"
|
||||
#include "openair2/COMMON/udp_messages_def.h"
|
||||
#include "openair2/COMMON/gtpv1_u_messages_def.h"
|
||||
#include "openair2/COMMON/flexran_messages_def.h"
|
||||
@@ -0,0 +1,414 @@
|
||||
/*
|
||||
Author: Laurent THOMAS, Open Cells
|
||||
copyleft: OpenAirInterface Software Alliance and it's licence
|
||||
*/
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <sys/eventfd.h>
|
||||
|
||||
|
||||
#include <intertask_interface.h>
|
||||
|
||||
typedef struct timer_elm_s {
|
||||
timer_type_t type; ///< Timer type
|
||||
long instance;
|
||||
long duration;
|
||||
uint64_t timeout;
|
||||
void *timer_arg; ///< Optional argument that will be passed when timer expires
|
||||
} timer_elm_t ;
|
||||
|
||||
typedef struct task_list_s {
|
||||
task_info_t admin;
|
||||
pthread_t thread;
|
||||
pthread_mutex_t queue_cond_lock;
|
||||
std::vector<MessageDef *> message_queue;
|
||||
std::map<long,timer_elm_t> timer_map;
|
||||
uint64_t next_timer=UINT64_MAX;
|
||||
struct epoll_event *events =NULL;
|
||||
int nb_fd_epoll=0;
|
||||
int nb_events=0;
|
||||
int epoll_fd=-1;
|
||||
int sem_fd=-1;
|
||||
} task_list_t;
|
||||
|
||||
int timer_expired(int fd);
|
||||
task_list_t tasks[TASK_MAX];
|
||||
|
||||
extern "C" {
|
||||
void *pool_buffer_init (void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *pool_buffer_clean (void *arg) {
|
||||
//-----------------------------------------------------------------------------
|
||||
return 0;
|
||||
}
|
||||
|
||||
void free_mem_block (mem_block_t *leP, const char *caller) {
|
||||
AssertFatal(leP!=NULL,"");
|
||||
free(leP);
|
||||
}
|
||||
|
||||
mem_block_t *get_free_mem_block (uint32_t sizeP, const char *caller) {
|
||||
mem_block_t *ptr=(mem_block_t *)malloc(sizeP+sizeof(mem_block_t));
|
||||
ptr->next = NULL;
|
||||
ptr->previous = NULL;
|
||||
ptr->data=((unsigned char *)ptr)+sizeof(mem_block_t);
|
||||
ptr->size=sizeP;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *itti_malloc(task_id_t origin_task_id, task_id_t destination_task_id, ssize_t size) {
|
||||
void *ptr = NULL;
|
||||
AssertFatal ((ptr=malloc (size)) != NULL, "Memory allocation of %zu bytes failed (%d -> %d)!\n",
|
||||
size, origin_task_id, destination_task_id);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int itti_free(task_id_t task_id, void *ptr) {
|
||||
AssertFatal (ptr != NULL, "Trying to free a NULL pointer (%d)!\n", task_id);
|
||||
free (ptr);
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
MessageDef *itti_alloc_new_message_sized(task_id_t origin_task_id, MessagesIds message_id, MessageHeaderSize size) {
|
||||
MessageDef *temp = (MessageDef *)itti_malloc (origin_task_id, TASK_UNKNOWN, sizeof(MessageHeader) + size);
|
||||
temp->ittiMsgHeader.messageId = message_id;
|
||||
temp->ittiMsgHeader.originTaskId = origin_task_id;
|
||||
temp->ittiMsgHeader.ittiMsgSize = size;
|
||||
return temp;
|
||||
}
|
||||
|
||||
MessageDef *itti_alloc_new_message(task_id_t origin_task_id, MessagesIds message_id) {
|
||||
int size=sizeof(MessageHeader) + messages_info[message_id].size;
|
||||
MessageDef *temp = (MessageDef *)itti_malloc (origin_task_id, TASK_UNKNOWN, size);
|
||||
temp->ittiMsgHeader.messageId = message_id;
|
||||
temp->ittiMsgHeader.originTaskId = origin_task_id;
|
||||
temp->ittiMsgHeader.ittiMsgSize = size;
|
||||
return temp;
|
||||
//return itti_alloc_new_message_sized(origin_task_id, message_id, messages_info[message_id].size);
|
||||
}
|
||||
|
||||
static inline int itti_send_msg_to_task_locked(task_id_t destination_task_id, instance_t instance, MessageDef *message) {
|
||||
task_list_t *t=tasks+destination_task_id;
|
||||
message->ittiMsgHeader.destinationTaskId = destination_task_id;
|
||||
message->ittiMsgHeader.instance = instance;
|
||||
message->ittiMsgHeader.lte_time.frame = 0;
|
||||
message->ittiMsgHeader.lte_time.slot = 0;
|
||||
int message_id = message->ittiMsgHeader.messageId;
|
||||
size_t s=t->message_queue.size();
|
||||
|
||||
if ( s > t->admin.queue_size )
|
||||
LOG_E(TMR,"Queue for %s task contains %ld messages\n", itti_get_task_name(destination_task_id), s );
|
||||
|
||||
if ( s > 50 )
|
||||
LOG_I(TMR,"Queue for %s task size: %ld\n",itti_get_task_name(destination_task_id), s+1);
|
||||
|
||||
t->message_queue.insert(t->message_queue.begin(), message);
|
||||
eventfd_t sem_counter = 1;
|
||||
AssertFatal ( sizeof(sem_counter) == write(t->sem_fd, &sem_counter, sizeof(sem_counter)), "");
|
||||
LOG_D(TMR,"sent messages id=%d to %s\n",message_id, t->admin.name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int itti_send_msg_to_task(task_id_t destination_task_id, instance_t instance, MessageDef *message) {
|
||||
task_list_t *t=&tasks[destination_task_id];
|
||||
pthread_mutex_lock (&t->queue_cond_lock);
|
||||
int ret=itti_send_msg_to_task_locked(destination_task_id, instance, message);
|
||||
|
||||
while ( t->message_queue.size()>0 && t->admin.func != NULL ) {
|
||||
if (t->message_queue.size()>1)
|
||||
LOG_W(TMR,"queue in no thread mode is %ld\n", t->message_queue.size());
|
||||
pthread_mutex_unlock (&t->queue_cond_lock);
|
||||
t->admin.func(NULL);
|
||||
pthread_mutex_lock (&t->queue_cond_lock);
|
||||
}
|
||||
pthread_mutex_unlock (&t->queue_cond_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void itti_subscribe_event_fd(task_id_t task_id, int fd) {
|
||||
struct epoll_event event;
|
||||
task_list_t *t=&tasks[task_id];
|
||||
t->nb_fd_epoll++;
|
||||
t->events = (struct epoll_event *)realloc((void *)t->events,
|
||||
t->nb_fd_epoll * sizeof(struct epoll_event));
|
||||
event.events = EPOLLIN | EPOLLERR;
|
||||
event.data.u64 = 0;
|
||||
event.data.fd = fd;
|
||||
AssertFatal(epoll_ctl(t->epoll_fd, EPOLL_CTL_ADD, fd, &event) == 0,
|
||||
"epoll_ctl (EPOLL_CTL_ADD) failed for task %s, fd %d: %s!\n",
|
||||
itti_get_task_name(task_id), fd, strerror(errno));
|
||||
}
|
||||
|
||||
void itti_unsubscribe_event_fd(task_id_t task_id, int fd) {
|
||||
task_list_t *t=&tasks[task_id];
|
||||
AssertFatal (epoll_ctl(t->epoll_fd, EPOLL_CTL_DEL, fd, NULL) == 0,
|
||||
"epoll_ctl (EPOLL_CTL_DEL) failed for task %s, fd %d: %s!\n",
|
||||
itti_get_task_name(task_id), fd, strerror(errno));
|
||||
t->nb_fd_epoll--;
|
||||
}
|
||||
|
||||
static inline int itti_get_events_locked(task_id_t task_id, struct epoll_event **events) {
|
||||
task_list_t *t=&tasks[task_id];
|
||||
uint64_t current_time=0;
|
||||
|
||||
do {
|
||||
if ( t->next_timer != UINT64_MAX ) {
|
||||
struct timespec tp;
|
||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||
current_time=(uint64_t)tp.tv_sec*1000+tp.tv_nsec/(1000*1000);
|
||||
|
||||
if ( t->next_timer < current_time) {
|
||||
t->next_timer=UINT64_MAX;
|
||||
|
||||
// Proceed expired timer
|
||||
for ( auto it=t->timer_map.begin() ; it != t->timer_map.end() ; ++it ) {
|
||||
if ( it->second.timeout < current_time ) {
|
||||
MessageDef *message = itti_alloc_new_message(TASK_TIMER, TIMER_HAS_EXPIRED);
|
||||
message->ittiMsg.timer_has_expired.timer_id=it->first;
|
||||
message->ittiMsg.timer_has_expired.arg=it->second.timer_arg;
|
||||
|
||||
if (itti_send_msg_to_task_locked(task_id, it->second.instance, message) < 0) {
|
||||
LOG_W(TMR,"Failed to send msg TIMER_HAS_EXPIRED to task %u\n", task_id);
|
||||
free(message);
|
||||
t->timer_map.erase(it);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( it->second.type==TIMER_PERIODIC ) {
|
||||
it->second.timeout+=it->second.duration;
|
||||
|
||||
if (it->second.timeout < t->next_timer)
|
||||
t->next_timer=it->second.timeout;
|
||||
} else
|
||||
t->timer_map.erase(it);
|
||||
} else if (it->second.timeout < t->next_timer)
|
||||
t->next_timer=it->second.timeout;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int epoll_timeout = -1;
|
||||
|
||||
if ( t->next_timer != UINT64_MAX )
|
||||
epoll_timeout = t->next_timer-current_time;
|
||||
|
||||
pthread_mutex_unlock(&t->queue_cond_lock);
|
||||
LOG_D(TMR,"enter blocking wait for %s\n", itti_get_task_name(task_id));
|
||||
t->nb_events = epoll_wait(t->epoll_fd,t->events,t->nb_fd_epoll, epoll_timeout);
|
||||
if ( t->nb_events < 0 && (errno == EINTR || errno == EAGAIN ) )
|
||||
pthread_mutex_lock(&t->queue_cond_lock);
|
||||
} while (t->nb_events < 0 && (errno == EINTR || errno == EAGAIN ) );
|
||||
|
||||
AssertFatal (t->nb_events >=0,
|
||||
"epoll_wait failed for task %s, nb fds %d, timeout %lu: %s!\n",
|
||||
itti_get_task_name(task_id), t->nb_fd_epoll, t->next_timer != UINT64_MAX ? t->next_timer-current_time : -1, strerror(errno));
|
||||
LOG_D(TMR,"receive on %d descriptors for %s\n", t->nb_events, itti_get_task_name(task_id));
|
||||
|
||||
if (t->nb_events == 0)
|
||||
/* No data to read -> return */
|
||||
return 0;
|
||||
|
||||
for (int i = 0; i < t->nb_events; i++) {
|
||||
/* Check if there is an event for ITTI for the event fd */
|
||||
if ((t->events[i].events & EPOLLIN) &&
|
||||
(t->events[i].data.fd == t->sem_fd)) {
|
||||
eventfd_t sem_counter;
|
||||
/* Read will always return 1 */
|
||||
AssertFatal( sizeof(sem_counter) == read (t->sem_fd, &sem_counter, sizeof(sem_counter)), "");
|
||||
/* Mark that the event has been processed */
|
||||
t->events[i].events &= ~EPOLLIN;
|
||||
}
|
||||
}
|
||||
|
||||
*events = t->events;
|
||||
return t->nb_events;
|
||||
}
|
||||
|
||||
int itti_get_events(task_id_t task_id, struct epoll_event **events) {
|
||||
pthread_mutex_lock(&tasks[task_id].queue_cond_lock);
|
||||
return itti_get_events_locked(task_id, events);
|
||||
}
|
||||
|
||||
void itti_receive_msg(task_id_t task_id, MessageDef **received_msg) {
|
||||
// Reception of one message, blocking caller
|
||||
task_list_t *t=&tasks[task_id];
|
||||
pthread_mutex_lock(&t->queue_cond_lock);
|
||||
|
||||
// Weird condition to deal with crap legacy itti interface
|
||||
if ( t->nb_fd_epoll == 1 ) {
|
||||
while (t->message_queue.empty()) {
|
||||
itti_get_events_locked(task_id, &t->events);
|
||||
pthread_mutex_lock(&t->queue_cond_lock);
|
||||
}
|
||||
} else {
|
||||
if (t->message_queue.empty()) {
|
||||
itti_get_events_locked(task_id, &t->events);
|
||||
pthread_mutex_lock(&t->queue_cond_lock);
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy design: we return even if we have no message
|
||||
// in this case, *received_msg is NULL
|
||||
if (t->message_queue.empty()) {
|
||||
*received_msg=NULL;
|
||||
LOG_D(TMR,"task %s received even from other fd (total fds: %d), returning msg NULL\n",t->admin.name, t->nb_fd_epoll);
|
||||
} else {
|
||||
*received_msg=t->message_queue.back();
|
||||
t->message_queue.pop_back();
|
||||
LOG_D(TMR,"task %s received a message\n",t->admin.name);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock (&t->queue_cond_lock);
|
||||
}
|
||||
|
||||
void itti_poll_msg(task_id_t task_id, MessageDef **received_msg) {
|
||||
//reception of one message, non-blocking
|
||||
task_list_t *t=&tasks[task_id];
|
||||
pthread_mutex_lock(&t->queue_cond_lock);
|
||||
|
||||
if (!t->message_queue.empty()) {
|
||||
LOG_D(TMR,"task %s received a message in polling mode\n",t->admin.name);
|
||||
*received_msg=t->message_queue.back();
|
||||
t->message_queue.pop_back();
|
||||
} else
|
||||
*received_msg=NULL;
|
||||
|
||||
pthread_mutex_unlock (&t->queue_cond_lock);
|
||||
}
|
||||
|
||||
int itti_create_task(task_id_t task_id, void *(*start_routine)(void *), void *args_p) {
|
||||
task_list_t *t=&tasks[task_id];
|
||||
AssertFatal ( pthread_create (&t->thread, NULL, start_routine, args_p) ==0,
|
||||
"Thread creation for task %d failed!\n", task_id);
|
||||
pthread_setname_np( t->thread, itti_get_task_name(task_id) );
|
||||
LOG_I(TMR,"Created Posix thread %s\n", itti_get_task_name(task_id) );
|
||||
#if 1 // BMC test RT prio
|
||||
{
|
||||
int policy;
|
||||
struct sched_param sparam;
|
||||
memset(&sparam, 0, sizeof(sparam));
|
||||
sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-10;
|
||||
policy = SCHED_FIFO ;
|
||||
if (pthread_setschedparam(t->thread, policy, &sparam) != 0) {
|
||||
LOG_E(TMR,"task %s : Failed to set pthread priority\n", itti_get_task_name(task_id) );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void itti_exit_task(void) {
|
||||
pthread_exit (NULL);
|
||||
}
|
||||
|
||||
void itti_terminate_tasks(task_id_t task_id) {
|
||||
// Sends Terminate signals to all tasks.
|
||||
itti_send_terminate_message (task_id);
|
||||
usleep(100*1000); // Allow the tasks to receive the message before going returning to main thread
|
||||
}
|
||||
|
||||
int itti_init(task_id_t task_max, thread_id_t thread_max, MessagesIds messages_id_max, const task_info_t *tasks_info,
|
||||
const message_info_t *messages_info) {
|
||||
AssertFatal(TASK_MAX<UINT16_MAX, "Max itti tasks");
|
||||
|
||||
for(int i=0; i<task_max; ++i) {
|
||||
LOG_I(TMR,"Starting itti queue: %s as task %d\n", tasks_info[i].name, i);
|
||||
pthread_mutex_init(&tasks[i].queue_cond_lock, NULL);
|
||||
memcpy(&tasks[i].admin, &tasks_info[i], sizeof(task_info_t));
|
||||
AssertFatal( ( tasks[i].epoll_fd = epoll_create1(0) ) >=0, "");
|
||||
AssertFatal( ( tasks[i].sem_fd = eventfd(0, EFD_SEMAPHORE) ) >=0, "");
|
||||
itti_subscribe_event_fd((task_id_t)i, tasks[i].sem_fd);
|
||||
|
||||
if (tasks[i].admin.threadFunc != NULL)
|
||||
itti_create_task((task_id_t)i, tasks[i].admin.threadFunc, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_setup(
|
||||
uint32_t interval_sec,
|
||||
uint32_t interval_us,
|
||||
task_id_t task_id,
|
||||
int32_t instance,
|
||||
timer_type_t type,
|
||||
void *timer_arg,
|
||||
long *timer_id) {
|
||||
task_list_t *t=&tasks[task_id];
|
||||
|
||||
do {
|
||||
// set the taskid in the timer id to keep compatible with the legacy API
|
||||
// timer_remove() takes only the timer id as parameter
|
||||
*timer_id=(random()%UINT16_MAX) << 16 | task_id ;
|
||||
} while ( t->timer_map.find(*timer_id) != t->timer_map.end());
|
||||
|
||||
/* Allocate new timer list element */
|
||||
timer_elm_t timer;
|
||||
struct timespec tp;
|
||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||
|
||||
if (interval_us%1000 != 0)
|
||||
LOG_W(TMR, "Can't set timer precision below 1ms, rounding it\n");
|
||||
|
||||
timer.duration = interval_sec*1000+interval_us/1000;
|
||||
timer.timeout= ((uint64_t)tp.tv_sec*1000+tp.tv_nsec/(1000*1000)+timer.duration);
|
||||
timer.instance = instance;
|
||||
timer.type = type;
|
||||
timer.timer_arg = timer_arg;
|
||||
pthread_mutex_lock (&t->queue_cond_lock);
|
||||
t->timer_map[*timer_id]= timer;
|
||||
|
||||
if (timer.timeout < t->next_timer)
|
||||
t->next_timer=timer.timeout;
|
||||
|
||||
eventfd_t sem_counter = 1;
|
||||
AssertFatal ( sizeof(sem_counter) == write(t->sem_fd, &sem_counter, sizeof(sem_counter)), "");
|
||||
pthread_mutex_unlock (&t->queue_cond_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_remove(long timer_id) {
|
||||
task_id_t task_id=(task_id_t)(timer_id&0xffff);
|
||||
int ret;
|
||||
pthread_mutex_lock (&tasks[task_id].queue_cond_lock);
|
||||
ret=tasks[task_id].timer_map.erase(timer_id);
|
||||
pthread_mutex_unlock (&tasks[task_id].queue_cond_lock);
|
||||
|
||||
if (ret==1)
|
||||
return 0;
|
||||
else {
|
||||
LOG_W(TMR, "tried to remove a non existing timer\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
const char *itti_get_message_name(MessagesIds message_id) {
|
||||
return messages_info[message_id].name;
|
||||
}
|
||||
|
||||
const char *itti_get_task_name(task_id_t task_id) {
|
||||
return tasks[task_id].admin.name;
|
||||
}
|
||||
|
||||
// void for compatibility
|
||||
void itti_send_terminate_message(task_id_t task_id) {
|
||||
}
|
||||
|
||||
void itti_wait_tasks_end(void) {
|
||||
while(1)
|
||||
sleep(24*3600);
|
||||
}
|
||||
|
||||
void itti_update_lte_time(uint32_t frame, uint8_t slot) {}
|
||||
void itti_set_task_real_time(task_id_t task_id) {}
|
||||
void itti_mark_task_ready(task_id_t task_id) {
|
||||
// Function meaning is clear, but legacy implementation is wrong
|
||||
// keep it void is fine: today implementation accepts messages in the queue before task is ready
|
||||
}
|
||||
void itti_wait_ready(int wait_tasks) {
|
||||
// Stupid function, kept for compatibility (the parameter is meaningless!!!)
|
||||
}
|
||||
int signal_mask(void) { return 0;}
|
||||
}
|
||||
@@ -0,0 +1,541 @@
|
||||
/*
|
||||
Author: Laurent THOMAS, Open Cells
|
||||
Copyleft: OpenAirInterface software alliance and it's licence
|
||||
*/
|
||||
#ifndef INTERTASK_INTERFACE_H_
|
||||
#define INTERTASK_INTERFACE_H_
|
||||
#include <stdint.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
#include <mem_block.h>
|
||||
#include <assertions.h>
|
||||
|
||||
|
||||
typedef enum timer_type_s {
|
||||
TIMER_PERIODIC,
|
||||
TIMER_ONE_SHOT,
|
||||
TIMER_TYPE_MAX,
|
||||
} timer_type_t;
|
||||
|
||||
typedef struct {
|
||||
void *arg;
|
||||
long timer_id;
|
||||
} timer_has_expired_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t interval_sec;
|
||||
uint32_t interval_us;
|
||||
long task_id;
|
||||
int32_t instance;
|
||||
timer_type_t type;
|
||||
void *timer_arg;
|
||||
long timer_id;
|
||||
} timer_create_t;
|
||||
|
||||
typedef struct {
|
||||
long task_id;
|
||||
long timer_id;
|
||||
} timer_delete_t;
|
||||
|
||||
|
||||
typedef struct itti_lte_time_s {
|
||||
uint32_t frame;
|
||||
uint8_t slot;
|
||||
} itti_lte_time_t;
|
||||
|
||||
|
||||
typedef struct IttiMsgEmpty_s {
|
||||
} IttiMsgEmpty;
|
||||
|
||||
typedef struct IttiMsgText_s {
|
||||
uint32_t size;
|
||||
char text[];
|
||||
} IttiMsgText;
|
||||
|
||||
#include <openair2/COMMON/phy_messages_types.h>
|
||||
#include <openair2/COMMON/mac_messages_types.h>
|
||||
#include <openair2/COMMON/rlc_messages_types.h>
|
||||
#include <openair2/COMMON/pdcp_messages_types.h>
|
||||
#include <openair2/COMMON/networkDef.h>
|
||||
#include <openair2/COMMON/as_message.h>
|
||||
#include <openair2/RRC/LTE/rrc_types.h>
|
||||
#include <openair2/COMMON/rrc_messages_types.h>
|
||||
|
||||
#include <openair3/NAS/COMMON/UTIL/OctetString.h>
|
||||
#include <openair3/NAS/COMMON/IES/AccessPointName.h>
|
||||
#include <openair3/NAS/COMMON/IES/AdditionalUpdateResult.h>
|
||||
#include <openair3/NAS/COMMON/IES/AdditionalUpdateType.h>
|
||||
#include <openair3/NAS/COMMON/IES/ApnAggregateMaximumBitRate.h>
|
||||
#include <openair3/NAS/COMMON/IES/AuthenticationFailureParameter.h>
|
||||
#include <openair3/NAS/COMMON/IES/AuthenticationParameterAutn.h>
|
||||
#include <openair3/NAS/COMMON/IES/AuthenticationParameterRand.h>
|
||||
#include <openair3/NAS/COMMON/IES/AuthenticationResponseParameter.h>
|
||||
#include <openair3/NAS/COMMON/IES/CipheringKeySequenceNumber.h>
|
||||
#include <openair3/NAS/COMMON/IES/Cli.h>
|
||||
#include <openair3/NAS/COMMON/IES/CsfbResponse.h>
|
||||
#include <openair3/NAS/COMMON/IES/DaylightSavingTime.h>
|
||||
#include <openair3/NAS/COMMON/IES/DetachType.h>
|
||||
#include <openair3/NAS/COMMON/IES/DrxParameter.h>
|
||||
#include <openair3/NAS/COMMON/IES/EmergencyNumberList.h>
|
||||
#include <openair3/NAS/COMMON/IES/EmmCause.h>
|
||||
#include <openair3/NAS/COMMON/IES/EpsAttachResult.h>
|
||||
#include <openair3/NAS/COMMON/IES/EpsAttachType.h>
|
||||
#include <openair3/NAS/COMMON/IES/EpsBearerContextStatus.h>
|
||||
#include <openair3/NAS/COMMON/IES/EpsBearerIdentity.h>
|
||||
#include <openair3/NAS/COMMON/IES/EpsMobileIdentity.h>
|
||||
#include <openair3/NAS/COMMON/IES/EpsNetworkFeatureSupport.h>
|
||||
#include <openair3/NAS/COMMON/IES/EpsQualityOfService.h>
|
||||
#include <openair3/NAS/COMMON/IES/EpsUpdateResult.h>
|
||||
#include <openair3/NAS/COMMON/IES/EpsUpdateType.h>
|
||||
#include <openair3/NAS/COMMON/IES/EsmCause.h>
|
||||
#include <openair3/NAS/COMMON/IES/EsmInformationTransferFlag.h>
|
||||
#include <openair3/NAS/COMMON/IES/EsmMessageContainer.h>
|
||||
#include <openair3/NAS/COMMON/IES/GprsTimer.h>
|
||||
#include <openair3/NAS/COMMON/IES/GutiType.h>
|
||||
#include <openair3/NAS/COMMON/IES/IdentityType2.h>
|
||||
#include <openair3/NAS/COMMON/IES/ImeisvRequest.h>
|
||||
#include <openair3/NAS/COMMON/IES/KsiAndSequenceNumber.h>
|
||||
#include <openair3/NAS/COMMON/IES/LcsClientIdentity.h>
|
||||
#include <openair3/NAS/COMMON/IES/LcsIndicator.h>
|
||||
#include <openair3/NAS/COMMON/IES/LinkedEpsBearerIdentity.h>
|
||||
#include <openair3/NAS/COMMON/IES/LlcServiceAccessPointIdentifier.h>
|
||||
#include <openair3/NAS/COMMON/IES/LocationAreaIdentification.h>
|
||||
#include <openair3/NAS/COMMON/IES/MessageType.h>
|
||||
#include <openair3/NAS/COMMON/IES/MobileIdentity.h>
|
||||
#include <openair3/NAS/COMMON/IES/MobileStationClassmark2.h>
|
||||
#include <openair3/NAS/COMMON/IES/MobileStationClassmark3.h>
|
||||
#include <openair3/NAS/COMMON/IES/MsNetworkCapability.h>
|
||||
#include <openair3/NAS/COMMON/IES/MsNetworkFeatureSupport.h>
|
||||
#include <openair3/NAS/COMMON/IES/NasKeySetIdentifier.h>
|
||||
#include <openair3/NAS/COMMON/IES/NasMessageContainer.h>
|
||||
#include <openair3/NAS/COMMON/IES/NasRequestType.h>
|
||||
#include <openair3/NAS/COMMON/IES/NasSecurityAlgorithms.h>
|
||||
#include <openair3/NAS/COMMON/IES/NetworkName.h>
|
||||
#include <openair3/NAS/COMMON/IES/Nonce.h>
|
||||
#include <openair3/NAS/COMMON/IES/PacketFlowIdentifier.h>
|
||||
#include <openair3/NAS/COMMON/IES/PagingIdentity.h>
|
||||
#include <openair3/NAS/COMMON/IES/PdnAddress.h>
|
||||
#include <openair3/NAS/COMMON/IES/PdnType.h>
|
||||
#include <openair3/NAS/COMMON/IES/PlmnList.h>
|
||||
#include <openair3/NAS/COMMON/IES/ProcedureTransactionIdentity.h>
|
||||
#include <openair3/NAS/COMMON/IES/ProtocolConfigurationOptions.h>
|
||||
#include <openair3/NAS/COMMON/IES/ProtocolDiscriminator.h>
|
||||
#include <openair3/NAS/COMMON/IES/PTmsiSignature.h>
|
||||
#include <openair3/NAS/COMMON/IES/QualityOfService.h>
|
||||
#include <openair3/NAS/COMMON/IES/RadioPriority.h>
|
||||
#include <openair3/NAS/COMMON/IES/SecurityHeaderType.h>
|
||||
#include <openair3/NAS/COMMON/IES/ServiceType.h>
|
||||
#include <openair3/NAS/COMMON/IES/ShortMac.h>
|
||||
#include <openair3/NAS/COMMON/IES/SsCode.h>
|
||||
#include <openair3/NAS/COMMON/IES/SupportedCodecList.h>
|
||||
#include <openair3/NAS/COMMON/IES/TimeZoneAndTime.h>
|
||||
#include <openair3/NAS/COMMON/IES/TimeZone.h>
|
||||
#include <openair3/NAS/COMMON/IES/TmsiStatus.h>
|
||||
#include <openair3/NAS/COMMON/IES/TrackingAreaIdentity.h>
|
||||
#include <openair3/NAS/COMMON/IES/TrackingAreaIdentityList.h>
|
||||
#include <openair3/NAS/COMMON/IES/TrafficFlowAggregateDescription.h>
|
||||
#include <openair3/NAS/COMMON/IES/TrafficFlowTemplate.h>
|
||||
#include <openair3/NAS/COMMON/IES/TransactionIdentifier.h>
|
||||
#include <openair3/NAS/COMMON/IES/UeNetworkCapability.h>
|
||||
#include <openair3/NAS/COMMON/IES/UeRadioCapabilityInformationUpdateNeeded.h>
|
||||
#include <openair3/NAS/COMMON/IES/UeSecurityCapability.h>
|
||||
#include <openair3/NAS/COMMON/IES/VoiceDomainPreferenceAndUeUsageSetting.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextAccept.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextReject.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextRequest.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/ActivateDefaultEpsBearerContextAccept.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/ActivateDefaultEpsBearerContextReject.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/ActivateDefaultEpsBearerContextRequest.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/BearerResourceAllocationReject.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/BearerResourceAllocationRequest.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/BearerResourceModificationReject.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/BearerResourceModificationRequest.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/DeactivateEpsBearerContextAccept.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/DeactivateEpsBearerContextRequest.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/esm_cause.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/EsmInformationRequest.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/EsmInformationResponse.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/EsmStatus.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/ModifyEpsBearerContextAccept.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/ModifyEpsBearerContextReject.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/ModifyEpsBearerContextRequest.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/PdnConnectivityReject.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/PdnConnectivityRequest.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/PdnDisconnectReject.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/PdnDisconnectRequest.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/esm_msgDef.h>
|
||||
#include <openair3/NAS/COMMON/ESM/MSG/esm_msg.h>
|
||||
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/AttachAccept.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/AttachComplete.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/AttachReject.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/AttachRequest.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/AuthenticationFailure.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/AuthenticationReject.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/AuthenticationRequest.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/AuthenticationResponse.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/CsServiceNotification.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/DetachAccept.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/DetachRequest.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/DownlinkNasTransport.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/emm_cause.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/EmmInformation.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/EmmStatus.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/ExtendedServiceRequest.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/GutiReallocationCommand.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/GutiReallocationComplete.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/IdentityRequest.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/IdentityResponse.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/NASSecurityModeCommand.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/NASSecurityModeComplete.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/SecurityModeReject.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/ServiceReject.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/ServiceRequest.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/TrackingAreaUpdateAccept.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/TrackingAreaUpdateComplete.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/TrackingAreaUpdateReject.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/TrackingAreaUpdateRequest.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/UplinkNasTransport.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/emm_msgDef.h>
|
||||
#include <openair3/NAS/COMMON/EMM/MSG/emm_msg.h>
|
||||
|
||||
#include <openair3/NAS/COMMON/API/NETWORK/nas_message.h>
|
||||
#include <openair2/COMMON/nas_messages_types.h>
|
||||
#if ENABLE_RAL
|
||||
#include <ral_messages_types.h>
|
||||
#endif
|
||||
#include <openair2/COMMON/s1ap_messages_types.h>
|
||||
#include <openair2/COMMON/x2ap_messages_types.h>
|
||||
#include <openair2/COMMON/sctp_messages_types.h>
|
||||
#include <openair2/COMMON/udp_messages_types.h>
|
||||
#include <openair2/COMMON/gtpv1_u_messages_types.h>
|
||||
#include <openair3/SCTP/sctp_eNB_task.h>
|
||||
#include <openair3/NAS/UE/nas_proc_defs.h>
|
||||
#include <openair3/NAS/UE/ESM/esmData.h>
|
||||
#include <openair3/NAS/COMMON/UTIL/nas_timer.h>
|
||||
#include <openair3/NAS/UE/ESM/esm_pt_defs.h>
|
||||
#include <openair3/NAS/UE/EMM/emm_proc_defs.h>
|
||||
#include <openair3/NAS/UE/EMM/emmData.h>
|
||||
#include <openair3/NAS/UE/EMM/IdleMode_defs.h>
|
||||
#include <openair3/NAS/UE/EMM/emm_fsm_defs.h>
|
||||
#include <openair3/NAS/UE/EMM/emmData.h>
|
||||
#include <openair3/NAS/COMMON/securityDef.h>
|
||||
#include <openair3/NAS/UE/EMM/Authentication.h>
|
||||
#include <openair3/NAS/UE/EMM/SecurityModeControl.h>
|
||||
#include <openair3/NAS/UE/API/USIM/usim_api.h>
|
||||
#include <openair3/NAS/COMMON/userDef.h>
|
||||
#include <openair3/NAS/UE/API/USER/at_command.h>
|
||||
#include <openair3/NAS/UE/API/USER/at_response.h>
|
||||
#include <openair3/NAS/UE/API/USER/user_api_defs.h>
|
||||
#include <openair3/NAS/UE/EMM/LowerLayer_defs.h>
|
||||
#include <openair3/NAS/UE/user_defs.h>
|
||||
#include <openair3/NAS/UE/nas_ue_task.h>
|
||||
#include <openair3/S1AP/s1ap_eNB.h>
|
||||
//#include <proto.h>
|
||||
|
||||
#include <openair3/GTPV1-U/gtpv1u_eNB_task.h>
|
||||
void *rrc_enb_process_itti_msg(void *);
|
||||
#include <openair3/SCTP/sctp_eNB_task.h>
|
||||
#include <openair3/S1AP/s1ap_eNB.h>
|
||||
|
||||
/*
|
||||
static const char *const messages_definition_xml = {
|
||||
#include <messages_xml.h>
|
||||
};
|
||||
*/
|
||||
|
||||
typedef uint32_t MessageHeaderSize;
|
||||
typedef uint32_t itti_message_types_t;
|
||||
typedef unsigned long message_number_t;
|
||||
#define MESSAGE_NUMBER_SIZE (sizeof(unsigned long))
|
||||
|
||||
typedef enum task_priorities_e {
|
||||
TASK_PRIORITY_MAX = 100,
|
||||
TASK_PRIORITY_MAX_LEAST = 85,
|
||||
TASK_PRIORITY_MED_PLUS = 70,
|
||||
TASK_PRIORITY_MED = 55,
|
||||
TASK_PRIORITY_MED_LEAST = 40,
|
||||
TASK_PRIORITY_MIN_PLUS = 25,
|
||||
TASK_PRIORITY_MIN = 10,
|
||||
} task_priorities_t;
|
||||
|
||||
typedef struct {
|
||||
task_priorities_t priority;
|
||||
unsigned int queue_size;
|
||||
/* Printable name */
|
||||
char name[256];
|
||||
void *(*func)(void *) ;
|
||||
void *(*threadFunc)(void *) ;
|
||||
} task_info_t;
|
||||
//
|
||||
//TASK_DEF(TASK_RRC_ENB, TASK_PRIORITY_MED, 200, NULL,NULL)
|
||||
//TASK_DEF(TASK_RRC_ENB, TASK_PRIORITY_MED, 200, NULL, NULL)
|
||||
//TASK_DEF(TASK_GTPV1_U, TASK_PRIORITY_MED, 1000,NULL, NULL)
|
||||
//TASK_DEF(TASK_UDP, TASK_PRIORITY_MED, 1000, NULL, NULL)
|
||||
|
||||
#define FOREACH_TASK(TASK_DEF) \
|
||||
TASK_DEF(TASK_UNKNOWN, TASK_PRIORITY_MED, 50, NULL, NULL) \
|
||||
TASK_DEF(TASK_TIMER, TASK_PRIORITY_MED, 10, NULL, NULL) \
|
||||
TASK_DEF(TASK_L2L1, TASK_PRIORITY_MAX, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_BM, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_PHY_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_MAC_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_RLC_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_RRC_ENB_NB_IoT, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_PDCP_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_RRC_ENB, TASK_PRIORITY_MED, 200, NULL,NULL)\
|
||||
TASK_DEF(TASK_RAL_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_S1AP, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_X2AP, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_SCTP, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_ENB_APP, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_FLEXRAN_AGENT,TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_PHY_UE, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_MAC_UE, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_RLC_UE, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_PDCP_UE, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_RRC_UE, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_NAS_UE, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_RAL_UE, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_MSC, TASK_PRIORITY_MED, 200, NULL, NULL)\
|
||||
TASK_DEF(TASK_GTPV1_U, TASK_PRIORITY_MED, 1000,NULL, NULL)\
|
||||
TASK_DEF(TASK_UDP, TASK_PRIORITY_MED, 1000, NULL, NULL)\
|
||||
TASK_DEF(TASK_MAX, TASK_PRIORITY_MED, 200, NULL, NULL)
|
||||
|
||||
#define TASK_DEF(TaskID, pRIO, qUEUEsIZE, FuNc, ThreadFunc) { pRIO, qUEUEsIZE, #TaskID, FuNc, ThreadFunc },
|
||||
|
||||
/* Map task id to printable name. */
|
||||
static const task_info_t tasks_info[] = {
|
||||
FOREACH_TASK(TASK_DEF)
|
||||
};
|
||||
|
||||
#define TASK_ENUM(TaskID, pRIO, qUEUEsIZE, FuNc,ThreadFunc ) TaskID,
|
||||
//! Tasks id of each task
|
||||
typedef enum {
|
||||
FOREACH_TASK(TASK_ENUM)
|
||||
} task_id_t;
|
||||
|
||||
|
||||
typedef task_id_t thread_id_t;
|
||||
|
||||
typedef enum message_priorities_e {
|
||||
MESSAGE_PRIORITY_MAX = 100,
|
||||
MESSAGE_PRIORITY_MAX_LEAST = 85,
|
||||
MESSAGE_PRIORITY_MED_PLUS = 70,
|
||||
MESSAGE_PRIORITY_MED = 55,
|
||||
MESSAGE_PRIORITY_MED_LEAST = 40,
|
||||
MESSAGE_PRIORITY_MIN_PLUS = 25,
|
||||
MESSAGE_PRIORITY_MIN = 10,
|
||||
} message_priorities_t;
|
||||
|
||||
|
||||
#define FOREACH_MSG(INTERNAL_MSG) \
|
||||
INTERNAL_MSG(TIMER_HAS_EXPIRED, MESSAGE_PRIORITY_MED, timer_has_expired_t, timer_has_expired) \
|
||||
INTERNAL_MSG(INITIALIZE_MESSAGE, MESSAGE_PRIORITY_MED, IttiMsgEmpty, initialize_message) \
|
||||
INTERNAL_MSG(ACTIVATE_MESSAGE, MESSAGE_PRIORITY_MED, IttiMsgEmpty, activate_message) \
|
||||
INTERNAL_MSG(DEACTIVATE_MESSAGE, MESSAGE_PRIORITY_MED, IttiMsgEmpty, deactivate_message) \
|
||||
INTERNAL_MSG(TERMINATE_MESSAGE, MESSAGE_PRIORITY_MAX, IttiMsgEmpty, terminate_message) \
|
||||
INTERNAL_MSG(MESSAGE_TEST, MESSAGE_PRIORITY_MED, IttiMsgEmpty, message_test)
|
||||
|
||||
/* This enum defines messages ids. Each one is unique. */
|
||||
typedef enum {
|
||||
#define MESSAGE_DEF(iD, pRIO, sTRUCT, fIELDnAME) iD,
|
||||
FOREACH_MSG(MESSAGE_DEF)
|
||||
#include <all_msg.h>
|
||||
#undef MESSAGE_DEF
|
||||
MESSAGES_ID_MAX,
|
||||
} MessagesIds;
|
||||
|
||||
typedef union msg_s {
|
||||
#define MESSAGE_DEF(iD, pRIO, sTRUCT, fIELDnAME) sTRUCT fIELDnAME;
|
||||
FOREACH_MSG(MESSAGE_DEF)
|
||||
#include <all_msg.h>
|
||||
#undef MESSAGE_DEF
|
||||
} msg_t;
|
||||
|
||||
typedef struct MessageHeader_s {
|
||||
MessagesIds messageId; /**< Unique message id as referenced in enum MessagesIds */
|
||||
task_id_t originTaskId; /**< ID of the sender task */
|
||||
task_id_t destinationTaskId; /**< ID of the destination task */
|
||||
instance_t instance; /**< Task instance for virtualization */
|
||||
itti_lte_time_t lte_time;
|
||||
MessageHeaderSize ittiMsgSize; /**< Message size (not including header size) */
|
||||
} MessageHeader;
|
||||
|
||||
typedef struct message_info_s {
|
||||
int id;
|
||||
message_priorities_t priority;
|
||||
/* Message payload size */
|
||||
MessageHeaderSize size;
|
||||
/* Printable name */
|
||||
const char name[256];
|
||||
} message_info_t;
|
||||
|
||||
/* Map message id to message information */
|
||||
static const message_info_t messages_info[] = {
|
||||
#define MESSAGE_DEF(iD, pRIO, sTRUCT, fIELDnAME) { iD, pRIO, sizeof(sTRUCT), #iD },
|
||||
FOREACH_MSG(MESSAGE_DEF)
|
||||
#include <all_msg.h>
|
||||
#undef MESSAGE_DEF
|
||||
};
|
||||
|
||||
typedef struct __attribute__ ((__packed__)) MessageDef_s {
|
||||
MessageHeader ittiMsgHeader; /**< Message header */
|
||||
msg_t ittiMsg;
|
||||
} MessageDef;
|
||||
|
||||
|
||||
|
||||
/* Extract the instance from a message */
|
||||
#define ITTI_MESSAGE_GET_INSTANCE(mESSAGE) ((mESSAGE)->ittiMsgHeader.instance)
|
||||
#define ITTI_MSG_ID(mSGpTR) ((mSGpTR)->ittiMsgHeader.messageId)
|
||||
#define ITTI_MSG_ORIGIN_ID(mSGpTR) ((mSGpTR)->ittiMsgHeader.originTaskId)
|
||||
#define ITTI_MSG_DESTINATION_ID(mSGpTR) ((mSGpTR)->ittiMsgHeader.destinationTaskId)
|
||||
#define ITTI_MSG_INSTANCE(mSGpTR) ((mSGpTR)->ittiMsgHeader.instance)
|
||||
#define ITTI_MSG_NAME(mSGpTR) itti_get_message_name(ITTI_MSG_ID(mSGpTR))
|
||||
#define ITTI_MSG_ORIGIN_NAME(mSGpTR) itti_get_task_name(ITTI_MSG_ORIGIN_ID(mSGpTR))
|
||||
#define ITTI_MSG_DESTINATION_NAME(mSGpTR) itti_get_task_name(ITTI_MSG_DESTINATION_ID(mSGpTR))
|
||||
#define TIMER_HAS_EXPIRED(mSGpTR) (mSGpTR)->ittiMsg.timer_has_expired
|
||||
|
||||
#define INSTANCE_DEFAULT (UINT16_MAX - 1)
|
||||
|
||||
static inline int64_t clock_difftime_ns(struct timespec start, struct timespec end) {
|
||||
return (int64_t)( end.tv_sec-start.tv_sec) * (int64_t)(1000*1000*1000) + end.tv_nsec-start.tv_nsec;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \brief Send a message to a task (could be itself)
|
||||
\param task_id Task ID
|
||||
\param instance Instance of the task used for virtualization
|
||||
\param message Pointer to the message to send
|
||||
@returns -1 on failure, 0 otherwise
|
||||
**/
|
||||
int itti_send_msg_to_task(task_id_t task_id, instance_t instance, MessageDef *message);
|
||||
|
||||
/** \brief Add a new fd to monitor.
|
||||
NOTE: it is up to the user to read data associated with the fd
|
||||
\param task_id Task ID of the receiving task
|
||||
\param fd The file descriptor to monitor
|
||||
**/
|
||||
void itti_subscribe_event_fd(task_id_t task_id, int fd);
|
||||
|
||||
/** \brief Remove a fd from the list of fd to monitor
|
||||
\param task_id Task ID of the task
|
||||
\param fd The file descriptor to remove
|
||||
**/
|
||||
void itti_unsubscribe_event_fd(task_id_t task_id, int fd);
|
||||
|
||||
/** \brief Return the list of events excluding the fd associated with itti
|
||||
\param task_id Task ID of the task
|
||||
\param events events list
|
||||
@returns number of events to handle
|
||||
**/
|
||||
int itti_get_events(task_id_t task_id, struct epoll_event **events);
|
||||
|
||||
/** \brief Retrieves a message in the queue associated to task_id.
|
||||
If the queue is empty, the thread is blocked till a new message arrives.
|
||||
\param task_id Task ID of the receiving task
|
||||
\param received_msg Pointer to the allocated message
|
||||
**/
|
||||
void itti_receive_msg(task_id_t task_id, MessageDef **received_msg);
|
||||
|
||||
/** \brief Try to retrieves a message in the queue associated to task_id.
|
||||
\param task_id Task ID of the receiving task
|
||||
\param received_msg Pointer to the allocated message
|
||||
**/
|
||||
void itti_poll_msg(task_id_t task_id, MessageDef **received_msg);
|
||||
|
||||
/** \brief Start thread associated to the task
|
||||
\param task_id task to start
|
||||
\param start_routine entry point for the task
|
||||
\param args_p Optional argument to pass to the start routine
|
||||
@returns -1 on failure, 0 otherwise
|
||||
**/
|
||||
int itti_create_task(task_id_t task_id,
|
||||
void *(*start_routine) (void *),
|
||||
void *args_p);
|
||||
|
||||
/** \brief Exit the current task.
|
||||
**/
|
||||
void itti_exit_task(void);
|
||||
|
||||
/** \brief Initiate termination of all tasks.
|
||||
\param task_id task that is completed
|
||||
**/
|
||||
void itti_terminate_tasks(task_id_t task_id);
|
||||
|
||||
// Void for legacy compatibility
|
||||
void itti_wait_ready(int wait_tasks);
|
||||
void itti_mark_task_ready(task_id_t task_id);
|
||||
|
||||
/** \brief Return the printable string associated with the message
|
||||
\param message_id Id of the message
|
||||
**/
|
||||
const char *itti_get_message_name(MessagesIds message_id);
|
||||
|
||||
/** \brief Return the printable string associated with a task id
|
||||
\param thread_id Id of the task
|
||||
**/
|
||||
const char *itti_get_task_name(task_id_t task_id);
|
||||
|
||||
/** \brief Alloc and memset(0) a new itti message.
|
||||
\param origin_task_id Task ID of the sending task
|
||||
\param message_id Message ID
|
||||
@returns NULL in case of failure or newly allocated mesage ref
|
||||
**/
|
||||
MessageDef *itti_alloc_new_message(
|
||||
task_id_t origin_task_id,
|
||||
MessagesIds message_id);
|
||||
|
||||
/** \brief Alloc and memset(0) a new itti message.
|
||||
\param origin_task_id Task ID of the sending task
|
||||
\param message_id Message ID
|
||||
\param size size of the payload to send
|
||||
@returns NULL in case of failure or newly allocated mesage ref
|
||||
**/
|
||||
MessageDef *itti_alloc_new_message_sized(
|
||||
task_id_t origin_task_id,
|
||||
MessagesIds message_id,
|
||||
MessageHeaderSize size);
|
||||
|
||||
/** \brief handle signals and wait for all threads to join when the process complete.
|
||||
This function should be called from the main thread after having created all ITTI tasks.
|
||||
**/
|
||||
void itti_wait_tasks_end(void);
|
||||
#define THREAD_MAX 0 //for compatibility
|
||||
void itti_set_task_real_time(task_id_t task_id);
|
||||
|
||||
/** \brief Send a termination message to all tasks.
|
||||
\param task_id task that is broadcasting the message.
|
||||
**/
|
||||
void itti_send_terminate_message(task_id_t task_id);
|
||||
|
||||
void *itti_malloc(task_id_t origin_task_id, task_id_t destination_task_id, ssize_t size);
|
||||
void *calloc_or_fail(size_t size);
|
||||
void *malloc_or_fail(size_t size);
|
||||
int memory_read(const char *datafile, void *data, size_t size);
|
||||
int itti_free(task_id_t task_id, void *ptr);
|
||||
|
||||
int itti_init(task_id_t task_max, thread_id_t thread_max, MessagesIds messages_id_max, const task_info_t *tasks_info,
|
||||
const message_info_t *messages_info);
|
||||
int timer_setup(
|
||||
uint32_t interval_sec,
|
||||
uint32_t interval_us,
|
||||
task_id_t task_id,
|
||||
int32_t instance,
|
||||
timer_type_t type,
|
||||
void *timer_arg,
|
||||
long *timer_id);
|
||||
|
||||
|
||||
int timer_remove(long timer_id);
|
||||
#define timer_stop timer_remove
|
||||
int signal_handle(int *end);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* INTERTASK_INTERFACE_H_ */
|
||||
@@ -199,28 +199,29 @@ int proccmd_show(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
print_threads(buf,debug,prnt);
|
||||
}
|
||||
if (strcasestr(buf,"loglvl") != NULL) {
|
||||
prnt(" component level enabled\n");
|
||||
prnt("\n component level enabled output\n");
|
||||
for (int i=MIN_LOG_COMPONENTS; i < MAX_LOG_COMPONENTS; i++) {
|
||||
if (g_log->log_component[i].name != NULL) {
|
||||
prnt("%02i %17.17s:%10.10s %s\n",i ,g_log->log_component[i].name,
|
||||
map_int_to_str(log_level_names,g_log->log_component[i].level),
|
||||
((g_log->log_component[i].interval>0)?"Y":"N") );
|
||||
prnt("%02i %17.17s:%10.10s %s %s\n",i ,g_log->log_component[i].name,
|
||||
map_int_to_str(log_level_names,(g_log->log_component[i].level>=0)?g_log->log_component[i].level:g_log->log_component[i].savedlevel),
|
||||
((g_log->log_component[i].level>=0)?"Y":"N"),
|
||||
((g_log->log_component[i].filelog>0)?g_log->log_component[i].filelog_name:"stdout"));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (strcasestr(buf,"logopt") != NULL) {
|
||||
prnt(" option enabled\n");
|
||||
prnt("\n option enabled\n");
|
||||
for (int i=0; log_options[i].name != NULL; i++) {
|
||||
prnt("%02i %17.17s %10.10s \n",i ,log_options[i].name,
|
||||
((g_log->flag & log_options[i].value)?"Y":"N") );
|
||||
}
|
||||
}
|
||||
if (strcasestr(buf,"dbgopt") != NULL) {
|
||||
prnt(" option debug matlab\n");
|
||||
prnt("\n module debug dumpfile\n");
|
||||
for (int i=0; log_maskmap[i].name != NULL ; i++) {
|
||||
prnt("%02i %17.17s %5.5s %5.5s\n",i ,log_maskmap[i].name,
|
||||
prnt("%02i %17.17s %5.5s %5.5s\n",i ,log_maskmap[i].name,
|
||||
((g_log->debug_mask & log_maskmap[i].value)?"Y":"N"),
|
||||
((g_log->matlab_mask & log_maskmap[i].value)?"Y":"N") );
|
||||
((g_log->dump_mask & log_maskmap[i].value)?"Y":"N") );
|
||||
}
|
||||
}
|
||||
if (strcasestr(buf,"config") != NULL) {
|
||||
@@ -302,8 +303,6 @@ char sv1[64];
|
||||
}
|
||||
int proccmd_exit(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
extern void exit_fun(const char* s);
|
||||
|
||||
if (debug > 0)
|
||||
prnt("process module received %s\n",buf);
|
||||
|
||||
@@ -337,15 +336,15 @@ int s = sscanf(buf,"%ms %i-%i\n",&logsubcmd, &idx1,&idx2);
|
||||
prnt("Available log levels: \n ");
|
||||
for (int i=0; log_level_names[i].name != NULL; i++)
|
||||
prnt("%s ",log_level_names[i].name);
|
||||
prnt("\n");
|
||||
prnt("\n\n");
|
||||
prnt("Available display options: \n ");
|
||||
for (int i=0; log_options[i].name != NULL; i++)
|
||||
prnt("%s ",log_options[i].name);
|
||||
prnt("\n");
|
||||
prnt("Available debug or matlab options: \n ");
|
||||
prnt("\n\n");
|
||||
prnt("Available debug and dump options: \n ");
|
||||
for (int i=0; log_maskmap[i].name != NULL; i++)
|
||||
prnt("%s ",log_maskmap[i].name);
|
||||
prnt("\n");
|
||||
prnt("\n\n");
|
||||
proccmd_show("loglvl",debug,prnt);
|
||||
proccmd_show("logopt",debug,prnt);
|
||||
proccmd_show("dbgopt",debug,prnt);
|
||||
@@ -377,7 +376,7 @@ int s = sscanf(buf,"%ms %i-%i\n",&logsubcmd, &idx1,&idx2);
|
||||
else if (l == 2 && strcmp(logparam,"debug") == 0){
|
||||
optbit=map_str_to_int(log_maskmap,opt);
|
||||
if (optbit < 0) {
|
||||
prnt("debug flag %s unknown\n",opt);
|
||||
prnt("module %s unknown\n",opt);
|
||||
} else {
|
||||
if (idx1 > 0)
|
||||
SET_LOG_DEBUG(optbit);
|
||||
@@ -386,42 +385,51 @@ int s = sscanf(buf,"%ms %i-%i\n",&logsubcmd, &idx1,&idx2);
|
||||
proccmd_show("dbgopt",debug,prnt);
|
||||
}
|
||||
}
|
||||
else if (l == 2 && strcmp(logparam,"matlab") == 0){
|
||||
else if (l == 2 && strcmp(logparam,"dump") == 0){
|
||||
optbit=map_str_to_int(log_maskmap,opt);
|
||||
if (optbit < 0) {
|
||||
prnt("matlab flag %s unknown\n",opt);
|
||||
prnt("module %s unknown\n",opt);
|
||||
} else {
|
||||
if (idx1 > 0)
|
||||
SET_LOG_MATLAB(optbit);
|
||||
SET_LOG_DUMP(optbit);
|
||||
else
|
||||
CLEAR_LOG_MATLAB(optbit);
|
||||
CLEAR_LOG_DUMP(optbit);
|
||||
proccmd_show("dbgopt",debug,prnt);
|
||||
}
|
||||
}
|
||||
if (logparam != NULL) free(logparam);
|
||||
if (opt != NULL) free(opt);
|
||||
} else if ( s == 3 && logsubcmd != NULL) {
|
||||
int level, interval;
|
||||
int level, enable,filelog;
|
||||
char *tmpstr=NULL;
|
||||
char *logparam=NULL;
|
||||
int l;
|
||||
|
||||
level = interval = -1;
|
||||
level = OAILOG_DISABLE - 1;
|
||||
filelog = -1;
|
||||
enable=-1;
|
||||
l=sscanf(logsubcmd,"%m[^'_']_%m[^'_']",&logparam,&tmpstr);
|
||||
if (debug > 0)
|
||||
prnt("l=%i, %s %s\n",l,((logparam==NULL)?"\"\"":logparam), ((tmpstr==NULL)?"\"\"":tmpstr));
|
||||
if (l ==2 ) {
|
||||
if (strcmp(logparam,"level") == 0) {
|
||||
level=map_str_to_int(log_level_names,tmpstr);
|
||||
if (level < 0) prnt("level %s unknown\n",tmpstr);
|
||||
if (level < 0) {
|
||||
prnt("level %s unknown\n",tmpstr);
|
||||
level=OAILOG_DISABLE - 1;
|
||||
}
|
||||
} else {
|
||||
prnt("%s%s unknown log sub command \n",logparam, tmpstr);
|
||||
}
|
||||
} else if (l ==1 ) {
|
||||
if (strcmp(logparam,"enable") == 0) {
|
||||
interval = 1;
|
||||
enable=1;
|
||||
} else if (strcmp(logparam,"disable") == 0) {
|
||||
interval = 0;
|
||||
level=OAILOG_DISABLE;
|
||||
} else if (strcmp(logparam,"file") == 0) {
|
||||
filelog = 1 ;
|
||||
} else if (strcmp(logparam,"nofile") == 0) {
|
||||
filelog = 0 ;
|
||||
} else {
|
||||
prnt("%s%s unknown log sub command \n",logparam, tmpstr);
|
||||
}
|
||||
@@ -431,20 +439,18 @@ int s = sscanf(buf,"%ms %i-%i\n",&logsubcmd, &idx1,&idx2);
|
||||
if (logparam != NULL) free(logparam);
|
||||
if (tmpstr != NULL) free(tmpstr);
|
||||
for (int i=idx1; i<=idx2 ; i++) {
|
||||
if (level < 0) {
|
||||
level=g_log->log_component[i].level;
|
||||
}
|
||||
if (interval < 0) {
|
||||
interval=g_log->log_component[i].interval;
|
||||
}
|
||||
set_log(i, level, interval);
|
||||
prnt("log level comp %i %s set to %s (%s)\n",
|
||||
i,((g_log->log_component[i].name==NULL)?"":g_log->log_component[i].name),
|
||||
map_int_to_str(log_level_names,g_log->log_component[i].level),
|
||||
((g_log->log_component[i].interval>0)?"enabled":"disabled"));
|
||||
|
||||
|
||||
}
|
||||
if (level >= OAILOG_DISABLE)
|
||||
set_log(i, level);
|
||||
else if ( enable == 1)
|
||||
set_log(i,g_log->log_component[i].savedlevel);
|
||||
else if ( filelog == 1 ) {
|
||||
set_component_filelog(i);
|
||||
} else if ( filelog == 0 ) {
|
||||
close_component_filelog(i);
|
||||
}
|
||||
|
||||
}
|
||||
proccmd_show("loglvl",debug,prnt);
|
||||
} else {
|
||||
prnt("%s: wrong log command...\n",buf);
|
||||
}
|
||||
|
||||
@@ -48,13 +48,15 @@ telnetshell_vardef_t proc_vardef[] = {
|
||||
show: display current log configuration \n\
|
||||
online, noonline: enable or disable console logs \n\
|
||||
enable, disable id1-id2: enable or disable logs for components index id1 to id2 \n\
|
||||
file, nofile id1-id2: enable or disable redirecting logs to file for components index id1 to id2 \n\
|
||||
logfile name depends on component name and is printed in the show command \n\
|
||||
level_<level> id1-id2: set log level to <level> for components index id1 to id2 \n\
|
||||
use the show command to get the authorized values for <level> and the list of component \
|
||||
indexes that can be used for id1 and id2 \n\
|
||||
use the show command to get the authorized values for \n\
|
||||
<level> and the list of component indexes that can be used for id1 and id2 \n\
|
||||
print_<opt> <0|1> disable or enable the \"opt\" log option, use the show command to get \
|
||||
the available options\n\
|
||||
matlab_<opt> debug_<func> disable or enable the debug code or matlab file generation \
|
||||
for \"func\" function. use the show command to get the available options\n"
|
||||
the available options\n\
|
||||
dump_<mod> debug_<mod > disable or enable the debug file generation or debug code\
|
||||
for \"mod\" module. use the show command to get the available modules\n"
|
||||
|
||||
#define PROCCMD_THREAD_HELP_STRING " thread sub commands: \n\
|
||||
<thread id> aff <core> : set affinity of thread <thread id> to core <core> \n\
|
||||
|
||||
Reference in New Issue
Block a user