Commit 117dc25a authored by Cedric Roux's avatar Cedric Roux

- Use itti timer API for NAS within MME

standalone NAS build OK

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4619 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent f4a685fa
...@@ -21,6 +21,7 @@ Description NAS procedure functions triggered by the network ...@@ -21,6 +21,7 @@ Description NAS procedure functions triggered by the network
#include "nas_network.h" #include "nas_network.h"
#include "commonDef.h" #include "commonDef.h"
#include "nas_log.h" #include "nas_log.h"
#include "nas_timer.h"
#include "as_message.h" #include "as_message.h"
#include "nas_proc.h" #include "nas_proc.h"
...@@ -62,6 +63,7 @@ void nas_network_initialize(void) ...@@ -62,6 +63,7 @@ void nas_network_initialize(void)
#ifdef NAS_MME #ifdef NAS_MME
/* Initialize the internal NAS processing data */ /* Initialize the internal NAS processing data */
# if defined(EPC_BUILD) # if defined(EPC_BUILD)
nas_timer_init();
nas_proc_initialize(mme_config_p); nas_proc_initialize(mme_config_p);
# else # else
nas_proc_initialize(); nas_proc_initialize();
......
/***************************************************************************** /*****************************************************************************
Eurecom OpenAirInterface 3 Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom Copyright(c) 2012 Eurecom
Source timer.c Source timer.c
Version 0.1 Version 0.1
Date 2012/10/09 Date 2012/10/09
Product NAS stack Product NAS stack
Subsystem Utilities Subsystem Utilities
Author Frederic Maurel Author Frederic Maurel
Description Timer utilities Description Timer utilities
*****************************************************************************/ *****************************************************************************/
#include <pthread.h>
#include <assert.h>
#include <signal.h>
#include <stdint.h>
#include <string.h> // memset
#include <time.h> // clock_gettime
#include <sys/time.h> // setitimer
#include <stdlib.h> // malloc, free
#if defined(NAS_MME) && defined(EPC_BUILD) #if defined(NAS_MME) && defined(EPC_BUILD)
# include "TIMER/timer.h" # include "intertask_interface.h"
# include "timer.h"
#endif #endif
#include "nas_timer.h" #include "nas_timer.h"
#include "commonDef.h" #include "commonDef.h"
#include <assert.h>
#include <pthread.h>
#include <signal.h>
#include <string.h> // memset
#include <time.h> // clock_gettime
#include <sys/time.h> // setitimer
#include <stdlib.h> // malloc, free
/****************************************************************************/ /****************************************************************************/
/**************** E X T E R N A L D E F I N I T I O N S ****************/ /**************** E X T E R N A L D E F I N I T I O N S ****************/
/****************************************************************************/ /****************************************************************************/
...@@ -48,11 +50,15 @@ Description Timer utilities ...@@ -48,11 +50,15 @@ Description Timer utilities
* value when the timer entry was allocated. * value when the timer entry was allocated.
*/ */
typedef struct { typedef struct {
struct timeval itv; /* Initial interval timer value */ #if !defined(EPC_BUILD)
struct timeval tv; /* Interval timer value */ pthread_t pid; /* Thread identifier of the callback */
nas_timer_callback_t cb; /* Callback executed at timer expiration */ #endif
void* args; /* Callback argument parameters */
pthread_t pid; /* Thread identifier of the callback */ struct timeval itv; /* Initial interval timer value */
struct timeval tv; /* Interval timer value */
nas_timer_callback_t cb; /* Callback executed at timer expiration */
void *args; /* Callback argument parameters */
} nas_timer_entry_t; } nas_timer_entry_t;
/* Structure of a timer queue - list of active interval timer entries /* Structure of a timer queue - list of active interval timer entries
...@@ -62,10 +68,10 @@ typedef struct { ...@@ -62,10 +68,10 @@ typedef struct {
* entry is removed from the queue and freed. * entry is removed from the queue and freed.
*/ */
typedef struct _nas_timer_queue_t { typedef struct _nas_timer_queue_t {
int id; /* Identifier of the current timer entry */ int id; /* Identifier of the current timer entry */
nas_timer_entry_t* entry; /* The current timer entry */ nas_timer_entry_t *entry; /* The current timer entry */
struct _nas_timer_queue_t* prev;/* The previous timer entry in the queue */ struct _nas_timer_queue_t *prev;/* The previous timer entry in the queue */
struct _nas_timer_queue_t* next;/* The next timer entry in the queue */ struct _nas_timer_queue_t *next;/* The next timer entry in the queue */
} timer_queue_t; } timer_queue_t;
/* Structure of a timer database /* Structure of a timer database
...@@ -74,49 +80,72 @@ typedef struct _nas_timer_queue_t { ...@@ -74,49 +80,72 @@ typedef struct _nas_timer_queue_t {
* startup and to maintain an ordered queue of active timer entries. * startup and to maintain an ordered queue of active timer entries.
*/ */
typedef struct { typedef struct {
int timer_id; /* Identifier of the first available timer entry */ int timer_id; /* Identifier of the first available timer entry */
#define TIMER_DATABASE_SIZE 256 #define TIMER_DATABASE_SIZE 256
timer_queue_t tq[TIMER_DATABASE_SIZE]; timer_queue_t tq[TIMER_DATABASE_SIZE];
timer_queue_t* head;/* Pointer to the first timer entry to be fired */ timer_queue_t *head;/* Pointer to the first timer entry to be fired */
#if !defined(EPC_BUILD)
pthread_mutex_t mutex; pthread_mutex_t mutex;
#endif
} nas_timer_database_t; } nas_timer_database_t;
/* /*
* The timer database * The timer database
*/ */
static nas_timer_database_t _nas_timer_db = {0, {}, NULL, PTHREAD_MUTEX_INITIALIZER}; static nas_timer_database_t _nas_timer_db = {
0,
{},
NULL
#if !defined(EPC_BUILD)
, PTHREAD_MUTEX_INITIALIZER
#endif
};
#if defined(EPC_BUILD)
#define nas_timer_lock_db()
#define nas_timer_unlock_db()
#else
#define nas_timer_lock_db() pthread_mutex_lock(&_nas_timer_db.mutex)
#define nas_timer_unlock_db() pthread_mutex_unlock(&_nas_timer_db.mutex)
#endif
/* /*
* The handler executed whenever the system timer expires * The handler executed whenever the system timer expires
*/ */
#if !defined(EPC_BUILD)
static void _nas_timer_handler(int signal); static void _nas_timer_handler(int signal);
#endif
/* /*
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
* Functions used to manage the timer database * Functions used to manage the timer database
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
*/ */
static void _nas_timer_db_init(void); static void _nas_timer_db_init(void);
static int _nas_timer_db_get_id(void); static int _nas_timer_db_get_id(void);
static int _nas_timer_db_is_active(int id); static int _nas_timer_db_is_active(int id);
static nas_timer_entry_t* _nas_timer_db_create_entry(long sec, nas_timer_callback_t cb, void* args); static nas_timer_entry_t *_nas_timer_db_create_entry(long sec,
nas_timer_callback_t cb, void *args);
static void _nas_timer_db_delete_entry(int id); static void _nas_timer_db_delete_entry(int id);
static void _nas_timer_db_insert_entry(int id, nas_timer_entry_t* te); static void _nas_timer_db_insert_entry(int id, nas_timer_entry_t *te);
static int _nas_timer_db_insert(timer_queue_t* entry); static int _nas_timer_db_insert(timer_queue_t *entry);
static nas_timer_entry_t* _nas_timer_db_remove_entry(int id); static nas_timer_entry_t *_nas_timer_db_remove_entry(int id);
static int _nas_timer_db_remove(timer_queue_t* entry); static int _nas_timer_db_remove(timer_queue_t *entry);
/* /*
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
* Operator functions for timeval structures * Operator functions for timeval structures
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
*/ */
static int _nas_timer_cmp(const struct timeval* a, const struct timeval* b); static int _nas_timer_cmp(const struct timeval *a, const struct timeval *b);
static void _nas_timer_add(const struct timeval* a, const struct timeval* b, struct timeval* result); static void _nas_timer_add(const struct timeval *a, const struct timeval *b,
static int _nas_timer_sub(const struct timeval* a, const struct timeval* b, struct timeval* result); struct timeval *result);
static int _nas_timer_sub(const struct timeval *a, const struct timeval *b,
struct timeval *result);
/****************************************************************************/ /****************************************************************************/
/****************** E X P O R T E D F U N C T I O N S ******************/ /****************** E X P O R T E D F U N C T I O N S ******************/
...@@ -124,16 +153,16 @@ static int _nas_timer_sub(const struct timeval* a, const struct timeval* b, stru ...@@ -124,16 +153,16 @@ static int _nas_timer_sub(const struct timeval* a, const struct timeval* b, stru
/**************************************************************************** /****************************************************************************
** ** ** **
** Name: timer_init() ** ** Name: timer_init() **
** ** ** **
** Description: Initializes internal data used to manage timers ** ** Description: Initializes internal data used to manage timers **
** ** ** **
** Inputs: None ** ** Inputs: None **
** Others: None ** ** Others: None **
** ** ** **
** Outputs: None ** ** Outputs: None **
** Return: RETURNok, RETURNerror ** ** Return: RETURNok, RETURNerror **
** Others: _nas_timer_db ** ** Others: _nas_timer_db **
** ** ** **
***************************************************************************/ ***************************************************************************/
int nas_timer_init(void) int nas_timer_init(void)
...@@ -141,6 +170,7 @@ int nas_timer_init(void) ...@@ -141,6 +170,7 @@ int nas_timer_init(void)
/* Initialize the timer database */ /* Initialize the timer database */
_nas_timer_db_init(); _nas_timer_db_init();
#if !defined(EPC_BUILD)
/* Setup the timer database handler */ /* Setup the timer database handler */
struct sigaction act; struct sigaction act;
...@@ -152,9 +182,9 @@ int nas_timer_init(void) ...@@ -152,9 +182,9 @@ int nas_timer_init(void)
(void) sigdelset (&act.sa_mask, SIGILL); (void) sigdelset (&act.sa_mask, SIGILL);
(void) sigdelset (&act.sa_mask, SIGTRAP); (void) sigdelset (&act.sa_mask, SIGTRAP);
(void) sigdelset (&act.sa_mask, SIGIOT); (void) sigdelset (&act.sa_mask, SIGIOT);
#ifndef LINUX # ifndef LINUX
(void) sigdelset (&act.sa_mask, SIGEMT); (void) sigdelset (&act.sa_mask, SIGEMT);
#endif # endif
(void) sigdelset (&act.sa_mask, SIGFPE); (void) sigdelset (&act.sa_mask, SIGFPE);
(void) sigdelset (&act.sa_mask, SIGBUS); (void) sigdelset (&act.sa_mask, SIGBUS);
(void) sigdelset (&act.sa_mask, SIGSEGV); (void) sigdelset (&act.sa_mask, SIGSEGV);
...@@ -162,112 +192,128 @@ int nas_timer_init(void) ...@@ -162,112 +192,128 @@ int nas_timer_init(void)
act.sa_handler = _nas_timer_handler; act.sa_handler = _nas_timer_handler;
if ( sigaction (SIGALRM, &act, 0) < 0 ) { if ( sigaction (SIGALRM, &act, 0) < 0 ) {
return (RETURNerror); return (RETURNerror);
} }
#endif
return (RETURNok); return (RETURNok);
} }
/**************************************************************************** /****************************************************************************
** ** ** **
** Name: timer_start() ** ** Name: timer_start() **
** ** ** **
** Description: Schedules the execution of the given callback function ** ** Description: Schedules the execution of the given callback function **
** upon expiration of the specified time interval ** ** upon expiration of the specified time interval **
** ** ** **
** Inputs: sec: The value of the time interval in seconds ** ** Inputs: sec: The value of the time interval in seconds **
** cb: Function executed upon timer expiration ** ** cb: Function executed upon timer expiration **
** args: Callback argument parameters ** ** args: Callback argument parameters **
** Others: None ** ** Others: None **
** ** ** **
** Outputs: None ** ** Outputs: None **
** Return: The timer identifier when successfully ** ** Return: The timer identifier when successfully **
** started; NAS_TIMER_INACTIVE_ID otherwise. ** ** started; NAS_TIMER_INACTIVE_ID otherwise. **
** Others: None ** ** Others: None **
** ** ** **
***************************************************************************/ ***************************************************************************/
int nas_timer_start(long sec, nas_timer_callback_t cb, void* args) int nas_timer_start(long sec, nas_timer_callback_t cb, void *args)
{ {
int id;
nas_timer_entry_t *te;
#if defined(EPC_BUILD)
int ret;
long timer_id;
#endif
/* Do not start null timer */ /* Do not start null timer */
if (sec == 0) { if (sec == 0) {
return (NAS_TIMER_INACTIVE_ID); return (NAS_TIMER_INACTIVE_ID);
} }
/* Get an identifier for the new timer entry */ /* Get an identifier for the new timer entry */
int id = _nas_timer_db_get_id(); id = _nas_timer_db_get_id();
if (id < 0) { if (id < 0) {
/* No available timer entry found */ /* No available timer entry found */
return (NAS_TIMER_INACTIVE_ID); return (NAS_TIMER_INACTIVE_ID);
} }
/* Create a new timer entry */ /* Create a new timer entry */
nas_timer_entry_t* te = _nas_timer_db_create_entry(sec, cb, args); te = _nas_timer_db_create_entry(sec, cb, args);
if (te == NULL) { if (te == NULL) {
return (NAS_TIMER_INACTIVE_ID); return (NAS_TIMER_INACTIVE_ID);
} }
/* Insert the new entry into the timer queue */ /* Insert the new entry into the timer queue */
_nas_timer_db_insert_entry(id, te); _nas_timer_db_insert_entry(id, te);
#if defined(EPC_BUILD)
ret = timer_setup(sec, 0, TASK_NAS, INSTANCE_DEFAULT, TIMER_PERIODIC, args, &timer_id);
if (ret == -1) {
return NAS_TIMER_INACTIVE_ID;
}
#endif
return (id); return (id);
} }
/**************************************************************************** /****************************************************************************
** ** ** **
** Name: timer_stop() ** ** Name: timer_stop() **
** ** ** **
** Description: Stop the timer with the specified identifier ** ** Description: Stop the timer with the specified identifier **
** ** ** **
** Inputs: id: The identifier of the timer to be stopped ** ** Inputs: id: The identifier of the timer to be stopped **
** Others: None ** ** Others: None **
** ** ** **
** Outputs: None ** ** Outputs: None **
** Return: NAS_TIMER_INACTIVE_ID when successfully stop- ** ** Return: NAS_TIMER_INACTIVE_ID when successfully stop- **
** ped; The timer identifier otherwise. ** ** ped; The timer identifier otherwise. **
** Others: None ** ** Others: None **
** ** ** **
***************************************************************************/ ***************************************************************************/
int nas_timer_stop(int id) int nas_timer_stop(int id)
{ {
/* Check if the timer entry is active */ /* Check if the timer entry is active */
if (_nas_timer_db_is_active(id)) { if (_nas_timer_db_is_active(id)) {
/* Remove the entry from the timer queue */ /* Remove the entry from the timer queue */
(void) _nas_timer_db_remove_entry(id); (void) _nas_timer_db_remove_entry(id);
/* Delete the timer entry */ /* Delete the timer entry */
_nas_timer_db_delete_entry(id); _nas_timer_db_delete_entry(id);
return (NAS_TIMER_INACTIVE_ID); return (NAS_TIMER_INACTIVE_ID);
} }
return (id); return (id);
} }
/**************************************************************************** /****************************************************************************
** ** ** **
** Name: timer_restart() ** ** Name: timer_restart() **
** ** ** **
** Description: Restart the timer with the specified identifier. The ti- ** ** Description: Restart the timer with the specified identifier. The ti- **
** mer is scheduled to expire after the same period of time ** ** mer is scheduled to expire after the same period of time **
** and will execute the callback function that has been set ** ** and will execute the callback function that has been set **
** when it was started. ** ** when it was started. **
** ** ** **
** Inputs: id: The identifier of the timer to be started ** ** Inputs: id: The identifier of the timer to be started **
** again ** ** again **
** Others: None ** ** Others: None **
** ** ** **
** Outputs: None ** ** Outputs: None **
** Return: The timer identifier when successfully ** ** Return: The timer identifier when successfully **
** re-started; NAS_TIMER_INACTIVE_ID otherwise. ** ** re-started; NAS_TIMER_INACTIVE_ID otherwise. **
** Others: None ** ** Others: None **
** ** ** **
***************************************************************************/ ***************************************************************************/
int nas_timer_restart(int id) int nas_timer_restart(int id)
{ {
/* Check if the timer entry is active */ /* Check if the timer entry is active */
if (_nas_timer_db_is_active(id)) { if (_nas_timer_db_is_active(id)) {
/* Remove the entry from the timer queue */ /* Remove the entry from the timer queue */
nas_timer_entry_t* te = _nas_timer_db_remove_entry(id); nas_timer_entry_t *te = _nas_timer_db_remove_entry(id);
/* Initialize its interval timer value */ /* Initialize its interval timer value */
te->tv = te->itv; te->tv = te->itv;
/* Insert again the entry into the timer queue */ /* Insert again the entry into the timer queue */
_nas_timer_db_insert_entry(id, te); _nas_timer_db_insert_entry(id, te);
return (id); return (id);
} }
return (NAS_TIMER_INACTIVE_ID); return (NAS_TIMER_INACTIVE_ID);
} }
...@@ -278,30 +324,39 @@ int nas_timer_restart(int id) ...@@ -278,30 +324,39 @@ int nas_timer_restart(int id)
/**************************************************************************** /****************************************************************************
** ** ** **
** Name: _nas_timer_handler() ** ** Name: _nas_timer_handler() **
** ** ** **
** Description: The timer handler is executed whenever the system deli- ** ** Description: The timer handler is executed whenever the system deli- **
** vers signal SIGALARM. It starts execution of the callback ** ** vers signal SIGALARM. It starts execution of the callback **
** function of the first entry within the queue of active ** ** function of the first entry within the queue of active **
** timer entries. The entry is not removed from the queue of ** ** timer entries. The entry is not removed from the queue of **
** active timer entries and shall be explicitly removed when ** ** active timer entries and shall be explicitly removed when **
** the timer expires. ** ** the timer expires. **
** ** ** **
** Inputs: None ** ** Inputs: None **
** Others: None ** ** Others: None **
** ** ** **
** Outputs: None ** ** Outputs: None **
** Return: None ** ** Return: None **
** Others: _nas_timer_db ** ** Others: _nas_timer_db **
** ** ** **
***************************************************************************/ ***************************************************************************/
#if defined(EPC_BUILD)
void nas_timer_handle_signal_expiry(long timer_id, void *arg_p)
{
/* Get the timer entry for which the system timer expired */
nas_timer_entry_t *te = _nas_timer_db.head->entry;
te->cb(te->args);
}
#else
static void _nas_timer_handler(int signal) static void _nas_timer_handler(int signal)
{ {
/* At least one timer has been started */ /* At least one timer has been started */
assert( (_nas_timer_db.head != NULL) && (_nas_timer_db.head->entry != NULL) ); assert( (_nas_timer_db.head != NULL) && (_nas_timer_db.head->entry != NULL) );
/* Get the timer entry for which the system timer expired */ /* Get the timer entry for which the system timer expired */
nas_timer_entry_t* te = _nas_timer_db.head->entry; nas_timer_entry_t *te = _nas_timer_db.head->entry;
/* Execute the callback function */ /* Execute the callback function */
pthread_attr_t attr; pthread_attr_t attr;
...@@ -313,54 +368,58 @@ static void _nas_timer_handler(int signal) ...@@ -313,54 +368,58 @@ static void _nas_timer_handler(int signal)
/* Wait for the thread to terminate before releasing the timer entry */ /* Wait for the thread to terminate before releasing the timer entry */
if (rc == 0) { if (rc == 0) {
void* result = NULL; void *result = NULL;
(void) pthread_join(te->pid, &result); (void) pthread_join(te->pid, &result);
/* TODO: Check returned result ??? */ /* TODO: Check returned result ??? */
if (result) free(result); if (result) {
free(result);
}
} }
} }
#endif
/* /*
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
* Functions used to manage the timer database * Functions used to manage the timer database
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
*/ */
/**************************************************************************** /****************************************************************************
** ** ** **
** Name: _nas_timer_db_init() ** ** Name: _nas_timer_db_init() **
** ** ** **
** Description: Initializes the timer database ** ** Description: Initializes the timer database **
** ** ** **
** Inputs: None ** ** Inputs: None **
** Others: None ** ** Others: None **
** ** ** **
** Outputs: None ** ** Outputs: None **
** Return: None ** ** Return: None **
** Others: _nas_timer_db ** ** Others: _nas_timer_db **
** ** ** **
***************************************************************************/ ***************************************************************************/
static void _nas_timer_db_init(void) static void _nas_timer_db_init(void)
{ {
for (int i = 0; i < TIMER_DATABASE_SIZE; i++) { int i;
_nas_timer_db.tq[i].id = NAS_TIMER_INACTIVE_ID; for (i = 0; i < TIMER_DATABASE_SIZE; i++) {
_nas_timer_db.tq[i].id = NAS_TIMER_INACTIVE_ID;
} }
} }
/**************************************************************************** /****************************************************************************
** ** ** **
** Name: _nas_timer_db_get_id() ** ** Name: _nas_timer_db_get_id() **
** ** ** **
** Description: Gets the identifier of the first available timer entry in ** ** Description: Gets the identifier of the first available timer entry in **
** the queue of active timer entries ** ** the queue of active timer entries **
** ** ** **
** Inputs: None ** ** Inputs: None **
** Others: _nas_timer_db ** ** Others: _nas_timer_db **
** ** ** **
** Outputs: None ** ** Outputs: None **
** Return: The identifier of the first available ** ** Return: The identifier of the first available **
** timer entry if the queue of active timers ** ** timer entry if the queue of active timers **
** is not full; -1 otherwise. ** ** is not full; -1 otherwise. **
** Others: _nas_timer_db ** ** Others: _nas_timer_db **
** ** ** **
***************************************************************************/ ***************************************************************************/
static int _nas_timer_db_get_id(void) static int _nas_timer_db_get_id(void)
...@@ -368,17 +427,17 @@ static int _nas_timer_db_get_id(void) ...@@ -368,17 +427,17 @@ static int _nas_timer_db_get_id(void)
int i; int i;
/* Search from the current timer entry to the last timer entry */ /* Search from the current timer entry to the last timer entry */
for (i = _nas_timer_db.timer_id; i < TIMER_DATABASE_SIZE; i++) { for (i = _nas_timer_db.timer_id; i < TIMER_DATABASE_SIZE; i++) {
if (_nas_timer_db.tq[i].id < 0 ) { if (_nas_timer_db.tq[i].id < 0 ) {
_nas_timer_db.timer_id = i+1; _nas_timer_db.timer_id = i+1;
return i; return i;
} }
} }
/* Search from the first timer entry to the current timer entry */ /* Search from the first timer entry to the current timer entry */
for (i = 0; i < _nas_timer_db.timer_id; i++) { for (i = 0; i < _nas_timer_db.timer_id; i++) {
if (_nas_timer_db.tq[i].id < 0 ) { if (_nas_timer_db.tq[i].id < 0 ) {
_nas_timer_db.timer_id = i+1; _nas_timer_db.timer_id = i+1;
return i; return i;
} }
} }
/* No available timer entry found */ /* No available timer entry found */
return (-1); return (-1);
...@@ -386,71 +445,71 @@ static int _nas_timer_db_get_id(void) ...@@ -386,71 +445,71 @@ static int _nas_timer_db_get_id(void)
/**************************************************************************** /****************************************************************************
** ** ** **
** Name: _nas_timer_db_is_active() ** ** Name: _nas_timer_db_is_active() **
** ** ** **
** Description: Checks whether the entry with the given identifier is ** ** Description: Checks whether the entry with the given identifier is **
** active within the queue of active timer entries ** ** active within the queue of active timer entries **
** ** ** **
** Inputs: id: Identifier of the timer entry to check ** ** Inputs: id: Identifier of the timer entry to check **
** Others: _nas_timer_db ** ** Others: _nas_timer_db **
** ** ** **
** Outputs: None ** ** Outputs: None **
** Return: TRUE if the timer entry is active; FALSE ** ** Return: TRUE if the timer entry is active; FALSE **
** if it is not an active timer entry. ** ** if it is not an active timer entry. **
** Others: None ** ** Others: None **
** ** ** **
***************************************************************************/ ***************************************************************************/
static int _nas_timer_db_is_active(int id) static int _nas_timer_db_is_active(int id)
{ {
return ( (id != NAS_TIMER_INACTIVE_ID) && return ( (id != NAS_TIMER_INACTIVE_ID) &&
(_nas_timer_db.tq[id].id != NAS_TIMER_INACTIVE_ID) ); (_nas_timer_db.tq[id].id != NAS_TIMER_INACTIVE_ID) );
} }
/**************************************************************************** /****************************************************************************
** ** ** **
** Name: _nas_timer_db_create_entry() ** ** Name: _nas_timer_db_create_entry() **
** ** ** **
** Description: Creates a new timer entry ** ** Description: Creates a new timer entry **
** ** ** **
** Inputs: sec: Time interval value ** ** Inputs: sec: Time interval value **
** cb: Function executed upon timer expiration ** ** cb: Function executed upon timer expiration **
** args: Callback argument parameters ** ** args: Callback argument parameters **
** Others: None ** ** Others: None **
** ** ** **
** Outputs: None ** ** Outputs: None **
** Return: A pointer to the new timer entry if ** ** Return: A pointer to the new timer entry if **
** successfully allocated; NULL otherwise ** ** successfully allocated; NULL otherwise **
** Others: None ** ** Others: None **
** ** ** **
***************************************************************************/ ***************************************************************************/
static nas_timer_entry_t* _nas_timer_db_create_entry( static nas_timer_entry_t *_nas_timer_db_create_entry(
long sec, nas_timer_callback_t cb, long sec, nas_timer_callback_t cb,
void* args) void *args)
{ {
nas_timer_entry_t* te = (nas_timer_entry_t*)malloc(sizeof(nas_timer_entry_t)); nas_timer_entry_t *te = (nas_timer_entry_t *)malloc(sizeof(nas_timer_entry_t));
if (te != NULL) { if (te != NULL) {
te->itv.tv_sec = sec; te->itv.tv_sec = sec;
te->itv.tv_usec = 0; te->itv.tv_usec = 0;
te->tv = te->itv; te->tv = te->itv;
te->cb = cb; te->cb = cb;
te->args = args; te->args = args;
} }
return (te); return (te);
} }
/**************************************************************************** /****************************************************************************
** ** ** **
** Name: _nas_timer_db_delete_entry() ** ** Name: _nas_timer_db_delete_entry() **
** ** ** **
** Description: Deletes the entry with the given identifier from the ti- ** ** Description: Deletes the entry with the given identifier from the ti- **
** mer database. ** ** mer database. **
** ** ** **
** Inputs: id: Identifier of the entry to be deleted ** ** Inputs: id: Identifier of the entry to be deleted **
** Others: None ** ** Others: None **
** ** ** **
** Outputs: None ** ** Outputs: None **
** Return: None ** ** Return: None **
** Others: _nas_timer_db ** ** Others: _nas_timer_db **
** ** ** **
***************************************************************************/ ***************************************************************************/
static void _nas_timer_db_delete_entry(int id) static void _nas_timer_db_delete_entry(int id)
...@@ -466,36 +525,38 @@ static void _nas_timer_db_delete_entry(int id) ...@@ -466,36 +525,38 @@ static void _nas_timer_db_delete_entry(int id)
/**************************************************************************** /****************************************************************************
** ** ** **
** Name: _nas_timer_db_insert_entry() ** ** Name: _nas_timer_db_insert_entry() **
** ** ** **
** Description: Inserts the entry with the given identifier into the ** ** Description: Inserts the entry with the given identifier into the **
** queue of active timer entries and restarts the system ** ** queue of active timer entries and restarts the system **
** timer if the new entry is the next entry for which the ** ** timer if the new entry is the next entry for which the **
** timer should be scheduled to expire. ** ** timer should be scheduled to expire. **
** ** ** **
** Inputs: id: Identifier of the new entry ** ** Inputs: id: Identifier of the new entry **
** te: Pointer to the entry to be inserted ** ** te: Pointer to the entry to be inserted **
** Others: None ** ** Others: None **
** ** ** **
** Outputs: None ** ** Outputs: None **
** Return: None ** ** Return: None **
** Others: _nas_timer_db ** ** Others: _nas_timer_db **
** ** ** **
***************************************************************************/ ***************************************************************************/
static void _nas_timer_db_insert_entry(int id, nas_timer_entry_t* te) static void _nas_timer_db_insert_entry(int id, nas_timer_entry_t *te)
{ {
struct itimerval it;
struct timespec ts;
struct timeval current_time;
int restart;
/* Enqueue the new timer entry */ /* Enqueue the new timer entry */
_nas_timer_db.tq[id].id = id; _nas_timer_db.tq[id].id = id;
_nas_timer_db.tq[id].entry = te; _nas_timer_db.tq[id].entry = te;
/* Save its interval timer value */ /* Save its interval timer value */
struct itimerval it;
it.it_interval.tv_sec = it.it_interval.tv_usec = 0; it.it_interval.tv_sec = it.it_interval.tv_usec = 0;
it.it_value = te->tv; it.it_value = te->tv;
/* Update its interval timer value */ /* Update its interval timer value */
struct timespec ts;
struct timeval current_time;
clock_gettime(CLOCK_MONOTONIC, &ts); clock_gettime(CLOCK_MONOTONIC, &ts);
current_time.tv_sec = ts.tv_sec; current_time.tv_sec = ts.tv_sec;
current_time.tv_usec = ts.tv_nsec/1000; current_time.tv_usec = ts.tv_nsec/1000;
...@@ -503,29 +564,33 @@ static void _nas_timer_db_insert_entry(int id, nas_timer_entry_t* te) ...@@ -503,29 +564,33 @@ static void _nas_timer_db_insert_entry(int id, nas_timer_entry_t* te)
_nas_timer_add(&te->tv, &current_time, &te->tv); _nas_timer_add(&te->tv, &current_time, &te->tv);
/* Insert the new timer entry into the list of active entries */ /* Insert the new timer entry into the list of active entries */
pthread_mutex_lock(&_nas_timer_db.mutex); nas_timer_lock_db();
int restart = _nas_timer_db_insert(&_nas_timer_db.tq[id]); restart = _nas_timer_db_insert(&_nas_timer_db.tq[id]);
pthread_mutex_unlock(&_nas_timer_db.mutex); nas_timer_unlock_db();
#if defined(EPC_BUILD)
if (restart) { if (restart) {
/* The new entry is the first entry of the list; /* The new entry is the first entry of the list;
* restart the system timer */ * restart the system timer */
setitimer(ITIMER_REAL, &it, 0); setitimer(ITIMER_REAL, &it, 0);
} }
#else
(void)(restart);
#endif
} }
static int _nas_timer_db_insert(timer_queue_t* entry) static int _nas_timer_db_insert(timer_queue_t *entry)
{ {
timer_queue_t *prev, *next; /* previous and next entry in the list */ timer_queue_t *prev, *next; /* previous and next entry in the list */
/* /*
* Search the list of timer entries for the first entry with an interval * Search the list of timer entries for the first entry with an interval
* timer value greater than the interval timer value of the new timer entry * timer value greater than the interval timer value of the new timer entry
*/ */
for (prev = NULL, next = _nas_timer_db.head; next != NULL; next = next->next) { for (prev = NULL, next = _nas_timer_db.head; next != NULL; next = next->next) {
if (_nas_timer_cmp(&next->entry->tv, &entry->entry->tv) > 0) { if (_nas_timer_cmp(&next->entry->tv, &entry->entry->tv) > 0) {
break; break;
} }
prev = next; prev = next;
} }
/* Insert the new entry in the list of active timer entries */ /* Insert the new entry in the list of active timer entries */
/* prev <-- entry --> next */ /* prev <-- entry --> next */
...@@ -533,18 +598,17 @@ static int _nas_timer_db_insert(timer_queue_t* entry) ...@@ -533,18 +598,17 @@ static int _nas_timer_db_insert(timer_queue_t* entry)
entry->next = next; entry->next = next;
/* Update the pointer from the previous entry */ /* Update the pointer from the previous entry */
if (entry->next != NULL) { if (entry->next != NULL) {
/* prev <-- entry <--> next */ /* prev <-- entry <--> next */
entry->next->prev = entry; entry->next->prev = entry;
} }
/* Update the pointer from the next entry */ /* Update the pointer from the next entry */
if (entry->prev != NULL) { if (entry->prev != NULL) {
/* prev <--> entry <--> next */ /* prev <--> entry <--> next */
entry->prev->next = entry; entry->prev->next = entry;
} } else {
else { /* The new entry is the first entry of the list */
/* The new entry is the first entry of the list */ _nas_timer_db.head = entry;
_nas_timer_db.head = entry; return TRUE;
return TRUE;
} }
/* The new entry is NOT the first entry of the list */ /* The new entry is NOT the first entry of the list */
return FALSE; return FALSE;
...@@ -552,87 +616,99 @@ static int _nas_timer_db_insert(timer_queue_t* entry) ...@@ -552,87 +616,99 @@ static int _nas_timer_db_insert(timer_queue_t* entry)
/**************************************************************************** /****************************************************************************
** ** ** **
** Name: _nas_timer_db_remove_entry() ** ** Name: _nas_timer_db_remove_entry() **
** ** ** **
** Description: Removes the entry with the given identifier from the ** ** Description: Removes the entry with the given identifier from the **
** queue of active timer entries and restarts the system ** ** queue of active timer entries and restarts the system **
** timer if the entry was the next entry for which the timer ** ** timer if the entry was the next entry for which the timer **
** was scheduled to expire. ** ** was scheduled to expire. **
** ** ** **
** Inputs: id: Identifier of the entry to be removed ** ** Inputs: id: Identifier of the entry to be removed **
** Others: None ** ** Others: None **
** ** ** **
** Outputs: None ** ** Outputs: None **
** Return: A pointer to the removed entry ** ** Return: A pointer to the removed entry **
** Others: _nas_timer_db ** ** Others: _nas_timer_db **
** ** ** **
***************************************************************************/ ***************************************************************************/
static nas_timer_entry_t* _nas_timer_db_remove_entry(int id) static nas_timer_entry_t *_nas_timer_db_remove_entry(int id)
{ {
int restart;
/* The identifier of the timer is valid within the timer queue */ /* The identifier of the timer is valid within the timer queue */
assert(_nas_timer_db.tq[id].id == id); assert(_nas_timer_db.tq[id].id == id);
/* Remove the timer entry from the list of active entries */ /* Remove the timer entry from the list of active entries */
pthread_mutex_lock(&_nas_timer_db.mutex); nas_timer_lock_db();
int restart = _nas_timer_db_remove(&_nas_timer_db.tq[id]); restart = _nas_timer_db_remove(&_nas_timer_db.tq[id]);
pthread_mutex_unlock(&_nas_timer_db.mutex); nas_timer_unlock_db();
if (restart) { if (restart) {
int rc; int rc;
/* The entry was the first entry of the list; /* The entry was the first entry of the list;
* the system timer needs to be restarted */ * the system timer needs to be restarted */
struct itimerval it; struct itimerval it;
it.it_interval.tv_sec = it.it_interval.tv_usec = 0; struct timeval tv;
struct timespec ts; struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
struct timeval time; it.it_interval.tv_sec = it.it_interval.tv_usec = 0;
time.tv_sec = ts.tv_sec;
time.tv_usec = ts.tv_nsec/1000; clock_gettime(CLOCK_MONOTONIC, &ts);
/* tv = tv - time() */
rc = _nas_timer_sub(&_nas_timer_db.head->entry->tv, &time, &it.it_value); tv.tv_sec = ts.tv_sec;
if (rc < 0) { tv.tv_usec = ts.tv_nsec/1000;
/* The system timer should has already expired */ /* tv = tv - time() */
_nas_timer_handler(SIGALRM); rc = _nas_timer_sub(&_nas_timer_db.head->entry->tv, &tv, &it.it_value);
}
else { #if defined(EPC_BUILD)
/* Restart the system timer */ (void)(rc);
setitimer(ITIMER_REAL, &it, 0); #else
} if (rc < 0) {
/* The system timer should have already expired */
_nas_timer_handler(SIGALRM);
} else {
/* Restart the system timer */
setitimer(ITIMER_REAL, &it, 0);
}
#endif
} }
/* Return a pointer to the removed entry */ /* Return a pointer to the removed entry */
return (_nas_timer_db.tq[id].entry); return (_nas_timer_db.tq[id].entry);
} }
static int _nas_timer_db_remove(timer_queue_t* entry) static int _nas_timer_db_remove(timer_queue_t *entry)
{ {
/* Update the pointer from the previous entry */ /* Update the pointer from the previous entry */
/* prev ---> entry ---> next */ /* prev ---> entry ---> next */
/* prev <--- entry <--- next */ /* prev <--- entry <--- next */
if (entry->next != NULL) { if (entry->next != NULL) {
/* prev ---> entry ---> next */ /* prev ---> entry ---> next */
/* prev <-------------- next */ /* prev <-------------- next */
entry->next->prev = entry->prev; entry->next->prev = entry->prev;
} }
/* Update the pointer from the next entry */ /* Update the pointer from the next entry */
if (entry->prev != NULL) { if (entry->prev != NULL) {
/* prev --------------> next */ /* prev --------------> next */
/* prev <-------------- next */ /* prev <-------------- next */
entry->prev->next = entry->next; entry->prev->next = entry->next;
} } else {
else { /* The entry was the first entry of the list */
/* The entry was the first entry of the list */ _nas_timer_db.head = entry->next;
_nas_timer_db.head = entry->next; if (_nas_timer_db.head != NULL) {
if (_nas_timer_db.head != NULL) { /* Other timers are scheduled to expire */
/* Other timers are scheduled to expire */ return TRUE;
return TRUE; }
} #if !defined(EPC_BUILD)
/* No more timer is scheduled to expire; stop the system timer */ {
struct itimerval it; /* No more timer is scheduled to expire; stop the system timer */
it.it_interval.tv_sec = it.it_interval.tv_usec = 0; struct itimerval it;
it.it_value.tv_sec = it.it_value.tv_usec = 0; it.it_interval.tv_sec = it.it_interval.tv_usec = 0;
setitimer(ITIMER_REAL, &it, 0); it.it_value.tv_sec = it.it_value.tv_usec = 0;
return FALSE; setitimer(ITIMER_REAL, &it, 0);
return FALSE;
}
#endif
} }
/* The entry was NOT the first entry of the list */ /* The entry was NOT the first entry of the list */
return FALSE; return FALSE;
...@@ -640,54 +716,55 @@ static int _nas_timer_db_remove(timer_queue_t* entry) ...@@ -640,54 +716,55 @@ static int _nas_timer_db_remove(timer_queue_t* entry)
/* /*
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
* Operator functions for timeval structures * Operator functions for timeval structures
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
*/ */
/**************************************************************************** /****************************************************************************
** ** ** **
** Name: _nas_timer_cmp() ** ** Name: _nas_timer_cmp() **
** ** ** **
** Description: Performs timeval comparaison ** ** Description: Performs timeval comparaison **
** ** ** **
** Inputs: a: The first timeval structure ** ** Inputs: a: The first timeval structure **
** b: The second timeval structure ** ** b: The second timeval structure **
** Others: None ** ** Others: None **
** ** ** **
** Outputs: None ** ** Outputs: None **
** Return: -1 if a < b; 1 if a > b; 0 if a == b ** ** Return: -1 if a < b; 1 if a > b; 0 if a == b **
** Others: None ** ** Others: None **
** ** ** **
***************************************************************************/ ***************************************************************************/
static int _nas_timer_cmp(const struct timeval* a, const struct timeval* b) static int _nas_timer_cmp(const struct timeval *a, const struct timeval *b)
{ {
if (a->tv_sec < b->tv_sec) if (a->tv_sec < b->tv_sec) {
return -1; return -1;
else if (a->tv_sec > b->tv_sec) } else if (a->tv_sec > b->tv_sec) {
return 1; return 1;
else if (a->tv_usec < b->tv_usec) } else if (a->tv_usec < b->tv_usec) {
return -1; return -1;
else if (a->tv_usec > b->tv_usec) } else if (a->tv_usec > b->tv_usec) {
return 1; return 1;
}
return 0; return 0;
} }
/**************************************************************************** /****************************************************************************
** ** ** **
** Name: _nas_timer_add() ** ** Name: _nas_timer_add() **
** ** ** **
** Description: Performs timeval addition ** ** Description: Performs timeval addition **
** ** ** **
** Inputs: a: The first timeval structure ** ** Inputs: a: The first timeval structure **
** b: The second timeval structure ** ** b: The second timeval structure **
** Others: None ** ** Others: None **
** ** ** **
** Outputs: result: result = timeval(a + b) ** ** Outputs: result: result = timeval(a + b) **
** Return: None ** ** Return: None **
** Others: None ** ** Others: None **
** ** ** **
***************************************************************************/ ***************************************************************************/
static void _nas_timer_add(const struct timeval* a, const struct timeval* b, static void _nas_timer_add(const struct timeval *a, const struct timeval *b,
struct timeval* result) struct timeval *result)
{ {
result->tv_sec = a->tv_sec + b->tv_sec; result->tv_sec = a->tv_sec + b->tv_sec;
result->tv_usec = a->tv_usec + b->tv_usec; result->tv_usec = a->tv_usec + b->tv_usec;
...@@ -699,30 +776,30 @@ static void _nas_timer_add(const struct timeval* a, const struct timeval* b, ...@@ -699,30 +776,30 @@ static void _nas_timer_add(const struct timeval* a, const struct timeval* b,
/**************************************************************************** /****************************************************************************
** ** ** **
** Name: _nas_timer_sub() ** ** Name: _nas_timer_sub() **
** ** ** **
** Description: Performs timeval substraction ** ** Description: Performs timeval substraction **
** ** ** **
** Inputs: a: The first timeval structure ** ** Inputs: a: The first timeval structure **
** b: The second timeval structure ** ** b: The second timeval structure **
** Others: None ** ** Others: None **
** ** ** **
** Outputs: result: a >= b, result = timeval(a - b) ** ** Outputs: result: a >= b, result = timeval(a - b) **
** Return: -1 if a < b; 0 otherwise ** ** Return: -1 if a < b; 0 otherwise **
** Others: None ** ** Others: None **
** ** ** **
***************************************************************************/ ***************************************************************************/
static int _nas_timer_sub(const struct timeval* a, const struct timeval* b, static int _nas_timer_sub(const struct timeval *a, const struct timeval *b,
struct timeval* result) struct timeval *result)
{ {
if (_nas_timer_cmp(a,b) > 0 ) { if (_nas_timer_cmp(a,b) > 0 ) {
result->tv_sec = a->tv_sec - b->tv_sec; result->tv_sec = a->tv_sec - b->tv_sec;
result->tv_usec = a->tv_usec - b->tv_usec; result->tv_usec = a->tv_usec - b->tv_usec;
if (result->tv_usec < 0) { if (result->tv_usec < 0) {
result->tv_sec--; result->tv_sec--;
result->tv_usec += 1000000; result->tv_usec += 1000000;
} }
return 0; return 0;
} }
return -1; return -1;
} }
......
/***************************************************************************** /*****************************************************************************
Eurecom OpenAirInterface 3 Eurecom OpenAirInterface 3
Copyright(c) 2012 Eurecom Copyright(c) 2012 Eurecom
Source timer.h Source timer.h
Version 0.1 Version 0.1
Date 2012/11/22 Date 2012/11/22
Product NAS stack Product NAS stack
Subsystem Utilities Subsystem Utilities
Author Frederic Maurel Author Frederic Maurel
Description Timer utilities Description Timer utilities
*****************************************************************************/ *****************************************************************************/
#ifndef __NAS_TIMER_H__ #ifndef __NAS_TIMER_H__
...@@ -28,7 +28,7 @@ Description Timer utilities ...@@ -28,7 +28,7 @@ Description Timer utilities
* Timer identifier returned when in inactive state (timer is stopped or has * Timer identifier returned when in inactive state (timer is stopped or has
* failed to be started) * failed to be started)
*/ */
#define NAS_TIMER_INACTIVE_ID (-1) #define NAS_TIMER_INACTIVE_ID (-1)
/****************************************************************************/ /****************************************************************************/
/************************ G L O B A L T Y P E S ************************/ /************************ G L O B A L T Y P E S ************************/
...@@ -36,12 +36,12 @@ Description Timer utilities ...@@ -36,12 +36,12 @@ Description Timer utilities
/* Timer structure */ /* Timer structure */
struct nas_timer_t { struct nas_timer_t {
int id; /* The timer identifier */ int id; /* The timer identifier */
long sec; /* The timer interval value in seconds */ long sec; /* The timer interval value in seconds */
}; };
/* Type of the callback executed when the timer expired */ /* Type of the callback executed when the timer expired */
typedef void* (*nas_timer_callback_t)(void*); typedef void *(*nas_timer_callback_t)(void *);
/****************************************************************************/ /****************************************************************************/
/******************** G L O B A L V A R I A B L E S ********************/ /******************** G L O B A L V A R I A B L E S ********************/
...@@ -51,16 +51,13 @@ typedef void* (*nas_timer_callback_t)(void*); ...@@ -51,16 +51,13 @@ typedef void* (*nas_timer_callback_t)(void*);
/****************** E X P O R T E D F U N C T I O N S ******************/ /****************** E X P O R T E D F U N C T I O N S ******************/
/****************************************************************************/ /****************************************************************************/
#if defined(NAS_MME) && defined(EPC_BUILD)
# define nas_timer_init
# define nas_timer_start
# define nas_timer_stop
# define nas_timer_restart
#else
int nas_timer_init(void); int nas_timer_init(void);
int nas_timer_start(long sec, nas_timer_callback_t cb, void* args); int nas_timer_start(long sec, nas_timer_callback_t cb, void *args);
int nas_timer_stop(int id); int nas_timer_stop(int id);
int nas_timer_restart(int id); int nas_timer_restart(int id);
#if defined(EPC_BUILD)
void nas_timer_handle_signal_expiry(long timer_id, void *arg_p);
#endif #endif
#endif /* __NAS_TIMER_H__ */ #endif /* __NAS_TIMER_H__ */
...@@ -370,6 +370,8 @@ libnas_ies_SRCS = \ ...@@ -370,6 +370,8 @@ libnas_ies_SRCS = \
libnas_utils_SRCS = \ libnas_utils_SRCS = \
EURECOM-NAS/src/util/nas_log.h \ EURECOM-NAS/src/util/nas_log.h \
EURECOM-NAS/src/util/nas_log.c \ EURECOM-NAS/src/util/nas_log.c \
EURECOM-NAS/src/util/nas_timer.h \
EURECOM-NAS/src/util/nas_timer.c \
EURECOM-NAS/src/util/TLVEncoder.h \ EURECOM-NAS/src/util/TLVEncoder.h \
EURECOM-NAS/src/util/TLVEncoder.c \ EURECOM-NAS/src/util/TLVEncoder.c \
EURECOM-NAS/src/util/TLVDecoder.h \ EURECOM-NAS/src/util/TLVDecoder.h \
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
# include "nas_proc.h" # include "nas_proc.h"
# include "emm_main.h" # include "emm_main.h"
# include "nas_log.h" # include "nas_log.h"
# include "nas_timer.h"
#endif #endif
#define NAS_ERROR(x, args...) do { fprintf(stderr, "[NAS] [E]"x, ##args); } while(0) #define NAS_ERROR(x, args...) do { fprintf(stderr, "[NAS] [E]"x, ##args); } while(0)
...@@ -133,6 +134,14 @@ next_message: ...@@ -133,6 +134,14 @@ next_message:
} break; } break;
#endif #endif
case TIMER_HAS_EXPIRED: {
#if !defined(DISABLE_USE_NAS)
/* Call the NAS timer api */
nas_timer_handle_signal_expiry(TIMER_HAS_EXPIRED(received_message_p).timer_id,
TIMER_HAS_EXPIRED(received_message_p).arg);
#endif
} break;
case TERMINATE_MESSAGE: { case TERMINATE_MESSAGE: {
itti_exit_task(); itti_exit_task();
} break; } break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment