Merge commit 'develop' into feature-127-protocol-split

* remove a lot of white spaces
* many conflicts in enb_config.c
This commit is contained in:
Robert Schmidt
2018-11-07 16:07:59 +01:00
246 changed files with 16448 additions and 9003 deletions
+7 -19
View File
@@ -35,6 +35,7 @@
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <platform_types.h>
#include "config_userapi.h"
@@ -141,25 +142,16 @@ char defbool[2]="1";
int config_process_cmdline(paramdef_t *cfgoptions,int numoptions, char *prefix)
{
int c = config_get_if()->argc;
int i,j;
char *pp;
char *cfgpath;
int c = config_get_if()->argc;
int i,j;
char *pp;
char cfgpath[512]; /* 512 should be enough for the sprintf below */
j = (prefix ==NULL) ? 0 : strlen(prefix);
cfgpath = malloc( j + MAX_OPTNAME_SIZE +1);
if (cfgpath == NULL) {
fprintf(stderr,"[CONFIG] %s %i malloc error, %s\n", __FILE__, __LINE__,strerror(errno));
return -1;
}
j = 0;
i = 0;
while (c > 0 ) {
char *oneargv = strdup(config_get_if()->argv[i]); /* we use strtok_r which modifies its string paramater, and we don't want argv to be modified */
/* first check help options, either --help, -h or --help_<section> */
/* first check help options, either --help, -h or --help_<section> */
if (strncmp(oneargv, "-h",2) == 0 || strncmp(oneargv, "--help",6) == 0 ) {
char *tokctx;
pp=strtok_r(oneargv, "_",&tokctx);
@@ -182,7 +174,7 @@ char *cfgpath;
}
}
/* now, check for non help options */
/* now, check for non help options */
if (oneargv[0] == '-') {
for(int n=0;n<numoptions;n++) {
if ( ( cfgoptions[n].paramflags & PARAMFLAG_DISABLECMDLINE) != 0) {
@@ -223,9 +215,5 @@ char *cfgpath;
c--;
} /* fin du while */
printf_cmdl("[CONFIG] %s %i options set from command line\n",((prefix == NULL) ? "(root)":prefix),j);
free(cfgpath);
return j;
} /* parse_cmdline*/
+34 -1
View File
@@ -29,6 +29,9 @@
* \note
* \warning
*/
#define _GNU_SOURCE
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
@@ -37,8 +40,8 @@
#include <dlfcn.h>
#include <arpa/inet.h>
#include <platform_types.h>
#include "config_userapi.h"
extern void exit_fun(const char* s); // lte-softmodem clean exit function
configmodule_interface_t *config_get_if(void)
@@ -210,6 +213,36 @@ configmodule_interface_t *cfgif = config_get_if();
return ret;
}
int config_getlist(paramlist_def_t *ParamList, paramdef_t *params, int numparams, char *prefix)
{
if (CONFIG_ISFLAGSET(CONFIG_ABORT)) {
fprintf(stderr,"[CONFIG] config_get skipped, config module not properly initialized\n");
return -1;
}
if (!config_get_if())
return -1;
const int ret = config_get_if()->getlist(ParamList, params, numparams, prefix);
if (ret >= 0 && params) {
char *newprefix;
if (prefix) {
int rc = asprintf(&newprefix, "%s.%s", prefix, ParamList->listname);
if (rc < 0) newprefix = NULL;
} else {
newprefix = ParamList->listname;
}
char cfgpath[MAX_OPTNAME_SIZE*2 + 6]; /* prefix.listname.[listindex] */
for (int i = 0; i < ParamList->numelt; ++i) {
// TODO config_process_cmdline?
sprintf(cfgpath, "%s.[%i]", newprefix, i);
config_execcheck(ParamList->paramarray[i], numparams, cfgpath);
}
if (prefix)
free(newprefix);
}
return ret;
}
int config_isparamset(paramdef_t *params,int paramidx)
{
if ((params[paramidx].paramflags & PARAMFLAG_PARAMSET) != 0) {
+1 -3
View File
@@ -38,8 +38,6 @@
extern "C"
{
#endif
/* get rid of "exit_fun undeclared" warning */
extern void exit_fun(const char* s);
#define CONFIG_GETSOURCE ( (config_get_if()==NULL) ? NULL : config_get_if()->cfgmode )
#define CONFIG_GETNUMP ( (config_get_if()==NULL) ? 0 : config_get_if()->num_cfgP )
@@ -59,7 +57,7 @@ extern int config_assign_ipv4addr(paramdef_t *cfgoptions, char *ipv4addr);
/* apis to get parameters, to be used by oai modules, at configuration time */
extern int config_get(paramdef_t *params,int numparams, char *prefix);
#define config_getlist config_get_if()->getlist
extern int config_getlist(paramlist_def_t *ParamList, paramdef_t *params, int numparams, char *prefix);
/* apis to retrieve parameters info after calling get or getlist functions */
extern int config_isparamset(paramdef_t *params,int paramidx);
+2 -11
View File
@@ -91,8 +91,6 @@ int read_intarray(paramdef_t *cfgoptions,config_setting_t *setting, char *cfgpat
int config_libconfig_get(paramdef_t *cfgoptions,int numoptions, char *prefix )
{
config_setting_t *setting;
char *str;
int i,u;
@@ -103,15 +101,9 @@ int config_libconfig_get(paramdef_t *cfgoptions,int numoptions, char *prefix )
int notfound;
int defval;
int fatalerror=0;
char *cfgpath; /* listname.[listindex].paramname */
int numdefvals=0;
i = (prefix ==NULL) ? 0 : strlen(prefix);
cfgpath = malloc( i+ MAX_OPTNAME_SIZE +1);
if (cfgpath == NULL) {
fprintf(stderr,"[LIBCONFIG] %s %i malloc error, %s\n", __FILE__, __LINE__,strerror(errno));
return -1;
}
char cfgpath[512]; /* 512 should be enough for the sprintf below */
for(i=0;i<numoptions;i++) {
if (prefix != NULL) {
@@ -253,7 +245,6 @@ int config_libconfig_get(paramdef_t *cfgoptions,int numoptions, char *prefix )
config_libconfig_end();
end_configmodule();
}
free(cfgpath);
return status;
}
+1 -1
View File
@@ -456,7 +456,7 @@ int rt = pthread_getname_np(pthread_self(), threadname,bufsize) ;
}
}
int inline log_header(char *log_buffer, int buffsize, int comp, int level,const char *format) {
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],
-1
View File
@@ -44,7 +44,6 @@
#include <unistd.h>
#include "assertions.h"
#include "signals.h"
#include "vcd_signal_dumper.h"
+67 -4
View File
@@ -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_ */
-32
View File
@@ -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
-90
View File
@@ -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_ */
-930
View File
@@ -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);
}
-235
View File
@@ -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_ */
-82
View File
@@ -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
-26
View File
@@ -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.
-37
View File
@@ -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_ */
-141
View File
@@ -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 "common/utils/LOG/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;
}
-29
View File
@@ -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_ */
-25
View File
@@ -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.
-255
View File
@@ -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 "common/utils/LOG/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;
}
-69
View File
@@ -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
-22
View File
@@ -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)
-35
View File
@@ -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_ */
+103 -62
View File
@@ -120,75 +120,116 @@ int ret;
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(autoinit_arg);
}
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)
-1
View File
@@ -37,7 +37,6 @@
#include "liblfds611.h"
#include "intertask_interface.h"
#include "timer.h"
+2
View File
@@ -65,6 +65,8 @@ typedef enum {
MSC_F1AP_CU,
MSC_F1AP_DU,
MAX_MSC_PROTOS,
MSC_X2AP_SRC_ENB,
MSC_X2AP_TARGET_ENB,
} msc_proto_t;
+16
View File
@@ -0,0 +1,16 @@
#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"
#include "openair2/COMMON/f1ap_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;}
}
+543
View File
@@ -0,0 +1,543 @@
/*
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_CU_F1, TASK_PRIORITY_MED, 200, NULL, NULL) \
TASK_DEF(TASK_DU_F1, TASK_PRIORITY_MED, 200, 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_ */
@@ -303,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);