log.h 21.7 KB
Newer Older
1 2 3 4 5
/*
 * 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
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * 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
 */
21 22 23 24

/*! \file log.h
* \brief openair log generator (OLG) for
* \author Navid Nikaein
25
* \date 2009 - 2014
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
* \version 0.5
* @ingroup util
*/

#ifndef __LOG_H__
#    define __LOG_H__

/*--- INCLUDES ---------------------------------------------------------------*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdarg.h>
laurent's avatar
laurent committed
44 45
#include <time.h>
#include <stdint.h>
46
#ifndef __STDC_FORMAT_MACROS
laurent's avatar
fixes  
laurent committed
47
  #define __STDC_FORMAT_MACROS
48
#endif
laurent's avatar
laurent committed
49
#include <inttypes.h>
laurent's avatar
laurent committed
50
#ifndef _GNU_SOURCE
laurent's avatar
fixes  
laurent committed
51
  #define _GNU_SOURCE
laurent's avatar
laurent committed
52
#endif
53
#include <pthread.h>
54
#include "T.h"
laurent's avatar
fixes  
laurent committed
55
#include <common/utils/utils.h>
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
/*----------------------------------------------------------------------------*/

#ifdef __cplusplus
extern "C" {
#endif

/** @defgroup _LOG LOG Generator
 * @{*/
/* @}*/

/** @defgroup _macro Macro Definition
 *  @ingroup _LOG
 *  @brief these macros are used in the code of LOG
 * @{*/
/* @}*/

/** @defgroup _max_length Maximum Length of LOG
 *  @ingroup _macro
 *  @brief the macros that describe the maximum length of LOG
 * @{*/
76

77 78 79 80 81 82 83
#define MAX_LOG_TOTAL 1500 /*!< \brief the maximum length of a log */
/* @}*/

/** @defgroup _log_level Message levels defined by LOG
 *  @ingroup _macro
 *  @brief LOG defines 9 levels of messages for users. Importance of these levels decrease gradually from 0 to 8
 * @{*/
84
# define  OAILOG_DISABLE -1 /*!< \brief disable all LOG messages, cannot be used in LOG macros, use only in LOG module */
85
# define  OAILOG_ERR      0 /*!< \brief critical error conditions, impact on "must have" functionalities */
86 87
# 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 */
88 89
# 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*/
90 91

#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)*/
92 93 94
/* @}*/


laurent's avatar
laurent committed
95 96 97 98 99 100 101
/** @defgroup _log_format Defined log format
 *  @ingroup _macro
 *  @brief Macro of log formats defined by LOG
 * @{*/

/* .log_format = 0x13 uncolored standard messages
 * .log_format = 0x93 colored standard messages */
102
/* keep white space in first position; switching it to 0 allows colors to be disabled*/
laurent's avatar
laurent committed
103 104 105 106 107 108 109 110 111 112 113 114 115
#define LOG_RED "\033[1;31m"  /*!< \brief VT100 sequence for bold red foreground */
#define LOG_GREEN "\033[32m"  /*!< \brief VT100 sequence for green foreground */
#define LOG_ORANGE "\033[93m"   /*!< \brief VT100 sequence for orange foreground */
#define LOG_BLUE "\033[34m" /*!< \brief VT100 sequence for blue foreground */
#define LOG_CYBL "\033[40;36m"  /*!< \brief VT100 sequence for cyan foreground on black background */
#define LOG_RESET "\033[0m" /*!< \brief VT100 sequence for reset (black) foreground */
/* @}*/


/** @defgroup _syslog_conf Macros for write in syslog.conf
 *  @ingroup _macro
 *  @brief Macros used to write lines (local/remote) in syslog.conf
 * @{*/
116 117


118 119 120
#define FLAG_NOCOLOR     0x0001  /*!< \brief use colors in log messages, depending on level */
#define FLAG_THREAD      0x0008  /*!< \brief display thread name in log messages */
#define FLAG_LEVEL       0x0010  /*!< \brief display log level in log messages */
121 122
#define FLAG_FUNCT       0x0020
#define FLAG_FILE_LINE   0x0040
123 124
#define FLAG_TIME        0x0100
#define FLAG_INITIALIZED 0x8000
125 126 127 128 129 130

#define SET_LOG_OPTION(O)   g_log->flag = (g_log->flag | O)
#define CLEAR_LOG_OPTION(O) g_log->flag = (g_log->flag & (~O))

/** @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
laurent's avatar
fixes  
laurent committed
131
 *            it allows to dynamically activate or not blocks of code. The  LOG_MASKMAP_INIT macro
132 133 134
 *            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.
laurent's avatar
fixes  
laurent committed
135
 *  @brief
136
 * @{*/
137 138 139
#define DEBUG_PRACH        (1<<0)
#define DEBUG_RU           (1<<1)
#define DEBUG_UE_PHYPROC   (1<<2)
140
#define DEBUG_LTEESTIM     (1<<3)
141 142 143 144 145
#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)
146
#define DEBUG_ASN1         (1<<9)
147
#define DEBUG_CTRLSOCKET   (1<<10)
148 149
#define DEBUG_SECURITY     (1<<11)
#define DEBUG_NAS          (1<<12)
150
#define DEBUG_RLC          (1<<13)
151
#define DEBUG_DLSCH_DECOD  (1<<14)
152
#define UE_TIMING          (1<<20)
153 154


155
#define LOG_MASKMAP_INIT {\
laurent's avatar
fixes  
laurent committed
156 157 158 159 160 161 162 163 164 165 166 167 168
    {"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},\
169
    {"RLC",         DEBUG_RLC},\
170
    {"DLSCH_DECOD", DEBUG_DLSCH_DECOD},\
laurent's avatar
fixes  
laurent committed
171 172 173
    {"UE_TIMING",   UE_TIMING},\
    {NULL,-1}\
  }
174 175 176 177 178 179



#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))

180 181
#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))
182

laurent's avatar
laurent committed
183 184 185


typedef enum {
laurent's avatar
fixes  
laurent committed
186 187 188
  MIN_LOG_COMPONENTS = 0,
  PHY = MIN_LOG_COMPONENTS,
  MAC,
189
  EMU,
laurent's avatar
fixes  
laurent committed
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
  SIM,
  OCG,
  OMG,
  OPT,
  OTG,
  OTG_LATENCY,
  OTG_LATENCY_BG,
  OTG_GP,
  OTG_GP_BG,
  OTG_JITTER,
  RLC,
  PDCP,
  RRC,
  NAS,
  PERF,
  OIP,
206
  CLI,
laurent's avatar
fixes  
laurent committed
207 208 209 210 211 212
  MSC,
  OCM,
  UDP_,
  GTPU,
  SPGW,
  S1AP,
213
  F1AP,
laurent's avatar
fixes  
laurent committed
214 215 216 217 218 219
  SCTP,
  HW,
  OSA,
  RAL_ENB,
  RAL_UE,
  ENB_APP,
220 221
  MCE_APP,
  MME_APP,
laurent's avatar
fixes  
laurent committed
222 223 224 225
  FLEXRAN_AGENT,
  TMR,
  USIM,
  LOCALIZE,
226 227
  PROTO_AGENT,
  F1U,
laurent's avatar
fixes  
laurent committed
228
  X2AP,
229 230
  M2AP,
  M3AP,
zhenghuangkun's avatar
zhenghuangkun committed
231
  NGAP,
232 233 234 235
  GNB_APP,
  NR_RRC,
  NR_MAC,
  NR_PHY,
laurent's avatar
fixes  
laurent committed
236 237
  LOADER,
  ASN,
238 239
  NFAPI_VNF,
  NFAPI_PNF,
laurent's avatar
fixes  
laurent committed
240
  MAX_LOG_PREDEF_COMPONENTS,
laurent's avatar
laurent committed
241 242 243
}
comp_name_t;

244 245
#define MAX_LOG_DYNALLOC_COMPONENTS 20
#define MAX_LOG_COMPONENTS (MAX_LOG_PREDEF_COMPONENTS + MAX_LOG_DYNALLOC_COMPONENTS)
246

laurent's avatar
laurent committed
247 248

typedef struct {
laurent's avatar
fixes  
laurent committed
249 250
  char *name; /*!< \brief string name of item */
  int value;  /*!< \brief integer value of mapping */
laurent's avatar
laurent committed
251 252
} mapping;

253 254
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, ... );
laurent's avatar
laurent committed
255
typedef struct  {
laurent's avatar
fixes  
laurent committed
256 257 258 259 260 261 262 263 264 265 266
  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];
laurent's avatar
laurent committed
267 268 269 270
} log_component_t;


typedef struct {
laurent's avatar
fixes  
laurent committed
271 272 273 274 275 276
  log_component_t         log_component[MAX_LOG_COMPONENTS];
  char                    level2string[NUM_LOG_LEVEL];
  int                     flag;
  char                   *filelog_name;
  uint64_t                debug_mask;
  uint64_t                dump_mask;
laurent's avatar
laurent committed
277 278 279 280
} log_t;



281 282 283 284
#ifdef LOG_MAIN
log_t *g_log;
#else
#ifdef __cplusplus
laurent's avatar
fixes  
laurent committed
285
extern "C" {
286
#endif
laurent's avatar
fixes  
laurent committed
287
  extern log_t *g_log;
288 289 290 291
#ifdef __cplusplus
}
#endif
#endif
laurent's avatar
laurent committed
292 293 294 295
/*--- INCLUDES ---------------------------------------------------------------*/
#    include "log_if.h"
/*----------------------------------------------------------------------------*/
int  logInit (void);
296
int  isLogInitDone (void);
297
void logRecord_mt(const char *file, const char *func, int line,int comp, int level, const char *format, ...) __attribute__ ((format (printf, 6, 7)));
298
void vlogRecord_mt(const char *file, const char *func, int line, int comp, int level, const char *format, va_list args );
laurent's avatar
fixes  
laurent committed
299
void log_dump(int component, void *buffer, int buffsize,int datatype, const char *format, ... );
300
int  set_log(int component, int level);
301 302
void set_glog(int level);

303 304
void set_glog_onlinelog(int enable);
void set_glog_filelog(int enable);
laurent's avatar
laurent committed
305
void set_component_filelog(int comp);
306 307
void close_component_filelog(int comp);
void set_component_consolelog(int comp);
laurent's avatar
laurent committed
308 309 310 311
int  map_str_to_int(mapping *map, const char *str);
char *map_int_to_str(mapping *map, int val);
void logClean (void);
int  is_newline( char *str, int size);
312

313
int register_log_component(char *name, char *fext, int compidx);
314

315 316 317 318 319 320 321 322 323 324 325 326 327
#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);
  
typedef struct {
  char* buf_p;
  int buf_index;
  int enable_flag;
} log_mem_cnt_t;

328 329
/* @}*/

bruno mongazon's avatar
bruno mongazon committed
330 331 332 333 334 335 336 337 338 339 340
/*!\fn int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, char format);
\brief Write output file from signal data
@param fname output file name
@param vname  output vector name (for MATLAB/OCTAVE)
@param data   point to data
@param length length of data vector to output
@param dec    decimation level
@param format data format (0 = real 16-bit, 1 = complex 16-bit,2 real 32-bit, 3 complex 32-bit,4 = real 8-bit, 5 = complex 8-bit)
*/
int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, char format);

341 342 343 344 345 346
/*----------------macro definitions for reading log configuration from the config module */
#define CONFIG_STRING_LOG_PREFIX                           "log_config"

#define LOG_CONFIG_STRING_GLOBAL_LOG_LEVEL                 "global_log_level"
#define LOG_CONFIG_STRING_GLOBAL_LOG_ONLINE                "global_log_online"
#define LOG_CONFIG_STRING_GLOBAL_LOG_INFILE                "global_log_infile"
347
#define LOG_CONFIG_STRING_GLOBAL_LOG_OPTIONS               "global_log_options"
348 349 350

#define LOG_CONFIG_LEVEL_FORMAT                            "%s_log_level"
#define LOG_CONFIG_LOGFILE_FORMAT                          "%s_log_infile"
351
#define LOG_CONFIG_DEBUG_FORMAT                            "%s_debug"
352
#define LOG_CONFIG_DUMP_FORMAT                             "%s_dump"
353 354

#define LOG_CONFIG_HELP_OPTIONS      " list of comma separated options to enable log module behavior. Available options: \n"\
laurent's avatar
fixes  
laurent committed
355 356 357 358 359
  " nocolor:   disable color usage in log messages\n"\
  " level:     add log level indication in log messages\n"\
  " thread:    add threads names in log messages\n"


360

361

362
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
363
/*   LOG global configuration parameters                                                                                                                                                */
364 365
/*   optname                               help                                          paramflags         XXXptr               defXXXval                          type        numelt */
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
366
#define LOG_GLOBALPARAMS_DESC { \
367 368 369
    {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:&(consolelog),         defintval:1,                       TYPE_INT,        0}, \
    {LOG_CONFIG_STRING_GLOBAL_LOG_OPTIONS, LOG_CONFIG_HELP_OPTIONS,                               0, strlistptr:NULL,            defstrlistval:NULL,                TYPE_STRINGLIST, 0} \
laurent's avatar
fixes  
laurent committed
370
  }
371 372

#define LOG_OPTIONS_IDX   2
373 374


375
/*----------------------------------------------------------------------------------*/
376 377 378 379
/** @defgroup _debugging debugging macros
 *  @ingroup _macro
 *  @brief Macro used to call logIt function with different message levels
 * @{*/
380 381 382 383
#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 */
laurent's avatar
fixes  
laurent committed
384
#  if T_TRACER
385
/* per component, level dependent macros */
laurent's avatar
fixes  
laurent committed
386 387 388 389 390
#    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)
391
#    define VLOG(c,l, f, args) do { if (T_stdout) { if( g_log->log_component[c].level >= l  ) vlogRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, l, f, args)   ;} } while (0)
laurent's avatar
fixes  
laurent committed
392
/* macro used to dump a buffer or a message as in openair2/RRC/LTE/RRC_eNB.c, replaces LOG_F macro */
393
#    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)  /* */
394
/* bitmask dependent macros, to isolate debugging code */
395 396
#    define LOG_DEBUGFLAG(D) (g_log->debug_mask & D)

397
/* bitmask dependent macros, to generate debug file such as matlab file or message dump */
398
#    define LOG_DUMPFLAG(D) (g_log->dump_mask & D)
399
#    define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format);} while(0)/* */
laurent's avatar
fixes  
laurent committed
400
/* define variable only used in LOG macro's */
401
#    define LOG_VAR(A,B) A B
402
#  else /* T_TRACER: remove all debugging and tracing messages, except errors */
403

404 405 406 407 408 409 410
#    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_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)

laurent's avatar
fixes  
laurent committed
411
#    define nfapi_log(FILE, FNC, LN, COMP, LVL, FMT...)
412 413 414 415
#    define LOG_DEBUGFLAG(D)  (g_log->dump_mask & D)
#    define LOG_DUMPFLAG(D) (g_log->debug_mask & D)
#    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)  /* */

416
#    define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format);} while(0)
417
#    define LOG_VAR(A,B) A B
418
#  endif /* T_TRACER */
419
/* avoid warnings for variables only used in LOG macro's but set outside debug section */
laurent's avatar
fixes  
laurent committed
420 421
#define GCC_NOTUSED   __attribute__((unused))
#define LOG_USEDINLOG_VAR(A,B) GCC_NOTUSED A B
422

423
/* unfiltered macros, useful for simulators or messages at init time, before log is configured */
424 425
#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)
426
#define LOG_UDUMPMSG(c, b, s, f, x...) do { log_dump(c, b, s, f, x)  ;}   while (0)  /* */
427 428 429 430 431 432 433
/* @}*/


/** @defgroup _useful_functions useful functions in LOG
 *  @ingroup _macro
 *  @brief Macro of some useful functions defined by LOG
 * @{*/
434 435 436 437 438 439
#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 */


440 441
/* @}*/

laurent's avatar
laurent committed
442
static __inline__ uint64_t rdtsc(void) {
Cedric Roux's avatar
Cedric Roux committed
443
  uint32_t a, d;
laurent's avatar
laurent committed
444
  __asm__ volatile ("rdtsc" : "=a" (a), "=d" (d));
Cedric Roux's avatar
Cedric Roux committed
445
  return (((uint64_t)d)<<32) | ((uint64_t)a);
446
}
447

laurent's avatar
laurent committed
448 449
#define DEBUG_REALTIME 1
#if DEBUG_REALTIME
450

laurent's avatar
laurent committed
451
extern double cpuf;
452

453 454 455 456
static inline uint64_t checkTCPU(int timeout,
		                         char *file,
								 int line)
{
457 458
  static uint64_t __thread lastCPUTime=0;
  static uint64_t __thread last=0;
laurent's avatar
fixes  
laurent committed
459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
  uint64_t cur=rdtsc();
  struct timespec CPUt;
  clock_gettime(CLOCK_THREAD_CPUTIME_ID, &CPUt);
  uint64_t CPUTime=CPUt.tv_sec*1000*1000+CPUt.tv_nsec/1000;
  double microCycles=(double)(cpuf*1000);
  int duration=(int)((cur-last)/microCycles);

  if ( last!=0 && duration > timeout ) {
    //struct timespec ts;
    //clock_gettime(CLOCK_MONOTONIC, &ts);
    printf("%s:%d lte-ue delay %d (exceed %d), CPU for this period: %lld\n", file, line,
           duration, timeout, (long long)CPUTime-lastCPUTime );
  }

  last=cur;
  lastCPUTime=CPUTime;
  return cur;
laurent's avatar
laurent committed
476 477
}

478 479 480 481
static inline unsigned long long checkT(int timeout,
		                                char *file,
										int line)
{
482
  static unsigned long long __thread last=0;
laurent's avatar
fixes  
laurent committed
483 484 485 486 487 488 489 490 491 492
  unsigned long long cur=rdtsc();
  int microCycles=(int)(cpuf*1000);
  int duration=(int)((cur-last)/microCycles);

  if ( last!=0 && duration > timeout )
    printf("%s:%d lte-ue delay %d (exceed %d)\n", file, line,
           duration, timeout);

  last=cur;
  return cur;
laurent's avatar
laurent committed
493
}
494

laurent's avatar
laurent committed
495
typedef struct m {
laurent's avatar
fixes  
laurent committed
496 497 498
  uint64_t iterations;
  uint64_t sum;
  uint64_t maxArray[11];
laurent's avatar
laurent committed
499 500
} Meas;

501 502 503 504
static inline void printMeas(char *txt,
		                     Meas *M,
							 int period)
{
laurent's avatar
fixes  
laurent committed
505 506 507 508 509 510 511 512 513
  if (M->iterations%period == 0 ) {
    char txt2[512];
    sprintf(txt2,"%s avg=%" PRIu64 " iterations=%" PRIu64 " max=%"
            PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 "\n",
            txt,
            M->sum/M->iterations,
            M->iterations,
            M->maxArray[1],M->maxArray[2], M->maxArray[3],M->maxArray[4], M->maxArray[5],
            M->maxArray[6],M->maxArray[7], M->maxArray[8],M->maxArray[9],M->maxArray[10]);
514 515
#if T_TRACER
    LOG_W(PHY,"%s",txt2);
Cedric Roux's avatar
Cedric Roux committed
516
#else
517
    printf("%s",txt2);
Cedric Roux's avatar
Cedric Roux committed
518
#endif
laurent's avatar
fixes  
laurent committed
519
  }
laurent's avatar
laurent committed
520
}
521

522 523 524
static inline int cmpint(const void *a,
		                 const void *b)
{
laurent's avatar
fixes  
laurent committed
525 526 527
  uint64_t *aa=(uint64_t *)a;
  uint64_t *bb=(uint64_t *)b;
  return (int)(*aa-*bb);
laurent's avatar
laurent committed
528
}
529

530 531 532 533 534
static inline void updateTimes(uint64_t start,
		                       Meas *M,
							   int period,
							   char *txt)
{
laurent's avatar
fixes  
laurent committed
535 536 537 538 539 540 541 542 543
  if (start!=0) {
    uint64_t end=rdtsc();
    long long diff=(end-start)/(cpuf*1000);
    M->maxArray[0]=diff;
    M->sum+=diff;
    M->iterations++;
    qsort(M->maxArray, 11, sizeof(uint64_t), cmpint);
    printMeas(txt,M,period);
  }
laurent's avatar
laurent committed
544
}
545

laurent's avatar
laurent committed
546 547
#define check(a) do { checkT(a,__FILE__,__LINE__); } while (0)
#define checkcpu(a) do { checkTCPU(a,__FILE__,__LINE__); } while (0)
laurent's avatar
laurent committed
548
#define initRefTimes(a) static __thread Meas a= {0}
laurent's avatar
laurent committed
549
#define pickTime(a) uint64_t a=rdtsc()
laurent's avatar
laurent committed
550
#define readTime(a) a
laurent's avatar
laurent committed
551 552
#define initStaticTime(a) static __thread uint64_t a={0}
#define pickStaticTime(a) do { a=rdtsc(); } while (0)
553

laurent's avatar
laurent committed
554 555
#else
#define check(a) do {} while (0)
laurent's avatar
laurent committed
556
#define checkcpu(a) do {} while (0)
laurent's avatar
laurent committed
557 558 559 560 561 562 563
#define initRefTimes(a) do {} while (0)
#define initStaticTime(a) do {} while (0)
#define pickTime(a) do {} while (0)
#define readTime(a) 0
#define pickStaticTime(a) do {} while (0)
#define updateTimes(a,b,c,d) do {} while (0)
#define printMeas(a,b,c) do {} while (0)
564 565
#endif

566 567 568 569 570
#ifdef __cplusplus
}
#endif

#endif