FlexRAN: reimplement timers without ITTI
The timer code used to trigger periodic statistics message sending used ITTI. Together with a high frequency reporting (e.g. 1ms), this resulted in high CPU usage. This commit reimplements this: * using a thread that is synchronized to the RU (if there is no MAC, we assume there is no RU generating a tick so we create the tick source ourselves) * no RB trees but plain arrays * smaller interface for users * slight user interface changes * remove stopped timer state: such timer might be simply removed * remove one-shot timers
This commit is contained in:
@@ -1562,11 +1562,10 @@ int flexran_agent_register_mac_xface(mid_t mod_id)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//xface->agent_ctxt = &shared_ctxt[mod_id];
|
|
||||||
xface->flexran_agent_send_sr_info = flexran_agent_send_sr_info;
|
xface->flexran_agent_send_sr_info = flexran_agent_send_sr_info;
|
||||||
xface->flexran_agent_send_sf_trigger = flexran_agent_send_sf_trigger;
|
xface->flexran_agent_send_sf_trigger = flexran_agent_send_sf_trigger;
|
||||||
//xface->flexran_agent_send_update_mac_stats = flexran_agent_send_update_mac_stats;
|
|
||||||
xface->flexran_agent_get_pending_dl_mac_config = flexran_agent_get_pending_dl_mac_config;
|
xface->flexran_agent_get_pending_dl_mac_config = flexran_agent_get_pending_dl_mac_config;
|
||||||
|
xface->flexran_agent_notify_tick = flexran_agent_timer_signal;
|
||||||
|
|
||||||
xface->dl_scheduler_loaded_lib = NULL;
|
xface->dl_scheduler_loaded_lib = NULL;
|
||||||
xface->ul_scheduler_loaded_lib = NULL;
|
xface->ul_scheduler_loaded_lib = NULL;
|
||||||
@@ -1689,11 +1688,10 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
AGENT_MAC_xface *xface = agent_mac_xface[mod_id];
|
AGENT_MAC_xface *xface = agent_mac_xface[mod_id];
|
||||||
//xface->agent_ctxt = NULL;
|
|
||||||
xface->flexran_agent_send_sr_info = NULL;
|
xface->flexran_agent_send_sr_info = NULL;
|
||||||
xface->flexran_agent_send_sf_trigger = NULL;
|
xface->flexran_agent_send_sf_trigger = NULL;
|
||||||
//xface->flexran_agent_send_update_mac_stats = NULL;
|
|
||||||
xface->flexran_agent_get_pending_dl_mac_config = NULL;
|
xface->flexran_agent_get_pending_dl_mac_config = NULL;
|
||||||
|
xface->flexran_agent_notify_tick = NULL;
|
||||||
|
|
||||||
xface->dl_scheduler_loaded_lib = NULL;
|
xface->dl_scheduler_loaded_lib = NULL;
|
||||||
xface->ul_scheduler_loaded_lib = NULL;
|
xface->ul_scheduler_loaded_lib = NULL;
|
||||||
|
|||||||
@@ -54,10 +54,9 @@ typedef struct {
|
|||||||
void (*flexran_agent_get_pending_dl_mac_config)(mid_t mod_id,
|
void (*flexran_agent_get_pending_dl_mac_config)(mid_t mod_id,
|
||||||
Protocol__FlexranMessage **msg);
|
Protocol__FlexranMessage **msg);
|
||||||
|
|
||||||
/// Notify the controller for a state change of a particular UE, by sending the proper
|
/// Notify the controller of another (RU) tick, i.e. new subframe. Used to
|
||||||
/// UE state change message (ACTIVATION, DEACTIVATION, HANDOVER)
|
/// synchronize the eNB and the agent.
|
||||||
// int (*flexran_agent_notify_ue_state_change)(mid_t mod_id, uint32_t rnti,
|
void (*flexran_agent_notify_tick)(mid_t mod_id);
|
||||||
// uint8_t state_change);
|
|
||||||
|
|
||||||
|
|
||||||
void *dl_scheduler_loaded_lib;
|
void *dl_scheduler_loaded_lib;
|
||||||
|
|||||||
@@ -33,27 +33,14 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
void *receive_thread(void *args);
|
|
||||||
Protocol__FlexranMessage *flexran_agent_timeout(void* args);
|
|
||||||
|
|
||||||
|
|
||||||
int agent_task_created = 0;
|
int agent_task_created = 0;
|
||||||
/*
|
/*
|
||||||
* enb agent task mainly wakes up the tx thread for periodic and oneshot messages to the controller
|
* enb agent task mainly wakes up the tx thread for periodic and oneshot messages to the controller
|
||||||
* and can interact with other itti tasks
|
* and can interact with other itti tasks
|
||||||
*/
|
*/
|
||||||
void *flexran_agent_task(void *args){
|
void *flexran_agent_task(void *args){
|
||||||
|
MessageDef *msg_p = NULL;
|
||||||
//flexran_agent_info_t *d = (flexran_agent_info_t *) args;
|
int result;
|
||||||
Protocol__FlexranMessage *msg;
|
|
||||||
void *data;
|
|
||||||
int size;
|
|
||||||
err_code_t err_code=0;
|
|
||||||
int priority = 0;
|
|
||||||
|
|
||||||
MessageDef *msg_p = NULL;
|
|
||||||
int result;
|
|
||||||
struct flexran_agent_timer_element_s * elem = NULL;
|
|
||||||
|
|
||||||
itti_mark_task_ready(TASK_FLEXRAN_AGENT);
|
itti_mark_task_ready(TASK_FLEXRAN_AGENT);
|
||||||
|
|
||||||
@@ -72,20 +59,6 @@ void *flexran_agent_task(void *args){
|
|||||||
LOG_I(FLEXRAN_AGENT, "Received %s\n", ITTI_MSG_NAME(msg_p));
|
LOG_I(FLEXRAN_AGENT, "Received %s\n", ITTI_MSG_NAME(msg_p));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TIMER_HAS_EXPIRED:
|
|
||||||
msg = flexran_agent_process_timeout(msg_p->ittiMsg.timer_has_expired.timer_id, msg_p->ittiMsg.timer_has_expired.arg);
|
|
||||||
if (msg != NULL){
|
|
||||||
data=flexran_agent_pack_message(msg,&size);
|
|
||||||
elem = get_timer_entry(msg_p->ittiMsg.timer_has_expired.timer_id);
|
|
||||||
if (flexran_agent_msg_send(elem->agent_id, FLEXRAN_AGENT_DEFAULT, data, size, priority)) {
|
|
||||||
err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENQUEUING;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_D(FLEXRAN_AGENT,"sent message with size %d\n", size);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_E(FLEXRAN_AGENT, "Received unexpected message %s\n", ITTI_MSG_NAME (msg_p));
|
LOG_E(FLEXRAN_AGENT, "Received unexpected message %s\n", ITTI_MSG_NAME (msg_p));
|
||||||
break;
|
break;
|
||||||
@@ -93,10 +66,6 @@ void *flexran_agent_task(void *args){
|
|||||||
|
|
||||||
result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
|
result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
|
||||||
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
||||||
continue;
|
|
||||||
error:
|
|
||||||
if (err_code != 0)
|
|
||||||
LOG_E(FLEXRAN_AGENT,"flexran_agent_task: error %d occured\n",err_code);
|
|
||||||
} while (1);
|
} while (1);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -245,7 +214,7 @@ int flexran_agent_start(mid_t mod_id)
|
|||||||
* initilize a timer
|
* initilize a timer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
flexran_agent_init_timer();
|
flexran_agent_timer_init(mod_id);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* start the enb agent task for tx and interaction with the underlying network function
|
* start the enb agent task for tx and interaction with the underlying network function
|
||||||
@@ -286,16 +255,3 @@ error:
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Protocol__FlexranMessage *flexran_agent_timeout(void* args){
|
|
||||||
|
|
||||||
// flexran_agent_timer_args_t *timer_args = calloc(1, sizeof(*timer_args));
|
|
||||||
//memcpy (timer_args, args, sizeof(*timer_args));
|
|
||||||
flexran_agent_timer_args_t *timer_args = (flexran_agent_timer_args_t *) args;
|
|
||||||
|
|
||||||
LOG_UI(FLEXRAN_AGENT, "flexran_agent %d timeout\n", timer_args->mod_id);
|
|
||||||
//LOG_I(FLEXRAN_AGENT, "eNB action %d ENB flags %d \n", timer_args->cc_actions,timer_args->cc_report_flags);
|
|
||||||
//LOG_I(FLEXRAN_AGENT, "UE action %d UE flags %d \n", timer_args->ue_actions,timer_args->ue_report_flags);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -150,10 +150,15 @@ Protocol__FlexranMessage* flexran_agent_handle_message (mid_t mod_id,
|
|||||||
uint32_t size);
|
uint32_t size);
|
||||||
|
|
||||||
/* Function to be used to send a message to a dispatcher once the appropriate event is triggered. */
|
/* Function to be used to send a message to a dispatcher once the appropriate event is triggered. */
|
||||||
Protocol__FlexranMessage *flexran_agent_handle_timed_task(void *args);
|
Protocol__FlexranMessage *flexran_agent_handle_timed_task(
|
||||||
|
mid_t mod_id,
|
||||||
|
Protocol__FlexranMessage *msg);
|
||||||
|
|
||||||
/*Top level Statistics hanlder*/
|
/*Top level Statistics hanlder*/
|
||||||
Protocol__FlexranMessage *flexran_agent_send_stats_reply(void *args);
|
Protocol__FlexranMessage *flexran_agent_send_stats_reply(
|
||||||
|
mid_t mod_id,
|
||||||
|
const Protocol__FlexranMessage *msg);
|
||||||
|
|
||||||
int flexran_agent_handle_stats(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
|
int flexran_agent_handle_stats(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
|
||||||
|
|
||||||
/* Function to be used to handle reply message . */
|
/* Function to be used to handle reply message . */
|
||||||
|
|||||||
@@ -107,36 +107,6 @@ typedef uint8_t lcid_t;
|
|||||||
typedef int32_t err_code_t;
|
typedef int32_t err_code_t;
|
||||||
|
|
||||||
|
|
||||||
/*---------Timer Enums --------- */
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
/* oneshot timer: */
|
|
||||||
FLEXRAN_AGENT_TIMER_TYPE_ONESHOT = 0,
|
|
||||||
|
|
||||||
/* periodic timer */
|
|
||||||
FLEXRAN_AGENT_TIMER_TYPE_PERIODIC = 1,
|
|
||||||
|
|
||||||
/* Inactive state: initial state for any timer. */
|
|
||||||
FLEXRAN_AGENT_TIMER_TYPE_EVENT_DRIVEN = 2,
|
|
||||||
|
|
||||||
/* Max number of states available */
|
|
||||||
FLEXRAN_AGENT_TIMER_TYPE_MAX,
|
|
||||||
} flexran_agent_timer_type_t;
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
/* Inactive state: initial state for any timer. */
|
|
||||||
FLEXRAN_AGENT_TIMER_STATE_INACTIVE = 0x0,
|
|
||||||
|
|
||||||
/* Inactive state: initial state for any timer. */
|
|
||||||
FLEXRAN_AGENT_TIMER_STATE_ACTIVE = 0x1,
|
|
||||||
|
|
||||||
/* Inactive state: initial state for any timer. */
|
|
||||||
FLEXRAN_AGENT_TIMER_STATE_STOPPED = 0x2,
|
|
||||||
|
|
||||||
/* Max number of states available */
|
|
||||||
FLEXRAN_AGENT_TIMER_STATE_MAX,
|
|
||||||
} flexran_agent_timer_state_t;
|
|
||||||
|
|
||||||
#define FLEXRAN_CAP_LOPHY(cApS) (((cApS) & (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOPHY)) > 0)
|
#define FLEXRAN_CAP_LOPHY(cApS) (((cApS) & (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOPHY)) > 0)
|
||||||
#define FLEXRAN_CAP_HIPHY(cApS) (((cApS) & (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIPHY)) > 0)
|
#define FLEXRAN_CAP_HIPHY(cApS) (((cApS) & (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIPHY)) > 0)
|
||||||
|
|||||||
@@ -154,39 +154,20 @@ void * flexran_agent_pack_message(Protocol__FlexranMessage *msg,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Protocol__FlexranMessage *flexran_agent_handle_timed_task(void *args) {
|
Protocol__FlexranMessage *flexran_agent_handle_timed_task(
|
||||||
|
mid_t mod_id,
|
||||||
|
Protocol__FlexranMessage *msg) {
|
||||||
err_code_t err_code;
|
err_code_t err_code;
|
||||||
flexran_agent_timer_args_t *timer_args = (flexran_agent_timer_args_t *) args;
|
|
||||||
|
|
||||||
Protocol__FlexranMessage *timed_task, *reply_message;
|
Protocol__FlexranMessage *reply_message;
|
||||||
timed_task = timer_args->msg;
|
err_code = ((*agent_messages_callback[msg->msg_case-1][msg->msg_dir-1])(
|
||||||
err_code = ((*agent_messages_callback[timed_task->msg_case-1][timed_task->msg_dir-1])(timer_args->mod_id, (void *) timed_task, &reply_message));
|
mod_id, msg, &reply_message));
|
||||||
if ( err_code < 0 ){
|
if (err_code < 0) {
|
||||||
goto error;
|
LOG_E(FLEXRAN_AGENT, "could not handle message: errno %d occured\n", err_code);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return reply_message;
|
return reply_message;
|
||||||
|
|
||||||
error:
|
|
||||||
LOG_E(FLEXRAN_AGENT,"errno %d occured\n",err_code);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Protocol__FlexranMessage* flexran_agent_process_timeout(long timer_id, void* timer_args){
|
|
||||||
|
|
||||||
struct flexran_agent_timer_element_s *found = get_timer_entry(timer_id);
|
|
||||||
|
|
||||||
if (found == NULL ) goto error;
|
|
||||||
LOG_D(FLEXRAN_AGENT, "Found the entry (%p): timer_id is 0x%lx 0x%lx\n", found, timer_id, found->timer_id);
|
|
||||||
|
|
||||||
if (timer_args == NULL)
|
|
||||||
LOG_W(FLEXRAN_AGENT,"null timer args\n");
|
|
||||||
|
|
||||||
return found->cb(timer_args);
|
|
||||||
|
|
||||||
error:
|
|
||||||
LOG_E(FLEXRAN_AGENT, "can't get the timer element\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err_code_t flexran_agent_destroy_flexran_message(Protocol__FlexranMessage *msg) {
|
err_code_t flexran_agent_destroy_flexran_message(Protocol__FlexranMessage *msg) {
|
||||||
@@ -209,24 +190,21 @@ int flexran_agent_handle_stats(mid_t mod_id, const void *params, Protocol__Flexr
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
Protocol__FlexCompleteStatsRequest *comp_req = stats_req->complete_stats_request;
|
Protocol__FlexCompleteStatsRequest *comp_req = stats_req->complete_stats_request;
|
||||||
flexran_agent_timer_args_t *timer_args = NULL;
|
|
||||||
|
|
||||||
switch (comp_req->report_frequency) {
|
switch (comp_req->report_frequency) {
|
||||||
case PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_OFF:
|
case PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_OFF:
|
||||||
flexran_agent_destroy_timer_by_task_id(xid);
|
flexran_agent_destroy_timer(mod_id, xid);
|
||||||
return 0;
|
return 0;
|
||||||
case PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_ONCE:
|
case PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_ONCE:
|
||||||
LOG_E(FLEXRAN_AGENT, "one-shot timer not implemented yet\n");
|
LOG_E(FLEXRAN_AGENT, "one-shot timer not implemented yet\n");
|
||||||
return -1;
|
return -1;
|
||||||
case PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_PERIODICAL:
|
case PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_PERIODICAL:
|
||||||
/* Create a one off flexran message as an argument for the periodical task */
|
/* Create a one off flexran message as an argument for the periodical task */
|
||||||
timer_args = calloc(1, sizeof(flexran_agent_timer_args_t));
|
LOG_I(FLEXRAN_AGENT, "periodical timer xid %d cell_flags %d ue_flags %d\n",
|
||||||
AssertFatal(timer_args, "cannot allocate memory for timer\n");
|
xid, comp_req->cell_report_flags, comp_req->ue_report_flags);
|
||||||
timer_args->mod_id = mod_id;
|
|
||||||
timer_args->msg = input;
|
|
||||||
flexran_agent_create_timer(mod_id, comp_req->sf,
|
flexran_agent_create_timer(mod_id, comp_req->sf,
|
||||||
FLEXRAN_AGENT_TIMER_TYPE_PERIODIC, xid,
|
FLEXRAN_AGENT_TIMER_TYPE_PERIODIC, xid,
|
||||||
flexran_agent_send_stats_reply, timer_args);
|
flexran_agent_send_stats_reply, input);
|
||||||
/* return 1: do not dispose comp_req message we received, we still need it */
|
/* return 1: do not dispose comp_req message we received, we still need it */
|
||||||
return 1;
|
return 1;
|
||||||
case PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_CONTINUOUS:
|
case PROTOCOL__FLEX_STATS_REPORT_FREQ__FLSRF_CONTINUOUS:
|
||||||
@@ -241,15 +219,14 @@ int flexran_agent_handle_stats(mid_t mod_id, const void *params, Protocol__Flexr
|
|||||||
/*
|
/*
|
||||||
Top level reply
|
Top level reply
|
||||||
*/
|
*/
|
||||||
Protocol__FlexranMessage *flexran_agent_send_stats_reply(void *args) {
|
Protocol__FlexranMessage *flexran_agent_send_stats_reply(
|
||||||
const flexran_agent_timer_args_t *timer_args = args;
|
mid_t mod_id,
|
||||||
const mid_t enb_id = timer_args->mod_id;
|
const Protocol__FlexranMessage *msg) {
|
||||||
const Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)timer_args->msg;
|
const Protocol__FlexStatsRequest *stats_req = msg->stats_request_msg;
|
||||||
const Protocol__FlexStatsRequest *stats_req = input->stats_request_msg;
|
|
||||||
const xid_t xid = stats_req->header->xid;
|
const xid_t xid = stats_req->header->xid;
|
||||||
|
|
||||||
Protocol__FlexranMessage *reply = NULL;
|
Protocol__FlexranMessage *reply = NULL;
|
||||||
err_code_t rc = flexran_agent_stats_reply(enb_id, xid, stats_req, &reply);
|
err_code_t rc = flexran_agent_stats_reply(mod_id, xid, stats_req, &reply);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
LOG_E(FLEXRAN_AGENT, "%s(): errno %d occured, cannot send stats_reply\n",
|
LOG_E(FLEXRAN_AGENT, "%s(): errno %d occured, cannot send stats_reply\n",
|
||||||
__func__, rc);
|
__func__, rc);
|
||||||
|
|||||||
@@ -21,175 +21,266 @@
|
|||||||
|
|
||||||
/*! \file flexran_agent_timer.c
|
/*! \file flexran_agent_timer.c
|
||||||
* \brief FlexRAN Timer
|
* \brief FlexRAN Timer
|
||||||
* \author shahab SHARIAT BAGHERI
|
* \author Robert Schmidt
|
||||||
* \date 2017
|
* \date 2019
|
||||||
* \version 0.1
|
* \version 0.2
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* timer primitives
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "flexran_agent_timer.h"
|
#include "flexran_agent_timer.h"
|
||||||
|
#include "flexran_agent_extern.h"
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <sys/timerfd.h>
|
||||||
|
|
||||||
//struct flexran_agent_map agent_map;
|
#define MAX_NUM_TIMERS 10
|
||||||
flexran_agent_timer_instance_t timer_instance;
|
|
||||||
int agent_timer_init = 0;
|
|
||||||
err_code_t flexran_agent_init_timer(void) {
|
|
||||||
LOG_I(FLEXRAN_AGENT, "init RB tree\n");
|
|
||||||
|
|
||||||
if (!agent_timer_init) {
|
typedef struct flexran_agent_timer_element_s {
|
||||||
RB_INIT(&timer_instance.flexran_agent_head);
|
mid_t mod_id;
|
||||||
agent_timer_init = 1;
|
xid_t xid; /* The id of the task as received by the controller message*/
|
||||||
|
uint32_t sf;
|
||||||
|
uint64_t next;
|
||||||
|
flexran_agent_timer_callback_t cb;
|
||||||
|
Protocol__FlexranMessage *msg;
|
||||||
|
} flexran_agent_timer_element_t;
|
||||||
|
|
||||||
|
typedef struct flexran_agent_timer_extern_source_s {
|
||||||
|
pthread_mutex_t mutex_sync;
|
||||||
|
pthread_cond_t cond;
|
||||||
|
int wait;
|
||||||
|
} flexran_agent_timer_extern_source_t;
|
||||||
|
|
||||||
|
struct timesync {
|
||||||
|
void *param_sync;
|
||||||
|
void (*fsync)(void *);
|
||||||
|
pthread_t thread;
|
||||||
|
|
||||||
|
uint64_t current;
|
||||||
|
uint64_t next;
|
||||||
|
|
||||||
|
int timer_num;
|
||||||
|
flexran_agent_timer_element_t *timer[MAX_NUM_TIMERS];
|
||||||
|
pthread_mutex_t mutex_timer;
|
||||||
|
|
||||||
|
int exit;
|
||||||
|
};
|
||||||
|
struct timesync timesync[NUM_MAX_ENB];
|
||||||
|
|
||||||
|
int flexran_agent_timer_signal_init(struct timesync *sync);
|
||||||
|
int flexran_agent_timer_source_setup(struct timesync *sync);
|
||||||
|
void *flexran_agent_timer_thread(void *args);
|
||||||
|
void flexran_agent_timer_remove_internal(struct timesync *sync, int index);
|
||||||
|
void flexran_agent_timer_process(flexran_agent_timer_element_t *t);
|
||||||
|
|
||||||
|
|
||||||
|
err_code_t flexran_agent_timer_init(mid_t mod_id) {
|
||||||
|
struct timesync *sync = ×ync[mod_id];
|
||||||
|
sync->current = 0;
|
||||||
|
sync->next = 0;
|
||||||
|
sync->timer_num = 0;
|
||||||
|
for (int i = 0; i < MAX_NUM_TIMERS; ++i)
|
||||||
|
sync->timer[i] = NULL;
|
||||||
|
pthread_mutex_init(&sync->mutex_timer, NULL);
|
||||||
|
sync->exit = 0;
|
||||||
|
|
||||||
|
/* if there is a MAC, we assume we can have a tick from the MAC interface
|
||||||
|
* (external tick source). Otherwise, generate a tick internally via the
|
||||||
|
* timerfd linux library. The init functions set everything up and the thread
|
||||||
|
* will use whatever is available. */
|
||||||
|
int (*init)(struct timesync *) = flexran_agent_get_mac_xface(mod_id) ?
|
||||||
|
flexran_agent_timer_signal_init : flexran_agent_timer_source_setup;
|
||||||
|
if (init(timesync) < 0
|
||||||
|
|| pthread_create(&sync->thread, NULL, flexran_agent_timer_thread, sync) != 0) {
|
||||||
|
sync->thread = 0;
|
||||||
|
if (sync->param_sync)
|
||||||
|
free(sync->param_sync);
|
||||||
|
LOG_E(FLEXRAN_AGENT, "could not start timer thread\n");
|
||||||
|
return TIMER_SETUP_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return PROTOCOL__FLEXRAN_ERR__NO_ERR;
|
return PROTOCOL__FLEXRAN_ERR__NO_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
RB_GENERATE(flexran_agent_map, flexran_agent_timer_element_s, entry, flexran_agent_compare_timer);
|
void flexran_agent_timer_exit(mid_t mod_id) {
|
||||||
|
timesync[mod_id].exit = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* The timer_id might not be the best choice for the comparison */
|
void flexran_agent_timer_source_sync(void *sync) {
|
||||||
int flexran_agent_compare_timer(struct flexran_agent_timer_element_s *a, struct flexran_agent_timer_element_s *b) {
|
int fd = *(int *)sync;
|
||||||
if (a->timer_id < b->timer_id) return -1;
|
uint64_t occ;
|
||||||
|
int rc __attribute__((unused)) = read(fd, &occ, sizeof(occ));
|
||||||
|
}
|
||||||
|
|
||||||
if (a->timer_id > b->timer_id) return 1;
|
int flexran_agent_timer_source_setup(struct timesync *sync) {
|
||||||
|
sync->param_sync = malloc(sizeof(int));
|
||||||
|
if (!sync->param_sync)
|
||||||
|
return -1;
|
||||||
|
int fd = timerfd_create(CLOCK_MONOTONIC, 0);
|
||||||
|
if (fd < 0)
|
||||||
|
return fd;
|
||||||
|
|
||||||
// equal timers
|
const uint64_t period_ns = 1000000; // 1ms
|
||||||
|
struct itimerspec t;
|
||||||
|
t.it_interval.tv_sec = period_ns / 1000000000;
|
||||||
|
t.it_interval.tv_nsec = period_ns % 1000000000;
|
||||||
|
t.it_value.tv_sec = period_ns / 1000000000;
|
||||||
|
t.it_value.tv_nsec = period_ns % 1000000000;
|
||||||
|
int rc = timerfd_settime(fd, 0, &t, NULL);
|
||||||
|
if (rc != 0)
|
||||||
|
return -1;
|
||||||
|
*(int *)sync->param_sync = fd;
|
||||||
|
sync->fsync = flexran_agent_timer_source_sync;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void flexran_agent_timer_signal_sync(void *param_sync) {
|
||||||
|
flexran_agent_timer_extern_source_t *sync = param_sync;
|
||||||
|
pthread_mutex_lock(&sync->mutex_sync);
|
||||||
|
while (sync->wait) {
|
||||||
|
pthread_cond_wait(&sync->cond, &sync->mutex_sync);
|
||||||
|
}
|
||||||
|
sync->wait = 1;
|
||||||
|
pthread_mutex_unlock(&sync->mutex_sync);
|
||||||
|
}
|
||||||
|
|
||||||
|
int flexran_agent_timer_signal_init(struct timesync *sync) {
|
||||||
|
flexran_agent_timer_extern_source_t *s = malloc(sizeof(flexran_agent_timer_extern_source_t));
|
||||||
|
if (!s)
|
||||||
|
return TIMER_SETUP_FAILED;
|
||||||
|
if (pthread_mutex_init(&s->mutex_sync, NULL) < 0)
|
||||||
|
return TIMER_SETUP_FAILED;
|
||||||
|
if (pthread_cond_init(&s->cond, NULL) < 0)
|
||||||
|
return TIMER_SETUP_FAILED;
|
||||||
|
s->wait = 1;
|
||||||
|
sync->param_sync = s;
|
||||||
|
sync->fsync = flexran_agent_timer_signal_sync;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void flexran_agent_timer_signal(mid_t mod_id) {
|
||||||
|
flexran_agent_timer_extern_source_t *sync = timesync[mod_id].param_sync;
|
||||||
|
pthread_mutex_lock(&sync->mutex_sync);
|
||||||
|
sync->wait = 0;
|
||||||
|
pthread_mutex_unlock(&sync->mutex_sync);
|
||||||
|
pthread_cond_signal(&sync->cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *flexran_agent_timer_thread(void *args) {
|
||||||
|
struct timesync *sync = args;
|
||||||
|
while (1) {
|
||||||
|
sync->fsync(sync->param_sync);
|
||||||
|
if (sync->exit)
|
||||||
|
break;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&sync->mutex_timer);
|
||||||
|
sync->current++;
|
||||||
|
|
||||||
|
if (sync->current < sync->next) {
|
||||||
|
pthread_mutex_unlock(&sync->mutex_timer);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < sync->timer_num; ++i) {
|
||||||
|
flexran_agent_timer_element_t *t = sync->timer[i];
|
||||||
|
if (sync->current == t->next) {
|
||||||
|
flexran_agent_timer_process(t);
|
||||||
|
t->next += t->sf;
|
||||||
|
}
|
||||||
|
if (sync->next == sync->current || t->next < sync->next)
|
||||||
|
sync->next = t->next;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&sync->mutex_timer);
|
||||||
|
}
|
||||||
|
LOG_W(FLEXRAN_AGENT, "terminated timer thread\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void flexran_agent_timer_process(flexran_agent_timer_element_t *t) {
|
||||||
|
Protocol__FlexranMessage *msg = t->cb(t->mod_id, t->msg);
|
||||||
|
if (!msg)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int size = 0;
|
||||||
|
void *data = flexran_agent_pack_message(msg, &size);
|
||||||
|
if (flexran_agent_msg_send(t->mod_id, FLEXRAN_AGENT_DEFAULT, data, size, 0) < 0)
|
||||||
|
LOG_E(FLEXRAN_AGENT, "error while sending message for timer xid %d\n", t->xid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
err_code_t flexran_agent_create_timer(mid_t mod_id,
|
err_code_t flexran_agent_create_timer(mid_t mod_id,
|
||||||
uint32_t sf,
|
uint32_t sf,
|
||||||
uint32_t timer_type,
|
flexran_agent_timer_type_t timer_type,
|
||||||
xid_t xid,
|
xid_t xid,
|
||||||
flexran_agent_timer_callback_t cb,
|
flexran_agent_timer_callback_t cb,
|
||||||
void *timer_args) {
|
Protocol__FlexranMessage *msg) {
|
||||||
int ret=-1;
|
if (sf == 0)
|
||||||
|
|
||||||
if (sf <= 0)
|
|
||||||
return TIMER_NULL;
|
return TIMER_NULL;
|
||||||
|
if (cb == NULL)
|
||||||
|
return TIMER_SETUP_FAILED;
|
||||||
|
AssertFatal(timer_type != FLEXRAN_AGENT_TIMER_TYPE_ONESHOT,
|
||||||
|
"one shot timer not yet implemented\n");
|
||||||
|
|
||||||
if (timer_type >= FLEXRAN_AGENT_TIMER_TYPE_MAX)
|
flexran_agent_timer_element_t *t = malloc(sizeof(flexran_agent_timer_element_t));
|
||||||
return TIMER_TYPE_INVALIDE;
|
if (!t) {
|
||||||
|
LOG_E(FLEXRAN_AGENT, "no memory for new timer %d\n", xid);
|
||||||
uint32_t interval_usec = sf * 1000;
|
|
||||||
uint32_t interval_sec = 0;
|
|
||||||
if (interval_usec >= 1000 * 1000) {
|
|
||||||
interval_sec = interval_usec / (1000 * 1000);
|
|
||||||
interval_usec = interval_usec % (1000 * 1000);
|
|
||||||
}
|
|
||||||
struct flexran_agent_timer_element_s *e = calloc(1, sizeof(*e));
|
|
||||||
DevAssert(e != NULL);
|
|
||||||
long timer_id = 0;
|
|
||||||
AssertFatal(e, "cannot allocate memory for FlexRAN timer!\n");
|
|
||||||
if (timer_type == FLEXRAN_AGENT_TIMER_TYPE_ONESHOT) {
|
|
||||||
ret = timer_setup(interval_sec,
|
|
||||||
interval_usec,
|
|
||||||
TASK_FLEXRAN_AGENT,
|
|
||||||
mod_id,
|
|
||||||
TIMER_ONE_SHOT,
|
|
||||||
timer_args,
|
|
||||||
&timer_id);
|
|
||||||
|
|
||||||
e->type = TIMER_ONE_SHOT;
|
|
||||||
} else if (timer_type == FLEXRAN_AGENT_TIMER_TYPE_PERIODIC ) {
|
|
||||||
ret = timer_setup(interval_sec,
|
|
||||||
interval_usec,
|
|
||||||
TASK_FLEXRAN_AGENT,
|
|
||||||
mod_id,
|
|
||||||
TIMER_PERIODIC,
|
|
||||||
timer_args,
|
|
||||||
&timer_id);
|
|
||||||
e->type = TIMER_PERIODIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret < 0 ) {
|
|
||||||
free(e);
|
|
||||||
return TIMER_SETUP_FAILED;
|
return TIMER_SETUP_FAILED;
|
||||||
}
|
}
|
||||||
|
t->mod_id = mod_id;
|
||||||
|
t->xid = xid;
|
||||||
|
t->sf = sf;
|
||||||
|
t->cb = cb;
|
||||||
|
t->msg = msg;
|
||||||
|
|
||||||
e->agent_id = mod_id;
|
struct timesync *sync = ×ync[mod_id];
|
||||||
e->instance = mod_id;
|
pthread_mutex_lock(&sync->mutex_timer);
|
||||||
e->state = FLEXRAN_AGENT_TIMER_STATE_ACTIVE;
|
if (sync->timer_num >= MAX_NUM_TIMERS) {
|
||||||
e->timer_id = timer_id;
|
pthread_mutex_unlock(&sync->mutex_timer);
|
||||||
e->xid = xid;
|
LOG_E(FLEXRAN_AGENT, "maximum number of timers (%d) reached while adding timer %d\n",
|
||||||
e->timer_args = timer_args;
|
sync->timer_num, xid);
|
||||||
e->cb = cb;
|
free(t);
|
||||||
/*element should be a real pointer*/
|
return TIMER_SETUP_FAILED;
|
||||||
RB_INSERT(flexran_agent_map, &timer_instance.flexran_agent_head, e);
|
|
||||||
LOG_I(FLEXRAN_AGENT,"Created a new timer with id 0x%lx for agent %d, instance %d \n",
|
|
||||||
e->timer_id, e->agent_id, e->instance);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
err_code_t flexran_agent_destroy_timer(long timer_id) {
|
|
||||||
struct flexran_agent_timer_element_s *e = get_timer_entry(timer_id);
|
|
||||||
|
|
||||||
if (e != NULL ) {
|
|
||||||
RB_REMOVE(flexran_agent_map, &timer_instance.flexran_agent_head, e);
|
|
||||||
flexran_agent_destroy_flexran_message(e->timer_args->msg);
|
|
||||||
free(e);
|
|
||||||
}
|
}
|
||||||
|
/* TODO check that xid does not exist? */
|
||||||
if (timer_remove(timer_id) < 0 )
|
t->next = sync->current + 1;
|
||||||
goto error;
|
if (sync->next <= sync->current || t->next < sync->next)
|
||||||
|
sync->next = t->next;
|
||||||
|
sync->timer[sync->timer_num] = t;
|
||||||
|
sync->timer_num++;
|
||||||
|
pthread_mutex_unlock(&sync->mutex_timer);
|
||||||
|
LOG_D(FLEXRAN_AGENT, "added new timer xid %d for agent %d\n", xid, mod_id);
|
||||||
return 0;
|
return 0;
|
||||||
error:
|
|
||||||
LOG_E(FLEXRAN_AGENT, "timer can't be removed\n");
|
|
||||||
return TIMER_REMOVED_FAILED ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err_code_t flexran_agent_destroy_timer_by_task_id(xid_t xid) {
|
err_code_t flexran_agent_destroy_timers(mid_t mod_id) {
|
||||||
struct flexran_agent_timer_element_s *e = NULL;
|
struct timesync *sync = ×ync[mod_id];
|
||||||
long timer_id;
|
pthread_mutex_lock(&sync->mutex_timer);
|
||||||
RB_FOREACH(e, flexran_agent_map, &timer_instance.flexran_agent_head) {
|
for (int i = sync->timer_num - 1; i < 0; --i) {
|
||||||
if (e->xid == xid) {
|
flexran_agent_timer_remove_internal(sync, i);
|
||||||
timer_id = e->timer_id;
|
}
|
||||||
RB_REMOVE(flexran_agent_map, &timer_instance.flexran_agent_head, e);
|
pthread_mutex_unlock(&sync->mutex_timer);
|
||||||
flexran_agent_destroy_flexran_message(e->timer_args->msg);
|
return 0;
|
||||||
free(e);
|
}
|
||||||
|
|
||||||
if (timer_remove(timer_id) < 0 ) {
|
err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid) {
|
||||||
goto error;
|
struct timesync *sync = ×ync[mod_id];
|
||||||
}
|
pthread_mutex_lock(&sync->mutex_timer);
|
||||||
|
for (int i = 0; i < sync->timer_num; ++i) {
|
||||||
|
if (sync->timer[i]->xid == xid) {
|
||||||
|
flexran_agent_timer_remove_internal(sync, i);
|
||||||
|
pthread_mutex_unlock(&sync->mutex_timer);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
pthread_mutex_unlock(&sync->mutex_timer);
|
||||||
error:
|
LOG_E(FLEXRAN_AGENT, "could not find timer %d\n", xid);
|
||||||
LOG_E(FLEXRAN_AGENT, "timer can't be removed\n");
|
return TIMER_ELEMENT_NOT_FOUND;
|
||||||
return TIMER_REMOVED_FAILED ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err_code_t flexran_agent_destroy_timers(void) {
|
/* this function assumes that the timer lock is held */
|
||||||
struct flexran_agent_timer_element_s *e = NULL;
|
void flexran_agent_timer_remove_internal(struct timesync *sync, int index) {
|
||||||
RB_FOREACH(e, flexran_agent_map, &timer_instance.flexran_agent_head) {
|
LOG_I(FLEXRAN_AGENT, "remove timer xid %d (index %d) for agent %d\n",
|
||||||
RB_REMOVE(flexran_agent_map, &timer_instance.flexran_agent_head, e);
|
sync->timer[index]->xid, index, sync->timer[index]->mod_id);
|
||||||
timer_remove(e->timer_id);
|
flexran_agent_destroy_flexran_message(sync->timer[index]->msg);
|
||||||
flexran_agent_destroy_flexran_message(e->timer_args->msg);
|
free(sync->timer[index]);
|
||||||
free(e);
|
for (int i = index + 1; i < sync->timer_num; ++i)
|
||||||
}
|
sync->timer[i - 1] = sync->timer[i];
|
||||||
return 0;
|
sync->timer_num--;
|
||||||
}
|
sync->timer[sync->timer_num] = NULL;
|
||||||
|
|
||||||
err_code_t flexran_agent_stop_timer(long timer_id) {
|
|
||||||
struct flexran_agent_timer_element_s *e=NULL;
|
|
||||||
struct flexran_agent_timer_element_s search;
|
|
||||||
memset(&search, 0, sizeof(struct flexran_agent_timer_element_s));
|
|
||||||
search.timer_id = timer_id;
|
|
||||||
e = RB_FIND(flexran_agent_map, &timer_instance.flexran_agent_head, &search);
|
|
||||||
|
|
||||||
if (e != NULL ) {
|
|
||||||
e->state = FLEXRAN_AGENT_TIMER_STATE_STOPPED;
|
|
||||||
}
|
|
||||||
|
|
||||||
timer_remove(timer_id);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct flexran_agent_timer_element_s *get_timer_entry(long timer_id) {
|
|
||||||
struct flexran_agent_timer_element_s search;
|
|
||||||
memset(&search, 0, sizeof(struct flexran_agent_timer_element_s));
|
|
||||||
search.timer_id = timer_id;
|
|
||||||
return RB_FIND(flexran_agent_map, &timer_instance.flexran_agent_head, &search);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,100 +26,45 @@
|
|||||||
* \version 0.1
|
* \version 0.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#ifndef _FLEXRAN_AGENT_TIMER_
|
||||||
#include <time.h>
|
#define _FLEXRAN_AGENT_TIMER_
|
||||||
|
|
||||||
#include "flexran_agent_common.h"
|
#include "flexran_agent_common.h"
|
||||||
#include "flexran_agent_common_internal.h"
|
|
||||||
#include "flexran_agent_extern.h"
|
|
||||||
#include "flexran_agent_defs.h"
|
#include "flexran_agent_defs.h"
|
||||||
|
|
||||||
|
|
||||||
# include "tree.h"
|
|
||||||
# include "intertask_interface.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************
|
|
||||||
* timer primitves
|
|
||||||
*******************/
|
|
||||||
|
|
||||||
#define TIMER_NULL -1
|
#define TIMER_NULL -1
|
||||||
#define TIMER_TYPE_INVALIDE -2
|
#define TIMER_TYPE_INVALIDE -2
|
||||||
#define TIMER_SETUP_FAILED -3
|
#define TIMER_SETUP_FAILED -3
|
||||||
#define TIMER_REMOVED_FAILED -4
|
#define TIMER_REMOVED_FAILED -4
|
||||||
#define TIMER_ELEMENT_NOT_FOUND -5
|
#define TIMER_ELEMENT_NOT_FOUND -5
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FLEXRAN_AGENT_TIMER_TYPE_ONESHOT,
|
||||||
|
FLEXRAN_AGENT_TIMER_TYPE_PERIODIC,
|
||||||
|
} flexran_agent_timer_type_t;
|
||||||
|
|
||||||
/* Type of the callback executed when the timer expired */
|
/* Type of the callback executed when the timer expired */
|
||||||
typedef Protocol__FlexranMessage *(*flexran_agent_timer_callback_t)(void*);
|
typedef Protocol__FlexranMessage *(*flexran_agent_timer_callback_t)(
|
||||||
|
mid_t mod_id, const Protocol__FlexranMessage *msg);
|
||||||
|
|
||||||
|
err_code_t flexran_agent_timer_init(mid_t mod_id);
|
||||||
|
void flexran_agent_timer_exit(mid_t mod_id);
|
||||||
|
|
||||||
typedef struct flexran_agent_timer_args_s{
|
/* Signals next subframe for FlexRAN timers */
|
||||||
mid_t mod_id;
|
void flexran_agent_timer_signal(mid_t mod_id);
|
||||||
Protocol__FlexranMessage *msg;
|
|
||||||
} flexran_agent_timer_args_t;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct flexran_agent_timer_element_s{
|
|
||||||
RB_ENTRY(flexran_agent_timer_element_s) entry;
|
|
||||||
|
|
||||||
agent_id_t agent_id;
|
|
||||||
instance_t instance;
|
|
||||||
|
|
||||||
flexran_agent_timer_type_t type;
|
|
||||||
flexran_agent_timer_state_t state;
|
|
||||||
|
|
||||||
uint32_t interval_sec;
|
|
||||||
uint32_t interval_usec;
|
|
||||||
|
|
||||||
long timer_id; /* Timer id returned by the timer API*/
|
|
||||||
xid_t xid; /*The id of the task as received by the controller
|
|
||||||
message*/
|
|
||||||
|
|
||||||
flexran_agent_timer_callback_t cb;
|
|
||||||
flexran_agent_timer_args_t *timer_args;
|
|
||||||
|
|
||||||
} flexran_agent_timer_element_t;
|
|
||||||
|
|
||||||
typedef struct flexran_agent_timer_instance_s{
|
|
||||||
RB_HEAD(flexran_agent_map, flexran_agent_timer_element_s) flexran_agent_head;
|
|
||||||
}flexran_agent_timer_instance_t;
|
|
||||||
|
|
||||||
|
|
||||||
err_code_t flexran_agent_init_timer(void);
|
|
||||||
|
|
||||||
/* Create a timer for some agent related event with id xid. */
|
/* Create a timer for some agent related event with id xid. */
|
||||||
err_code_t flexran_agent_create_timer(mid_t mod_id,
|
err_code_t flexran_agent_create_timer(mid_t mod_id,
|
||||||
uint32_t sf,
|
uint32_t sf,
|
||||||
uint32_t timer_type,
|
flexran_agent_timer_type_t timer_type,
|
||||||
xid_t xid,
|
xid_t xid,
|
||||||
flexran_agent_timer_callback_t cb,
|
flexran_agent_timer_callback_t cb,
|
||||||
void *timer_args);
|
Protocol__FlexranMessage *msg);
|
||||||
|
|
||||||
/* Destroy all existing timers */
|
/* Destroy all existing timers */
|
||||||
err_code_t flexran_agent_destroy_timers(void);
|
err_code_t flexran_agent_destroy_timers(mid_t mod_id);
|
||||||
|
|
||||||
/* Destroy the timer with the given timer_id */
|
|
||||||
err_code_t flexran_agent_destroy_timer(long timer_id);
|
|
||||||
|
|
||||||
/* Destroy the timer for task with id xid */
|
/* Destroy the timer for task with id xid */
|
||||||
err_code_t flexran_agent_destroy_timer_by_task_id(xid_t xid);
|
err_code_t flexran_agent_destroy_timer(mid_t mod_id, xid_t xid);
|
||||||
|
|
||||||
/* Stop a timer */
|
#endif /* _FLEXRAN_AGENT_TIMER_ */
|
||||||
err_code_t flexran_agent_stop_timer(long timer_id);
|
|
||||||
|
|
||||||
/* Restart the given timer */
|
|
||||||
err_code_t flexran_agent_restart_timer(long *timer_id);
|
|
||||||
|
|
||||||
/* Find the timer with the given timer_id */
|
|
||||||
struct flexran_agent_timer_element_s * get_timer_entry(long timer_id);
|
|
||||||
|
|
||||||
/* Obtain the protocol message stored in the given expired timer */
|
|
||||||
Protocol__FlexranMessage * flexran_agent_process_timeout(long timer_id, void* timer_args);
|
|
||||||
|
|
||||||
/* Comparator function comparing two timers. Decides the ordering of the timers */
|
|
||||||
int flexran_agent_compare_timer(struct flexran_agent_timer_element_s *a, struct flexran_agent_timer_element_s *b);
|
|
||||||
|
|
||||||
/* RB_PROTOTYPE is for .h files */
|
|
||||||
RB_PROTOTYPE(flexran_agent_map, flexran_agent_timer_element_s, entry, flexran_agent_compare_timer);
|
|
||||||
|
|||||||
@@ -988,6 +988,8 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
|||||||
if (flexran_agent_get_mac_xface(module_idP) && subframeP == 9) {
|
if (flexran_agent_get_mac_xface(module_idP) && subframeP == 9) {
|
||||||
flexran_agent_slice_update(module_idP);
|
flexran_agent_slice_update(module_idP);
|
||||||
}
|
}
|
||||||
|
if (flexran_agent_get_mac_xface(module_idP))
|
||||||
|
flexran_agent_get_mac_xface(module_idP)->flexran_agent_notify_tick(module_idP);
|
||||||
|
|
||||||
stop_meas(&(eNB->eNB_scheduler));
|
stop_meas(&(eNB->eNB_scheduler));
|
||||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER, VCD_FUNCTION_OUT);
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER, VCD_FUNCTION_OUT);
|
||||||
|
|||||||
Reference in New Issue
Block a user