Merge remote-tracking branch 'origin/develop' into develop-SRS

# Conflicts:
#	ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.usrpn310.conf
#	ci-scripts/conf_files/gnb.band78.sa.fr1.162PRB.2x2.usrpn310.conf
#	openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
#	openair2/RRC/NR/L2_nr_interface.c
This commit is contained in:
rmagueta
2022-01-08 12:11:56 +00:00
371 changed files with 20828 additions and 11134 deletions
+7 -2
View File
@@ -182,8 +182,8 @@ int config_cmdlineonly_get(paramdef_t *cfgoptions,int numoptions, char *prefix )
}
configmodule_interface_t *load_configmodule(int argc,
char **argv,
uint32_t initflags)
char **argv,
uint32_t initflags)
{
char *cfgparam=NULL;
char *modeparams=NULL;
@@ -194,6 +194,11 @@ configmodule_interface_t *load_configmodule(int argc,
int i;
int OoptIdx=-1;
printf("CMDLINE: ");
for (int i=0; i<argc; i++)
printf("\"%s\" ", argv[i]);
printf("\n");
/* first parse the command line to look for the -O option */
for (i = 0; i<argc; i++) {
if (strlen(argv[i]) < 2)
+1 -1
View File
@@ -122,7 +122,7 @@ int config_libconfig_get(paramdef_t *cfgoptions,int numoptions, char *prefix ) {
switch(cfgoptions[i].type) {
case TYPE_STRING:
if ( config_lookup_string(&(libconfig_privdata.cfg),cfgpath, (const char **)&str)) {
if ( config_lookup_string(&(libconfig_privdata.cfg), cfgpath, (const char**)&str)) {
if ( cfgoptions[i].numelt > 0 && str != NULL && strlen(str) >= cfgoptions[i].numelt ) {
fprintf(stderr,"[LIBCONFIG] %s: %s exceeds maximum length of %i bytes, value truncated\n",
cfgpath,str,cfgoptions[i].numelt);
+1 -1
View File
@@ -9,7 +9,7 @@ All logging facility parameters are defined in the log_config section. Some para
|:---:|:---:|:---:|:----|
| `global_log_level` | `pre-defined string of char` | `info` | Allows printing of messages up to the specified level. Available levels, from lower to higher are `error`,`warn`,`info`,`debug`,`trace` |
| `global_log_online` | `boolean` | 1 (=true) | If false, all console messages are discarded, whatever their level |
| `global_log_options` | `list of pre-defined string of char` | | 3 options can be specified to trigger the information added in the header of the message: `nocolor`, disable color usage in log messages, usefull when redirecting logs to a file, where escape sequences used for color selection can be annoying, `level`, add a one letter level id in the message header (T,D,I,W,E for trace, debug, info, warning, error),`thread`, add the thread name in the message header|
| `global_log_options` | `list of pre-defined string of char` | | 3 options can be specified to trigger the information added in the header of the message: `nocolor`, disable color usage in log messages, usefull when redirecting logs to a file, where escape sequences used for color selection can be annoying, `level`, add a one letter level id in the message header (T,D,I,W,E for trace, debug, info, warning, error),`thread`, add the thread name in the message header, `function`, adds the function name, `line_num`, adds the line number, `time` adds the time since process starts|
### Component specific parameters
| name | type | default | description |
+136 -151
View File
@@ -43,6 +43,8 @@
#include <string.h>
#include <linux/prctl.h>
#include "common/config/config_userapi.h"
#include <time.h>
#include <sys/time.h>
// main log variables
@@ -73,6 +75,9 @@ mapping log_options[] = {
{"nocolor", FLAG_NOCOLOR },
{"level", FLAG_LEVEL },
{"thread", FLAG_THREAD },
{"line_num", FLAG_FILE_LINE },
{"function", FLAG_FUNCT},
{"time", FLAG_TIME},
{NULL,-1}
};
@@ -81,6 +86,7 @@ mapping log_maskmap[] = LOG_MASKMAP_INIT;
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 */
static void log_output_memory(log_component_t *c, const char *file, const char *func, int line, int comp, int level, const char* format,va_list args);
int write_file_matlab(const char *fname,
@@ -476,6 +482,8 @@ int logInit (void)
register_log_component("NR_MAC","log",NR_MAC);
register_log_component("NR_PHY","log",NR_PHY);
register_log_component("NGAP","",NGAP);
register_log_component("ITTI","log",ITTI);
register_log_component("UTIL","log",UTIL);
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
@@ -493,84 +501,138 @@ int logInit (void)
return 0;
}
char *log_getthreadname(char *threadname,
int bufsize)
static inline int log_header(log_component_t *c,
char *log_buffer,
int buffsize,
const char *file,
const char *func,
int line,
int level)
{
int rt = pthread_getname_np(pthread_self(), threadname,bufsize) ;
int flag= g_log->flag | c->flag;
if (rt == 0) {
return threadname;
char threadname[64];
if (flag & FLAG_THREAD ) {
threadname[0]='{';
if ( pthread_getname_np(pthread_self(), threadname+1,61) != 0)
strcpy(threadname+1, "?thread?");
strcat(threadname,"}");
} else {
return "thread?";
threadname[0]=0;
}
char l[32];
if (flag & FLAG_FILE_LINE && flag & FLAG_FUNCT )
snprintf(l, sizeof l," (%s:%d) ", func, line);
else if (flag & FLAG_FILE_LINE)
sprintf(l," (%d) ", line);
else
l[0]=0;
char timeString[32];
if ( flag & FLAG_TIME ) {
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
snprintf(timeString, sizeof t,"%05.3f",t.tv_sec+t.tv_nsec/1.0e9);
} else {
timeString[0]=0;
}
return snprintf(log_buffer, buffsize, "%s%s[%s]%c%s %s ",
timeString,
flag & FLAG_NOCOLOR ? "" : log_level_highlight_start[level],
c->name,
flag & FLAG_LEVEL ? g_log->level2string[level] : ' ',
l,
threadname
);
}
static int log_header(char *log_buffer,
int buffsize,
int comp,
int level,
const char *format)
#if LOG_MINIMAL
#include <sys/syscall.h>
void logMinimal(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]);
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
abort();
char buf[MAX_LOG_TOTAL];
int n = snprintf(buf, sizeof(buf), "%lu.%06lu %08lx [%s] %c ",
ts.tv_sec,
ts.tv_nsec / 1000,
syscall(__NR_gettid),
g_log->log_component[comp].name,
level);
if (n < 0 || n >= sizeof(buf))
{
fprintf(stderr, "%s: n=%d\n", __func__, n);
return;
}
va_list args;
va_start(args, format);
int m = vsnprintf(buf + n, sizeof(buf) - n, format, args);
va_end(args);
if (m < 0)
{
fprintf(stderr, "%s: n=%d m=%d\n", __func__, n, m);
return;
}
int len = n + m;
if (len > sizeof(buf) - 1)
{
len = sizeof(buf) - 1;
}
if (buf[len - 1] != '\n')
{
buf[len++] = '\n';
}
__attribute__((unused))
int unused = write(STDOUT_FILENO, buf, len);
}
#endif // LOG_MINIMAL
void logRecord_mt(const char *file,
const char *func,
int line,
int comp,
int level,
const char *format,
... )
const char *func,
int line,
int comp,
int level,
const char *format,
... )
{
char log_buffer[MAX_LOG_TOTAL]= {0};
log_component_t *c = &g_log->log_component[comp];
va_list args;
va_start(args,format);
if (log_mem_flag == 1) {
log_output_memory(file,func,line,comp,level,format,args);
} else {
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);
fflush(g_log->log_component[comp].stream);
}
log_output_memory(c, file,func,line,comp,level,format,args);
va_end(args);
}
void vlogRecord_mt(const char *file,
const char *func,
int line,
int comp,
int level,
const char *format,
va_list args )
const char *func,
int line,
int comp,
int level,
const char *format,
va_list args )
{
char log_buffer[MAX_LOG_TOTAL];
if (log_mem_flag == 1) {
log_output_memory(file,func,line,comp,level, format,args);
} else {
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);
}
log_component_t *c = &g_log->log_component[comp];
log_output_memory(c, file,func,line,comp,level, format,args);
}
void log_dump(int component,
void *buffer,
int buffsize,
int datatype,
const char *format,
... )
void *buffer,
int buffsize,
int datatype,
const char *format,
... )
{
va_list args;
char *wbuf;
log_component_t *c = &g_log->log_component[component];
int flag= g_log->flag | c->flag;
switch(datatype) {
case LOG_DUMP_DOUBLE:
wbuf=malloc((buffsize * 10) + 64 + MAX_LOG_TOTAL);
@@ -584,9 +646,8 @@ void log_dump(int component,
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;
int pos=log_header(c, wbuf,MAX_LOG_TOTAL,"noFile","noFunc",0, OAILOG_INFO);
pos+=vsprintf(wbuf+pos,format, args);
va_end(args);
for (int i=0; i<buffsize; i++) {
@@ -601,9 +662,11 @@ void log_dump(int component,
break;
}
}
sprintf(wbuf+pos,"\n");
g_log->log_component[component].print(g_log->log_component[component].stream,wbuf);
if ( flag & FLAG_NOCOLOR )
sprintf(wbuf+pos,"\n");
else
sprintf(wbuf+pos,"%s\n",log_level_highlight_end[OAILOG_INFO]);
c->print(c->stream,wbuf);
free(wbuf);
}
}
@@ -803,13 +866,10 @@ void flush_mem_to_file(void)
char logmem_log_level[NUM_LOG_LEVEL]={'E','W','I','D','T'};
void log_output_memory(const char *file, const char *func, int line, int comp, int level, const char* format,va_list args)
static void log_output_memory(log_component_t *c, const char *file, const char *func, int line, int comp, int level, const char* format,va_list args)
{
//logRecord_mt(file,func,line, pthread_self(), comp, level, format, ##args)
int len = 0;
log_component_t *c;
char *log_start;
char *log_end;
/* The main difference with the version above is the use of this local log_buffer.
* The other difference is the return value of snprintf which was not used
* correctly. It was not a big problem because in practice MAX_LOG_TOTAL is
@@ -817,92 +877,17 @@ void log_output_memory(const char *file, const char *func, int line, int comp, i
*/
char log_buffer[MAX_LOG_TOTAL];
/* for no gcc warnings */
(void)log_start;
(void)log_end;
c = &g_log->log_component[comp];
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LOG_RECORD, VCD_FUNCTION_IN);
// make sure that for log trace the extra info is only printed once, reset when the level changes
if (level == OAILOG_TRACE) {
log_start = log_buffer;
len = vsnprintf(log_buffer, MAX_LOG_TOTAL, format, args);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
log_end = log_buffer + len;
} else {
if ( (g_log->flag & 0x001) || (c->flag & 0x001) ) {
len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "%s",
log_level_highlight_start[level]);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
}
log_start = log_buffer + len;
// if ( (g_log->flag & 0x004) || (c->flag & 0x004) ) {
len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%s]",
g_log->log_component[comp].name);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
// }
if ( (level >= OAILOG_ERR) && (level <= OAILOG_TRACE) ) {
len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%c]",
logmem_log_level[level]);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
}
if ( (g_log->flag & FLAG_THREAD) || (c->flag & FLAG_THREAD) ) {
# define THREAD_NAME_LEN 128
char threadname[THREAD_NAME_LEN];
if (pthread_getname_np(pthread_self(), threadname, THREAD_NAME_LEN) != 0)
{
perror("pthread_getname_np : ");
} else {
len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%s]", threadname);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
}
# undef THREAD_NAME_LEN
}
if ( (g_log->flag & FLAG_FUNCT) || (c->flag & FLAG_FUNCT) ) {
len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%s] ",
func);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
}
if ( (g_log->flag & FLAG_FILE_LINE) || (c->flag & FLAG_FILE_LINE) ) {
len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%s:%d]",
file, line);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
}
/* len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%08lx]", thread_id);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
struct timeval gettime;
gettimeofday(&gettime,NULL);
len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%ld.%06ld]", gettime.tv_sec, gettime.tv_usec);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
*/
if ( (g_log->flag & FLAG_NOCOLOR) || (c->flag & FLAG_NOCOLOR) ) {
len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "%s",
log_level_highlight_end[level]);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
}
len += vsnprintf(&log_buffer[len], MAX_LOG_TOTAL - len, format, args);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
log_end = log_buffer + len;
}
//va_end(args);
if (level < OAILOG_TRACE)
len += log_header(c, log_buffer, MAX_LOG_TOTAL, file, func, line, level);
len += vsnprintf(log_buffer+len, MAX_LOG_TOTAL-len, format, args);
if ( !((g_log->flag | c->flag) & FLAG_NOCOLOR) )
len+=snprintf(log_buffer+len, MAX_LOG_TOTAL-len, "%s", log_level_highlight_end[level]);
// OAI printf compatibility
if(log_mem_flag==1){
if(log_mem_d[log_mem_side].enable_flag==1){
int temp_index;
if(log_mem_flag==1){
if(log_mem_d[log_mem_side].enable_flag==1){
int temp_index;
temp_index=log_mem_d[log_mem_side].buf_index;
if(temp_index+len+1 < LOG_MEM_SIZE){
log_mem_d[log_mem_side].buf_index+=len;
@@ -933,9 +918,9 @@ void log_output_memory(const char *file, const char *func, int line, int comp, i
}
}
}
}else{
fwrite(log_buffer, len, 1, stdout);
}
}else{
if (write(fileno(c->stream), log_buffer, len)) {};
}
}
int logInit_log_mem (void)
+31 -1
View File
@@ -54,6 +54,12 @@
#include "T.h"
#include <common/utils/utils.h>
/*----------------------------------------------------------------------------*/
#include <assert.h>
#ifdef NDEBUG
#warning assert is disabled
#endif
#define NUM_ELEMENTS(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0]))
#define CHECK_INDEX(ARRAY, INDEX) assert((INDEX) < NUM_ELEMENTS(ARRAY))
#ifdef __cplusplus
extern "C" {
@@ -237,6 +243,8 @@ typedef enum {
ASN,
NFAPI_VNF,
NFAPI_PNF,
ITTI,
UTIL,
MAX_LOG_PREDEF_COMPONENTS,
}
comp_name_t;
@@ -315,7 +323,6 @@ int register_log_component(char *name, char *fext, int compidx);
#define LOG_MEM_SIZE 100*1024*1024
#define LOG_MEM_FILE "./logmem.log"
void flush_mem_to_file(void);
void log_output_memory(const char *file, const char *func, int line, int comp, int level, const char* format,va_list args);
int logInit_log_mem(void);
void close_log_mem(void);
@@ -400,10 +407,30 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int
#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 LOG_MINIMAL
void logMinimal(int component, int level, const char *format, ...) __attribute__((format(printf, 3, 4)));
# define LOG_E(COMPONENT, ...) do if (1) logMinimal(COMPONENT, 'E', __VA_ARGS__); while (0)
# define LOG_W(COMPONENT, ...) do if (1) logMinimal(COMPONENT, 'W', __VA_ARGS__); while (0)
# define LOG_A(COMPONENT, ...) do if (1) logMinimal(COMPONENT, 'A', __VA_ARGS__); while (0) /* logs intended for analysis */
# define LOG_I(COMPONENT, ...) do if (1) logMinimal(COMPONENT, 'I', __VA_ARGS__); while (0)
# define LOG_D(COMPONENT, ...) do if (0) logMinimal(COMPONENT, 'D', __VA_ARGS__); while (0)
# define LOG_T(COMPONENT, ...) do if (0) logMinimal(COMPONENT, 'T', __VA_ARGS__); while (0)
# define LOG_M(FILE, VECTOR, DATA, LEN, DEC, FORMAT) ((void) 0)
# define LOG_DUMPFLAG(D) 0
# define LOG_DEBUGFLAG(D) 0
# define LOG_DUMPMSG(C, B, S, X...) ((void) 0)
# define VLOG(C, L, F, ARGS) ((void) 0)
#else // LOG_MINIMAL
# if T_TRACER
/* per component, level dependent macros */
# 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_A LOG_I
# 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)
@@ -423,6 +450,7 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int
# define LOG_E(c, x...) do { if( g_log->log_component[c].level >= OAILOG_ERR ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_ERR, x) ;} while (0)
# define LOG_W(c, x...) do { if( g_log->log_component[c].level >= OAILOG_WARNING) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_WARNING, x) ;} while (0)
# define LOG_I(c, x...) do { if( g_log->log_component[c].level >= OAILOG_INFO ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_INFO, x) ;} while (0)
# define LOG_A LOG_I
# define LOG_D(c, x...) do { if( g_log->log_component[c].level >= OAILOG_DEBUG ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_DEBUG, x) ;} while (0)
# define LOG_T(c, x...) do { if( g_log->log_component[c].level >= OAILOG_TRACE ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_TRACE, x) ;} while (0)
# define VLOG(c,l, f, args) do { if( g_log->log_component[c].level >= l ) vlogRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, l, f, args) ; } while (0)
@@ -436,6 +464,8 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int
# define LOG_VAR(A,B) A B
# define T_ACTIVE(a) (0)
# endif /* T_TRACER */
#endif // LOG_MINIMAL
/* avoid warnings for variables only used in LOG macro's but set outside debug section */
#define GCC_NOTUSED __attribute__((unused))
#define LOG_USEDINLOG_VAR(A,B) GCC_NOTUSED A B
+42
View File
@@ -1069,6 +1069,48 @@ ID = LEGACY_NFAPI_PNF_TRACE
DESC = NFAPI_PNF legacy logs - trace level
GROUP = ALL:LEGACY_NFAPI_PNF:LEGACY_GROUP_TRACE:LEGACY
FORMAT = string,log
ID = LEGACY_ITTI_INFO
DESC = ITTI legacy logs - info level
GROUP = ALL:LEGACY_ITTI:LEGACY_GROUP_INFO:LEGACY
FORMAT = string,log
ID = LEGACY_ITTI_ERROR
DESC = ITTI legacy logs - error level
GROUP = ALL:LEGACY_ITTI:LEGACY_GROUP_ERROR:LEGACY
FORMAT = string,log
ID = LEGACY_ITTI_WARNING
DESC = ITTI legacy logs - warning level
GROUP = ALL:LEGACY_ITTI:LEGACY_GROUP_WARNING:LEGACY
FORMAT = string,log
ID = LEGACY_ITTI_DEBUG
DESC = ITTI legacy logs - debug level
GROUP = ALL:LEGACY_ITTI:LEGACY_GROUP_DEBUG:LEGACY
FORMAT = string,log
ID = LEGACY_ITTI_TRACE
DESC = ITTI legacy logs - trace level
GROUP = ALL:LEGACY_ITTI:LEGACY_GROUP_TRACE:LEGACY
FORMAT = string,log
ID = LEGACY_UTIL_INFO
DESC = UTIL legacy logs - info level
GROUP = ALL:LEGACY_UTIL:LEGACY_GROUP_INFO:LEGACY
FORMAT = string,log
ID = LEGACY_UTIL_ERROR
DESC = UTIL legacy logs - error level
GROUP = ALL:LEGACY_UTIL:LEGACY_GROUP_ERROR:LEGACY
FORMAT = string,log
ID = LEGACY_UTIL_WARNING
DESC = UTIL legacy logs - warning level
GROUP = ALL:LEGACY_UTIL:LEGACY_GROUP_WARNING:LEGACY
FORMAT = string,log
ID = LEGACY_UTIL_DEBUG
DESC = UTIL legacy logs - debug level
GROUP = ALL:LEGACY_UTIL:LEGACY_GROUP_DEBUG:LEGACY
FORMAT = string,log
ID = LEGACY_UTIL_TRACE
DESC = UTIL legacy logs - trace level
GROUP = ALL:LEGACY_UTIL:LEGACY_GROUP_TRACE:LEGACY
FORMAT = string,log
# this is a bad hack but I won't fix (function util_print_hex_octets
# in openairinterface5g/openair2/LAYER2/PDCP_v10.1.0/pdcp_util.c
# does funky things with the LOG_x macros but we work on the C pre-processor
+1 -8
View File
@@ -26,17 +26,10 @@
#include <stdlib.h>
#include <inttypes.h>
#include <platform_types.h>
#include "backtrace.h"
#if defined(ENB_MODE)
# define display_backtrace()
#else
# include "backtrace.h"
#endif
void output_log_mem(void);
#define _Assert_Exit_ \
fprintf(stderr, "\nExiting execution\n"); \
display_backtrace(); \
fflush(stdout); \
fflush(stderr); \
abort();
+1 -6
View File
@@ -28,7 +28,7 @@
#include <signal.h>
#include <execinfo.h>
#include "backtrace.h"
#include <common/utils/backtrace.h>
/* Obtain a backtrace and print it to stdout. */
void display_backtrace(void) {
@@ -49,8 +49,3 @@ void display_backtrace(void) {
free(strings);
}
void backtrace_handle_signal(siginfo_t *info) {
display_backtrace();
//exit(EXIT_FAILURE);
}
-3
View File
@@ -26,10 +26,7 @@
#ifdef __cplusplus
extern "C" {
#endif
void display_backtrace(void);
void backtrace_handle_signal(siginfo_t *info);
#ifdef __cplusplus
}
#endif
+14 -20
View File
@@ -42,7 +42,7 @@ const char *duplex_mode[]={"FDD","TDD"};
// - N_OFFs for bands from 80 to 89 and band 95 is referred to UL
// - Frequencies are expressed in KHz
// - col: NR_band ul_min ul_max dl_min dl_max step N_OFFs_DL deltaf_raster
nr_bandentry_t nr_bandtable[] = {
const nr_bandentry_t nr_bandtable[] = {
{1, 1920000, 1980000, 2110000, 2170000, 20, 422000, 100},
{2, 1850000, 1910000, 1930000, 1990000, 20, 386000, 100},
{3, 1710000, 1785000, 1805000, 1880000, 20, 361000, 100},
@@ -117,7 +117,7 @@ uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex)
uint64_t center_freq_diff_khz = 999999999999999999; // 2^64
uint16_t current_band = 0;
for (int ind = 0; ind < nr_bandtable_size; ind++) {
for (int ind = 0; ind < sizeofArray(nr_bandtable); ind++) {
if (dl_freq_khz < nr_bandtable[ind].dl_min || dl_freq_khz > nr_bandtable[ind].dl_max)
continue;
@@ -143,8 +143,6 @@ uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex)
return current_band;
}
const size_t nr_bandtable_size = sizeof(nr_bandtable) / sizeof(nr_bandentry_t);
int NRRIV2BW(int locationAndBandwidth,int N_RB) {
int tmp = locationAndBandwidth/N_RB;
int tmp2 = locationAndBandwidth%N_RB;
@@ -459,31 +457,27 @@ uint16_t config_bandwidth(int mu, int nb_rb, int nr_band)
// Returns the corresponding row index of the NR table
int get_nr_table_idx(int nr_bandP, uint8_t scs_index) {
int i, j;
int scs_khz = 15 << scs_index;
int supplementary_bands[] = {29,75,76,80,81,82,83,84,86,89,95};
size_t s = sizeof(supplementary_bands)/sizeof(supplementary_bands[0]);
for(j = 0; j < s; j++){
for(int j = 0; j < sizeofArray(supplementary_bands); j++){
if (nr_bandP == supplementary_bands[j])
AssertFatal(0 == 1, "Band %d is a supplementary band (%d). This is not supported yet.\n", nr_bandP, supplementary_bands[j]);
}
AssertFatal(nr_bandP <= nr_bandtable[nr_bandtable_size-1].band, "NR band %d exceeds NR bands table maximum limit %d\n", nr_bandP, nr_bandtable[nr_bandtable_size-1].band);
for (i = 0; i < nr_bandtable_size && nr_bandtable[i].band != nr_bandP; i++);
// In frequency bands with two deltaFRaster,
// the higher deltaFRaster applies to channels using only the SCS that is equal to or larger than the higher deltaFRaster
// and SSB SCS is equal to the higher deltaFRaster.
while(((i+1)<nr_bandtable_size) &&
(nr_bandtable[i+1].band == nr_bandtable[i].band) &&
(nr_bandtable[i].deltaf_raster != scs_khz)) {
i++;
int i;
for (i = 0; i < sizeofArray(nr_bandtable); i++) {
if ( nr_bandtable[i].band == nr_bandP && nr_bandtable[i].deltaf_raster == scs_khz )
break;
}
AssertFatal(nr_bandtable[i].band == nr_bandP, "Found band table %d does not correspond to the input one %d\n",nr_bandtable[i].band,nr_bandP);
if (i == sizeofArray(nr_bandtable)) {
LOG_I(PHY, "not found same deltaf_raster == scs_khz, use only band and last deltaf_raster \n");
for(i=sizeofArray(nr_bandtable)-1; i >=0; i--)
if ( nr_bandtable[i].band == nr_bandP )
break;
}
AssertFatal(i > 0 && i < sizeofArray(nr_bandtable), "band is not existing: %d\n",nr_bandP);
LOG_D(PHY, "NR band table index %d (Band %d, dl_min %lu, ul_min %lu)\n", i, nr_bandtable[i].band, nr_bandtable[i].dl_min,nr_bandtable[i].ul_min);
return i;
+1 -2
View File
@@ -48,8 +48,7 @@ typedef struct nr_bandentry_s {
uint8_t deltaf_raster;
} nr_bandentry_t;
extern const size_t nr_bandtable_size;
extern nr_bandentry_t nr_bandtable[];
extern const nr_bandentry_t nr_bandtable[];
static inline int get_num_dmrs(uint16_t dmrs_mask ) {
int num_dmrs=0;
+66 -15
View File
@@ -136,12 +136,12 @@ extern "C" {
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 (last message %s)\n",itti_get_task_name(destination_task_id), s+1,ITTI_MSG_NAME(message));
LOG_I(ITTI,"Queue for %s task size: %ld (last message %s)\n",itti_get_task_name(destination_task_id), s+1,ITTI_MSG_NAME(message));
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);
LOG_D(ITTI,"sent messages id=%d to %s\n",message_id, t->admin.name);
return 0;
}
@@ -152,7 +152,7 @@ extern "C" {
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());
LOG_W(ITTI,"queue in no thread mode is %ld\n", t->message_queue.size());
pthread_mutex_unlock (&t->queue_cond_lock);
t->admin.func(NULL);
@@ -208,7 +208,7 @@ extern "C" {
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);
LOG_W(ITTI,"Failed to send msg TIMER_HAS_EXPIRED to task %u\n", task_id);
free(message);
t->timer_map.erase(it);
return -1;
@@ -233,7 +233,7 @@ extern "C" {
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));
LOG_D(ITTI,"enter blocking wait for %s, timeout: %d ms\n", itti_get_task_name(task_id), epoll_timeout);
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 ) )
@@ -243,7 +243,7 @@ extern "C" {
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));
LOG_D(ITTI,"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 */
@@ -292,11 +292,11 @@ extern "C" {
// 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);
LOG_D(ITTI,"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);
LOG_D(ITTI,"task %s received a message\n",t->admin.name);
}
pthread_mutex_unlock (&t->queue_cond_lock);
@@ -308,7 +308,7 @@ extern "C" {
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);
LOG_D(ITTI,"task %s received a message in polling mode\n",t->admin.name);
*received_msg=t->message_queue.back();
t->message_queue.pop_back();
} else
@@ -322,7 +322,7 @@ extern "C" {
void *args_p) {
task_list_t *t=tasks[task_id];
threadCreate (&t->thread, start_routine, args_p, (char *)itti_get_task_name(task_id),-1,OAI_PRIORITY_RT);
LOG_I(TMR,"Created Posix thread %s\n", itti_get_task_name(task_id) );
LOG_I(ITTI,"Created Posix thread %s\n", itti_get_task_name(task_id) );
return 0;
}
@@ -344,7 +344,7 @@ extern "C" {
tasks = new_tasks;
tasks[newQueue]= new task_list_t;
pthread_mutex_unlock (&lock_nb_queues);
LOG_I(TMR,"Starting itti queue: %s as task %d\n", taskInfo->name, newQueue);
LOG_I(ITTI,"Starting itti queue: %s as task %d\n", taskInfo->name, newQueue);
pthread_mutex_init(&tasks[newQueue]->queue_cond_lock, NULL);
memcpy(&tasks[newQueue]->admin, taskInfo, sizeof(task_info_t));
AssertFatal( ( tasks[newQueue]->epoll_fd = epoll_create1(0) ) >=0, "");
@@ -392,7 +392,7 @@ extern "C" {
clock_gettime(CLOCK_MONOTONIC, &tp);
if (interval_us%1000 != 0)
LOG_W(TMR, "Can't set timer precision below 1ms, rounding it\n");
LOG_W(ITTI, "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);
@@ -421,7 +421,7 @@ extern "C" {
if (ret==1)
return 0;
else {
LOG_W(TMR, "tried to remove a non existing timer\n");
LOG_W(ITTI, "tried to remove a non existing timer\n");
return 1;
}
}
@@ -438,9 +438,22 @@ extern "C" {
void itti_send_terminate_message(task_id_t task_id) {
}
static volatile bool shutting_down;
static void catch_sigterm(int) {
static const char msg[] = "\n** Caught SIGTERM, shutting down\n";
__attribute__((unused))
int unused = write(STDOUT_FILENO, msg, sizeof(msg) - 1);
shutting_down = true;
}
void itti_wait_tasks_end(void) {
while(1)
sleep(24*3600);
shutting_down = false;
signal(SIGTERM, catch_sigterm);
while (! shutting_down)
{
sleep(24 * 3600);
}
}
void itti_update_lte_time(uint32_t frame, uint8_t slot) {}
@@ -455,4 +468,42 @@ extern "C" {
int signal_mask(void) {
return 0;
}
void log_scheduler(const char* label)
{
int policy = sched_getscheduler(0);
struct sched_param param;
if (sched_getparam(0, &param) == -1)
{
LOG_E(HW, "sched_getparam: %s\n", strerror(errno));
abort();
}
cpu_set_t cpu_set;
if (sched_getaffinity(0, sizeof(cpu_set), &cpu_set) == -1)
{
LOG_E(HW, "sched_getaffinity: %s\n", strerror(errno));
abort();
}
int num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
if (num_cpus < 1)
{
LOG_E(HW, "sysconf(_SC_NPROCESSORS_ONLN): %s\n", strerror(errno));
abort();
}
char buffer[num_cpus];
for (int i = 0; i < num_cpus; i++)
{
buffer[i] = CPU_ISSET(i, &cpu_set) ? 'Y' : '-';
}
LOG_A(HW, "Scheduler policy=%d priority=%d affinity=[%d]%.*s label=%s\n",
policy,
param.sched_priority,
num_cpus,
num_cpus,
buffer,
label);
}
} // extern "C"
@@ -346,6 +346,8 @@ void *rrc_enb_process_msg(void *);
TASK_DEF(TASK_DU_F1, TASK_PRIORITY_MED, 200, NULL, NULL) \
TASK_DEF(TASK_RRC_UE_SIM, TASK_PRIORITY_MED, 200, NULL, NULL) \
TASK_DEF(TASK_RRC_GNB_SIM, TASK_PRIORITY_MED, 200, NULL, NULL) \
TASK_DEF(TASK_RRC_NSA_UE, TASK_PRIORITY_MED, 200, NULL, NULL) \
TASK_DEF(TASK_RRC_NSA_NRUE, TASK_PRIORITY_MED, 200, NULL, NULL) \
TASK_DEF(TASK_NAS_NRUE, TASK_PRIORITY_MED, 200, NULL, NULL) \
TASK_DEF(TASK_MAX, TASK_PRIORITY_MED, 200, NULL, NULL)
@@ -362,6 +364,8 @@ typedef enum {
FOREACH_TASK(TASK_ENUM)
} task_id_t;
extern uint16_t ue_idx_standalone;
extern uint16_t node_number;
typedef task_id_t thread_id_t;
@@ -586,6 +590,7 @@ int timer_remove(long timer_id);
int signal_handle(int *end);
int signal_mask(void);
void log_scheduler(const char *label);
#ifdef __cplusplus
}
#endif
+91
View File
@@ -0,0 +1,91 @@
# interthread interface (ITTI)
A Middleware called “itti” (interthread interface) provides classical send/receive message queues between threads.
A simpler thread safe message queue is available in the thread-pool, as it is a required lower level feature.
ITTI is providing more feature, to be used as the thread event main loop.
It is also made for strong type definition is source code.
It is able to add in the managed events: external sockets, timers
All queues are created in .h files, as static permanent queues, nevertheless the possibility to add queues during runtime is available.
The queues are called tasks because it is often read in a single thread that have the same name.
# API definition
## itti_send_msg_to_task, itti_receive_msg, itti_poll_msg
Standard messages queues, thread safe
The reader is responsible of freeing the message
## itti_subscribe_event_fd, itti_get_events
Add external sockets to itti based main loop
## timer_setup timer_remove
When a timer expire, it adds a message in a itti queue
## itti_terminate_tasks
Calling this function push a “terminate” message on each itti queue
# Example code of a thread using ITTI
```
Thread_aLayer_main(void * context) {
// initialize the layer data
// and register in itti the external sockets (like S1AP, GTP)
aLayer_init();
while (1) {
MessageDef * msg
itti_receive_msg(TASK_aLayer, &msg);
// itti receive released, so we have incoming data
// Can be a itti message
if ( msg != NULL) {
switch(ITTI_MSG_ID(msg)) {
case …:
processThisMsgType1(msg);
break;
case …:
processThisMsgType2(msg);
break;
}
Itti_free(msg);
}
// or data/event on external entries (sockets)
Struct eppol_events* events;
int nbEvents=itti_get_events(TASK_aLayer, &events);
if ( nbEvents > 0)
processLayerEvents(events, nbEvents);
}
}
```
# Current usage in OpenAir
## UDP, SCTP
Simple threads that interface itti internal messages to Linux
## GTPV1-U, S1AP
Threads to implement S1AP and GTP protocols
## PDCP
4G Pdcp is not following itti design pattern, but it uses itti internally , 5G PDCP uses ad hoc design
## RRC
Implements 3GPP Rrc features
Interfaces the layer 1 and the above itti tasks
## X2, ENP_APP (configuration), L1L2
Are declared itti queues with a dedicated thread, but they are almost empty
+17 -54
View File
@@ -95,53 +95,16 @@ static void read_pipe(int p, char *b, int size) {
size -= ret;
}
}
static int baseRunTimeCommand(char* cmd, size_t cmdSize) {
FILE *fp;
size_t retSize = 0;
fp = popen(cmd, "r");
if(fp) {
memset(cmd, 0, cmdSize);
retSize = fread(cmd, 1, cmdSize, fp);
fclose(fp);
} else {
LOG_D(HW,"%s:%d:%s: Cannot open %s\n", __FILE__, __LINE__, __FUNCTION__, cmd);
}
if (retSize == 0) {
return 0;
}
return atoi(cmd);
}
int checkIfFedoraDistribution(void) {
char cmd[200];
memset(cmd, 0, 200);
sprintf(cmd, "cat /etc/os-release | grep ID_LIKE | grep -ic fedora || true");
return baseRunTimeCommand(cmd, 200);
return !system("grep -iq 'ID_LIKE.*fedora' /etc/os-release ");
}
int checkIfGenericKernelOnFedora(void) {
char cmd[200];
memset(cmd, 0, 200);
sprintf(cmd, "uname -a | grep -c rt || true");
return (1 - baseRunTimeCommand(cmd, 200));
return system("uname -a | grep -q rt");
}
int checkIfInsideContainer(void) {
char cmd[200];
int res = 0;
memset(cmd, 0, 200);
sprintf(cmd, "cat /proc/self/cgroup | egrep -c 'libpod|podman|kubepods' || true");
res = baseRunTimeCommand(cmd, 200);
if (res > 0)
return 1;
else
return 0;
return !system("egrep -q 'libpod|podman|kubepods' /proc/self/cgroup");
}
/********************************************************************/
@@ -257,21 +220,21 @@ void threadCreate(pthread_t* t, void * (*func)(void*), void * param, char* name,
AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno);
ret=pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno);
ret=pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno);
if (checkIfFedoraDistribution())
if (checkIfGenericKernelOnFedora())
if (checkIfInsideContainer())
settingPriority = 0;
if (system("grep -iq 'ID_LIKE.*fedora' /etc/os-release && uname -a | grep -c rt")==0)
if (system("cat /proc/self/cgroup | egrep -c 'libpod|podman|kubepods'")==0)
settingPriority = 0;
if (settingPriority) {
ret=pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno);
ret=pthread_attr_setschedpolicy(&attr, SCHED_OAI);
AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno);
if(priority<sched_get_priority_min(SCHED_OAI) || priority>sched_get_priority_max(SCHED_FIFO)) {
LOG_E(TMR,"Prio not possible: %d, min is %d, max: %d, forced in the range\n",
priority,
sched_get_priority_min(SCHED_OAI),
sched_get_priority_max(SCHED_OAI));
if(priority<sched_get_priority_min(SCHED_OAI) || priority>sched_get_priority_max(SCHED_OAI)) {
LOG_E(UTIL,"Prio not possible: %d, min is %d, max: %d, forced in the range\n",
priority,
sched_get_priority_min(SCHED_OAI),
sched_get_priority_max(SCHED_OAI));
if(priority<sched_get_priority_min(SCHED_OAI))
priority=sched_get_priority_min(SCHED_OAI);
if(priority>sched_get_priority_max(SCHED_OAI))
@@ -283,10 +246,10 @@ void threadCreate(pthread_t* t, void * (*func)(void*), void * param, char* name,
ret=pthread_attr_setschedparam(&attr, &sparam);
AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno);
}
ret=pthread_create(t, &attr, func, param);
AssertFatal(ret==0,"ret: %d, errno: %d\n",ret, errno);
pthread_setname_np(*t, name);
if (affinity != -1 ) {
cpu_set_t cpuset;
+1 -1
View File
@@ -142,7 +142,7 @@ static inline notifiedFIFO_elt_t *pullNotifiedFIFO_nothreadSafe(notifiedFIFO_t
notifiedFIFO_elt_t *ret=nf->outF;
if (nf->outF==nf->outF->next)
LOG_E(TMR,"Circular list in thread pool: push several times the same buffer is forbidden\n");
LOG_E(UTIL,"Circular list in thread pool: push several times the same buffer is forbidden\n");
nf->outF=nf->outF->next;
+43
View File
@@ -2,6 +2,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sched.h>
#include <errno.h>
#include "utils.h"
void *calloc_or_fail(size_t size) {
@@ -22,6 +25,32 @@ void *malloc_or_fail(size_t size) {
return ptr;
}
const char *hexdump(const void *data, size_t data_len, char *out, size_t out_len)
{
char *p = out;
char *endp = out + out_len;
const uint8_t *q = data;
snprintf(p, endp - p, "[%zu]", data_len);
p += strlen(p);
for (size_t i = 0; i < data_len; ++i)
{
if (p >= endp)
{
static const char ellipses[] = "...";
char *s = endp - sizeof(ellipses);
if (s >= p)
{
strcpy(s, ellipses);
}
break;
}
snprintf(p, endp - p, " %02X", *q++);
p += strlen(p);
}
return out;
}
/****************************************************************************
** **
** Name: hex_char_to_hex_value() **
@@ -111,3 +140,17 @@ void *memcpy1(void *dst,const void *src,size_t n) {
asm volatile("rep movsb" : "+D" (dst) : "c"(n), "S"(src) : "cc","memory");
return(ret);
}
void set_priority(int priority)
{
struct sched_param param =
{
.sched_priority = priority,
};
fprintf(stderr, "Calling sched_setscheduler(%d)\n", priority);
if (sched_setscheduler(0, SCHED_RR, &param) == -1)
{
fprintf(stderr, "sched_setscheduler: %s\n", strerror(errno));
abort();
}
}
+2
View File
@@ -10,6 +10,7 @@ extern "C" {
#define sizeofArray(a) (sizeof(a)/sizeof(*(a)))
void *calloc_or_fail(size_t size);
void *malloc_or_fail(size_t size);
const char *hexdump(const void *data, size_t data_len, char *out, size_t out_len);
// Converts an hexadecimal ASCII coded digit into its value. **
int hex_char_to_hex_value (char c);
@@ -18,6 +19,7 @@ int hex_string_to_hex_value (uint8_t *hex_value, const char *hex_string, int siz
void *memcpy1(void *dst,const void *src,size_t n);
void set_priority(int priority);
char *itoa(int i);