diff --git a/openair1/PHY/TOOLS/time_meas.h b/openair1/PHY/TOOLS/time_meas.h
index a732af69db96832ab792108947a1c2d03d3601e1..2ab84307404fc89c3d031d544ca700906eab3266 100644
--- a/openair1/PHY/TOOLS/time_meas.h
+++ b/openair1/PHY/TOOLS/time_meas.h
@@ -37,6 +37,8 @@ typedef struct {
 
   long long in;
   long long diff;
+  long long p_time; /*!< \brief absolute process duration */
+  long long diff_square; /*!< \brief process duration square */
   long long max;
   int trials;
 } time_stats_t;
@@ -92,6 +94,9 @@ static inline void stop_meas(time_stats_t *ts) {
 #endif
       {
 	ts->diff += (out-ts->in);
+        /// process duration is the difference between two clock points
+        ts->p_time = (out-ts->in);
+        ts->diff_square += pow((out-ts->in),2);        
 	if ((out-ts->in) > ts->max)
 	  ts->max = out-ts->in;
 	
@@ -104,6 +109,8 @@ static inline void reset_meas(time_stats_t *ts) {
   if (opp_enabled){
     ts->trials=0;
     ts->diff=0;
+    ts->p_time=0;
+    ts->diff_square=0;    
     ts->max=0;
   }
 }
diff --git a/openair1/SIMULATION/LTE_PHY/Makefile b/openair1/SIMULATION/LTE_PHY/Makefile
index 1f3f8f8e3c7b5e75ec957ae94667e67dc598f4b4..4b471c768a3cdf129009ecb8daa9c5106f578347 100644
--- a/openair1/SIMULATION/LTE_PHY/Makefile
+++ b/openair1/SIMULATION/LTE_PHY/Makefile
@@ -130,6 +130,8 @@ $(LFDS_DIR)/bin/liblfds611.a:
 test: $(SIMULATION_OBJS) $(TOOLS_OBJS) $(TOP_DIR)/PHY/INIT/lte_init.o test.c
 	$(CC)  test.c -I$(TOP_DIR) -o test $(CFLAGS) $(SIMULATION_OBJS) $(TOOLS_OBJS) -lm 
 
+OBJ += $(LIST_OBJ) 
+OBJ += $(MEM_OBJ)
 $(OBJ) : %.o : %.c
 	@echo 
 	@echo Compiling $< ...
diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c
index 66e5c25d149ec2e3b6fbc3f81184ac244f652b9c..410290a0f4c00d37b9bc2b5333b02b1f981e0983 100644
--- a/openair1/SIMULATION/LTE_PHY/dlsim.c
+++ b/openair1/SIMULATION/LTE_PHY/dlsim.c
@@ -30,7 +30,7 @@
 /*! \file dlsim.c
  \brief Top-level DL simulator
  \author R. Knopp
- \date 2011
+ \date 2011 - 2014
  \version 0.1
  \company Eurecom
  \email: knopp@eurecom.fr
@@ -56,6 +56,7 @@
 
 #include "OCG_vars.h"
 #include "UTIL/LOG/log.h"
+#include "UTIL/LISTS/list.h"
 
 extern unsigned int dlsch_tbs25[27][25],TBStable[27][110];
 extern unsigned char offset_mumimo_llr_drange_fix;
@@ -85,6 +86,13 @@ PHY_VARS_eNB *PHY_vars_eNB;
 PHY_VARS_UE *PHY_vars_UE;
 
 int otg_enabled=0;
+/*the following parameters are used to control the processing times calculations*/
+double t_tx_max = -1000000000; /*!< \brief initial max process time for tx */
+double t_rx_max = -1000000000; /*!< \brief initial max process time for rx */
+double t_tx_min = 1000000000; /*!< \brief initial min process time for tx */
+double t_rx_min = 1000000000; /*!< \brief initial min process time for rx */
+int n_tx_dropped = 0; /*!< \brief initial max process time for tx */
+int n_rx_dropped = 0; /*!< \brief initial max process time for rx */
 
 void handler(int sig) {
   void *array[10];
@@ -1931,6 +1939,12 @@ int main(int argc, char **argv) {
       reset_meas(&PHY_vars_UE->dlsch_tc_ext_stats);
       reset_meas(&PHY_vars_UE->dlsch_tc_intl1_stats);
       reset_meas(&PHY_vars_UE->dlsch_tc_intl2_stats);
+      // initialization
+      struct list time_vector_tx;
+      initialize(&time_vector_tx);
+      struct list time_vector_rx;
+      initialize(&time_vector_rx);
+      
       for (trials = 0;trials<n_frames;trials++) {
 	//  printf("Trial %d\n",trials);
 	fflush(stdout);
@@ -3195,9 +3209,57 @@ PHY_vars_UE->lte_ue_pdcch_vars[0]->num_pdcch_symbols,
 
     
 	PHY_vars_UE->frame_rx++;
+ 
+	/* calculate the total processing time for each packet, 
+	 * get the max, min, and number of packets that exceed t>2000us
+	 */
+	double t_tx = (double)PHY_vars_eNB->phy_proc_tx.p_time/cpu_freq_GHz/1000.0;        
+	double t_rx = (double)PHY_vars_UE->phy_proc_rx.p_time/cpu_freq_GHz/1000.0;
+        if (t_tx > t_tx_max)
+	  t_tx_max = t_tx;
+        if (t_tx < t_tx_min)
+            t_tx_min = t_tx;
+        if (t_rx > t_rx_max)
+            t_rx_max = t_rx;
+        if (t_rx < t_rx_min)
+            t_rx_min = t_rx;
+        if (t_tx > 2000)
+            n_tx_dropped++;
+        if (t_rx > 2000)
+            n_rx_dropped++;
+        
+        push_front(&time_vector_tx, t_tx);
+        push_front(&time_vector_rx, t_rx);
       }   //trials
       // round_trials[0]: number of code word : goodput the protocol
-
+      double table_tx[time_vector_tx.size];
+      totable(table_tx, &time_vector_tx);
+ 
+      double table_rx[time_vector_rx.size];
+      totable(table_rx, &time_vector_rx);
+      
+      // sort table
+      qsort (table_tx, time_vector_tx.size, sizeof(double), &compare);
+      qsort (table_rx, time_vector_rx.size, sizeof(double), &compare);
+#ifdef DEBUG      
+      int n;
+      printf("The transmitter raw data: \n");
+      for (n=0; n< time_vector_tx.size; n++)
+          printf("%f ", table_tx[n]);
+      printf("\n");
+      printf("The receiver raw data: \n");
+      for (n=0; n< time_vector_rx.size; n++)
+          printf("%f ", table_rx[n]);
+      printf("\n");
+#endif       
+      double tx_median = table_tx[time_vector_tx.size/2];
+      double tx_q1 = table_tx[time_vector_tx.size/4];
+      double tx_q3 = table_tx[3*time_vector_tx.size/4];
+      
+      double rx_median = table_rx[time_vector_rx.size/2];
+      double rx_q1 = table_rx[time_vector_rx.size/4];
+      double rx_q3 = table_rx[3*time_vector_rx.size/4]; 
+      
       effective_rate = ((double)(round_trials[0]-dci_errors)/((double)round_trials[0] + round_trials[1] + round_trials[2] + round_trials[3]));
 
       printf("\n**********************SNR = %f dB (tx_lev %f, sigma2_dB %f)**************************\n",
@@ -3230,7 +3292,9 @@ PHY_vars_UE->lte_ue_pdcch_vars[0]->num_pdcch_symbols,
       
       if (print_perf==1) {
 	printf("eNB TX function statistics (per 1ms subframe)\n\n");
+	double std_phy_proc_tx = sqrt((double)PHY_vars_eNB->phy_proc_tx.diff_square/pow(cpu_freq_GHz,2)/pow(1000,2)/PHY_vars_eNB->phy_proc_tx.trials - pow((double)PHY_vars_eNB->phy_proc_tx.diff/PHY_vars_eNB->phy_proc_tx.trials/cpu_freq_GHz/1000,2));
 	printf("Total PHY proc tx                 :%f us (%d trials)\n",(double)PHY_vars_eNB->phy_proc_tx.diff/PHY_vars_eNB->phy_proc_tx.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->phy_proc_tx.trials);
+	printf("|__ Statistcs                          %f std: %fus max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n",std_phy_proc_tx, t_tx_max, t_tx_min, tx_median, tx_q1, tx_q3, n_tx_dropped);
 	printf("OFDM_mod time                     :%f us (%d trials)\n",(double)PHY_vars_eNB->ofdm_mod_stats.diff/PHY_vars_eNB->ofdm_mod_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->ofdm_mod_stats.trials);
 	printf("DLSCH modulation time             :%f us (%d trials)\n",(double)PHY_vars_eNB->dlsch_modulation_stats.diff/PHY_vars_eNB->dlsch_modulation_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->dlsch_modulation_stats.trials);
 	printf("DLSCH scrambling time             :%f us (%d trials)\n",(double)PHY_vars_eNB->dlsch_scrambling_stats.diff/PHY_vars_eNB->dlsch_scrambling_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->dlsch_scrambling_stats.trials);
@@ -3240,7 +3304,9 @@ PHY_vars_UE->lte_ue_pdcch_vars[0]->num_pdcch_symbols,
 	printf("|__ DLSCH sub-block interleaving time :%f us (%d trials)\n",((double)PHY_vars_eNB->dlsch_interleaving_stats.trials/PHY_vars_eNB->dlsch_encoding_stats.trials)*(double)PHY_vars_eNB->dlsch_interleaving_stats.diff/PHY_vars_eNB->dlsch_interleaving_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->dlsch_interleaving_stats.trials);
 
 	printf("\n\nUE RX function statistics (per 1ms subframe)\n\n");
-	printf("Total PHY proc rx                                   :%f us (%d trials)\n",(double)PHY_vars_UE->phy_proc_rx.diff/PHY_vars_UE->phy_proc_rx.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->phy_proc_rx.trials*2/3);
+	double std_phy_proc_rx = sqrt((double)PHY_vars_UE->phy_proc_rx.diff_square/pow(cpu_freq_GHz,2)/pow(1000,2)/PHY_vars_UE->phy_proc_rx.trials - pow((double)PHY_vars_UE->phy_proc_rx.diff/PHY_vars_UE->phy_proc_rx.trials/cpu_freq_GHz/1000,2));
+        printf("Total PHY proc rx                                   :%f us (%d trials)\n",(double)PHY_vars_UE->phy_proc_rx.diff/PHY_vars_UE->phy_proc_rx.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->phy_proc_rx.trials*2/3);
+	printf("|__Statistcs                                            std: %fus max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n", std_phy_proc_rx, t_rx_max, t_rx_min, rx_median, rx_q1, rx_q3, n_rx_dropped);
 	printf("DLSCH OFDM demodulation and channel_estimation time :%f us (%d trials)\n",(nsymb)*(double)PHY_vars_UE->ofdm_demod_stats.diff/PHY_vars_UE->ofdm_demod_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->ofdm_demod_stats.trials*2/3);
 	printf("|__ DLSCH rx dft                                        :%f us (%d trials)\n",(nsymb*PHY_vars_UE->lte_frame_parms.nb_antennas_rx)*(double)PHY_vars_UE->rx_dft_stats.diff/PHY_vars_UE->rx_dft_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->rx_dft_stats.trials*2/3);
 	printf("|__ DLSCH channel estimation time                       :%f us (%d trials)\n",(4.0)*(double)PHY_vars_UE->dlsch_channel_estimation_stats.diff/PHY_vars_UE->dlsch_channel_estimation_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->dlsch_channel_estimation_stats.trials*2/3);
diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c
index 19b5b37162bbbd43c1a0f64f6138ea75326574a6..3366c907e0f56d333a1e9e09c0defee127d177b7 100644
--- a/openair1/SIMULATION/LTE_PHY/ulsim.c
+++ b/openair1/SIMULATION/LTE_PHY/ulsim.c
@@ -30,7 +30,7 @@
 /*! \file ulsim.c
  \brief Top-level DL simulator
  \author R. Knopp
- \date 2011
+ \date 2011 - 2014
  \version 0.1
  \company Eurecom
  \email: knopp@eurecom.fr
@@ -87,11 +87,20 @@ extern uint16_t beta_ack[16],beta_ri[16],beta_cqi[16];
 //extern  char* namepointer_chMag ;
 
 
+
 #ifdef XFORMS
 FD_lte_phy_scope_enb *form_enb;
 char title[255];
 #endif
 
+/*the following parameters are used to control the processing times*/
+double t_tx_max = -1000000000; /*!< \brief initial max process time for tx */
+double t_rx_max = -1000000000; /*!< \brief initial max process time for rx */
+double t_tx_min = 1000000000; /*!< \brief initial min process time for tx */
+double t_rx_min = 1000000000; /*!< \brief initial min process time for tx */
+int n_tx_dropped = 0; /*!< \brief initial max process time for tx */
+int n_rx_dropped = 0; /*!< \brief initial max process time for rx */
+
 void lte_param_init(unsigned char N_tx, unsigned char N_rx,unsigned char transmission_mode,uint8_t extended_prefix_flag,uint8_t N_RB_DL,uint8_t frame_type,uint8_t tdd_config,uint8_t osf) {
 
   LTE_DL_FRAME_PARMS *lte_frame_parms;
@@ -895,6 +904,12 @@ int main(int argc, char **argv) {
       reset_meas(&PHY_vars_eNB->ulsch_tc_intl1_stats);
       reset_meas(&PHY_vars_eNB->ulsch_tc_intl2_stats);
 
+      // initialization
+      struct list time_vector_tx;
+      initialize(&time_vector_tx);
+      struct list time_vector_rx;
+      initialize(&time_vector_rx);
+      
       for (trials = 0;trials<n_frames;trials++) {
 	//      printf("*");
 	//        PHY_vars_UE->frame++;
@@ -1270,8 +1285,53 @@ int main(int argc, char **argv) {
 #ifdef XFORMS
 	phy_scope_eNB(form_enb,PHY_vars_eNB,0);
 #endif       
+        /*calculate the total processing time for each packet, get the max, min, and number of packets that exceed t>3000us*/
+        double t_tx = (double)PHY_vars_UE->phy_proc_tx.p_time/cpu_freq_GHz/1000.0;        
+        double t_rx = (double)PHY_vars_eNB->phy_proc_rx.p_time/cpu_freq_GHz/1000.0;
+        if (t_tx > t_tx_max)
+            t_tx_max = t_tx;
+        if (t_tx < t_tx_min)
+            t_tx_min = t_tx;
+        if (t_rx > t_rx_max)
+            t_rx_max = t_rx;
+        if (t_rx < t_rx_min)
+            t_rx_min = t_rx;
+        if (t_tx > 2000)
+            n_tx_dropped++;
+        if (t_rx > 2000)
+            n_rx_dropped++;
+        
+        push_front(&time_vector_tx, t_tx);
+        push_front(&time_vector_rx, t_rx);
       }   //trials
+      double table_tx[time_vector_tx.size];
+      totable(table_tx, &time_vector_tx);
 
+      double table_rx[time_vector_rx.size];
+      totable(table_rx, &time_vector_rx);
+      
+      // sort table
+      qsort (table_tx, time_vector_tx.size, sizeof(double), &compare);
+      qsort (table_rx, time_vector_rx.size, sizeof(double), &compare);
+#ifdef DEBUG      
+      int n;
+      printf("The transmitter raw data: \n");
+      for (n=0; n< time_vector_tx.size; n++)
+          printf("%f ", table_tx[n]);
+      printf("\n");
+      printf("The receiver raw data: \n");
+      for (n=0; n< time_vector_rx.size; n++)
+          printf("%f ", table_rx[n]);
+      printf("\n");
+#endif       
+      double tx_median = table_tx[time_vector_tx.size/2];
+      double tx_q1 = table_tx[time_vector_tx.size/4];
+      double tx_q3 = table_tx[3*time_vector_tx.size/4];
+      
+      double rx_median = table_rx[time_vector_rx.size/2];
+      double rx_q1 = table_rx[time_vector_rx.size/4];
+      double rx_q3 = table_rx[3*time_vector_rx.size/4];
+      
       printf("\n**********rb: %d ***mcs : %d  *********SNR = %f dB (%f): TX %d dB (gain %f dB), N0W %f dB, I0 %d dB, delta_IF %d [ (%d,%d) dB / (%d,%d) dB ]**************************\n",
 	     nb_rb,mcs,SNR,SNR2,
 	     tx_lev_dB,
@@ -1334,7 +1394,9 @@ int main(int argc, char **argv) {
 
       if (dump_perf==1) {
 	printf("UE TX function statistics (per 1ms subframe)\n\n");
+        double std_phy_proc_tx = sqrt((double)PHY_vars_UE->phy_proc_tx.diff_square/pow(cpu_freq_GHz,2)/pow(1000,2)/PHY_vars_UE->phy_proc_tx.trials - pow((double)PHY_vars_UE->phy_proc_tx.diff/PHY_vars_UE->phy_proc_tx.trials/cpu_freq_GHz/1000,2));
 	printf("Total PHY proc tx                 :%f us (%d trials)\n",(double)PHY_vars_UE->phy_proc_tx.diff/PHY_vars_UE->phy_proc_tx.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->phy_proc_tx.trials);
+	printf("|__ Statistics                         std: %f us max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n",std_phy_proc_tx, t_tx_max, t_tx_min, tx_median, tx_q1, tx_q3, n_tx_dropped);
 	printf("OFDM_mod time                     :%f us (%d trials)\n",(double)PHY_vars_UE->ofdm_mod_stats.diff/PHY_vars_UE->ofdm_mod_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->ofdm_mod_stats.trials);
 	printf("ULSCH modulation time             :%f us (%d trials)\n",(double)PHY_vars_UE->ulsch_modulation_stats.diff/PHY_vars_UE->ulsch_modulation_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->ulsch_modulation_stats.trials);
 	printf("ULSCH encoding time               :%f us (%d trials)\n",(double)PHY_vars_UE->ulsch_encoding_stats.diff/PHY_vars_UE->ulsch_encoding_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->ulsch_encoding_stats.trials);
@@ -1345,8 +1407,12 @@ int main(int argc, char **argv) {
 	printf("|__ ULSCH multiplexing time           :%f us (%d trials)\n",((double)PHY_vars_UE->ulsch_multiplexing_stats.trials/PHY_vars_UE->ulsch_encoding_stats.trials)*(double)PHY_vars_UE->ulsch_multiplexing_stats.diff/PHY_vars_UE->ulsch_multiplexing_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_UE->ulsch_multiplexing_stats.trials);
 
 	printf("\n\neNB RX function statistics (per 1ms subframe)\n\n");
-	printf("Total PHY proc rx                                   :%f us (%d trials)\n",(double)PHY_vars_eNB->phy_proc_rx.diff/PHY_vars_eNB->phy_proc_rx.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->phy_proc_rx.trials);
+        double std_phy_proc_rx = sqrt((double)PHY_vars_eNB->phy_proc_rx.diff_square/pow(cpu_freq_GHz,2)/pow(1000,2)/PHY_vars_eNB->phy_proc_rx.trials - pow((double)PHY_vars_eNB->phy_proc_rx.diff/PHY_vars_eNB->phy_proc_rx.trials/cpu_freq_GHz/1000,2));
+        printf("Total PHY proc rx                  :%f us (%d trials)\n",(double)PHY_vars_eNB->phy_proc_rx.diff/PHY_vars_eNB->phy_proc_rx.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->phy_proc_rx.trials);
+	printf("|__ Statistcs                           std: %fus max: %fus min: %fus median %fus q1 %fus q3 %fus n_dropped: %d packet \n", std_phy_proc_rx, t_rx_max, t_rx_min, rx_median, rx_q1, rx_q3, n_rx_dropped);
+	
 	printf("OFDM_demod time                   :%f us (%d trials)\n",(double)PHY_vars_eNB->ofdm_demod_stats.diff/PHY_vars_eNB->ofdm_demod_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->ofdm_demod_stats.trials);
+
 	printf("ULSCH demodulation time           :%f us (%d trials)\n",(double)PHY_vars_eNB->ulsch_demodulation_stats.diff/PHY_vars_eNB->ulsch_demodulation_stats.trials/cpu_freq_GHz/1000.0,PHY_vars_eNB->ulsch_demodulation_stats.trials);
 	printf("ULSCH Decoding time (%.2f Mbit/s, avg iter %f)      :%f us (%d trials, max %f)\n",
 	       PHY_vars_UE->ulsch_ue[0]->harq_processes[harq_pid]->TBS/1000.0,(double)avg_iter/iter_trials,
diff --git a/openair2/UTIL/LISTS/list.c b/openair2/UTIL/LISTS/list.c
index e45478e07fdae706125cff10b02af4e539f8ac3e..44310192084c1c244311e0e4986e50365657c036 100755
--- a/openair2/UTIL/LISTS/list.c
+++ b/openair2/UTIL/LISTS/list.c
@@ -1,20 +1,39 @@
+/*******************************************************************************
+    OpenAirInterface 
+    Copyright(c) 1999 - 2014 Eurecom
 
-/*! \file pad_list.c
-* \brief list management primimtives
-* \author Mohamed Said MOSLI BOUKSIAA, Lionel GAUTHIER, Navid Nikaein
+    OpenAirInterface is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+
+    OpenAirInterface is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenAirInterface.The full GNU General Public License is 
+   included in this distribution in the file called "COPYING". If not, 
+   see <http://www.gnu.org/licenses/>.
+
+  Contact Information
+  OpenAirInterface Admin: openair_admin@eurecom.fr
+  OpenAirInterface Tech : openair_tech@eurecom.fr
+  OpenAirInterface Dev  : openair4g-devel@eurecom.fr
+  
+  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
+
+ *******************************************************************************/
+/*! \file list.c
+* \brief list management primimtives. It includes three implementations: (1) with mem_blocks, (2) standard list implementation (mem usage 314MB) (3) Linux Queue-based implementation (mem usage 394 MB)
+* \author  Navid Nikaein, Mohamed Said MOSLI BOUKSIAA, Lionel GAUTHIER
 * \date 2012 - 2014
 * \version 0.5
 * @ingroup util
 */
 
-/***************************************************************************
-                             list_t.c  -  description
-                             -------------------
-                             -------------------
-  AUTHOR  : Lionel GAUTHIER
-  COMPANY : EURECOM
-  EMAIL   : Lionel.Gauthier@eurecom.fr
- ***************************************************************************/
 #define LIST_C
 #define NULL 0
 
@@ -240,3 +259,165 @@ list_display (list_t * listP)
     //msg ("[SDU_MNGT][WARNING] display_cnt_list() : list is NULL\n");
   }
 }
+#ifndef LINUX_LIST
+/*! \fn void push_front(struct list* z, double val)
+* \brief this function pushes front new values in a predefined list.
+* \param z is the predefined list
+*       val is the new value to be pushed inside the list
+* \return
+*/
+void 
+push_front(struct list* z, double val) {
+
+	struct node* p = (struct node*) malloc(sizeof(struct node));
+
+	p->next = z->head;
+	p->val = val;
+	z->head = p;
+
+	z->size++;
+
+	return;
+		
+}
+
+/*! \fn void initialize(struct list* z)
+* \brief initialize a list structure.
+* \param z is the list
+* \return
+*/
+void 
+initialize(struct list* z) {
+	z->head = NULL;
+	z->size = 0;
+
+	return;
+}
+
+/*! \fn void del(struct list* z)
+* \brief delete a list structure.
+* \param z is the list
+* \return
+*/
+void 
+del(struct list* z) {
+	struct node* cur;
+	struct node* x = z->head;
+	
+	while(x) {
+		cur = x;
+		x = x->next;
+		free(cur);
+	}
+
+	z->head = NULL;
+	z->size = 0;
+
+	return; 
+}
+/*! \fn void totable(double* table, struct list* v)
+* \brief convert a list structure to a table.
+* \param table is a pointer to double table
+*        v is the list to be converted
+* \return
+*/
+void 
+totable(double* table, struct list* v) {
+	int i = 0;
+
+	struct node* x = v->head;
+
+	while(x) {
+		table[i] = x->val;
+		i++;
+		x = x->next;
+	}
+
+	return; 
+}
+/*! \fn int compare (const void * a, const void * b)
+* \brief compare the value of two parameters
+* \param a is a double, b is another double
+* \return 1 if a>b, -0 if a<b
+*/
+int compare (const void * a, const void * b)
+{
+  	double x = *(double*)a;
+	double y = *(double*)b;
+
+	return ( x > y );
+}
+#else
+// push an element to the head of the list
+void push_front(struct list* z, double val) {
+	struct entry* p = (struct entry*) malloc(sizeof(struct entry));
+	p->val = val;	
+
+	LIST_INSERT_HEAD(&z->head, p, entries);
+	z->size++;
+
+	return;
+		
+}
+
+
+// initialization 
+void initialize(struct list* z) {
+	LIST_INIT(&z->head);
+	z->size = 0;
+
+	return;
+}
+
+// delete
+void del(struct list* z) {
+	while (z->head.lh_first != NULL) {
+		free(z->head.lh_first);
+		LIST_REMOVE(z->head.lh_first, entries);
+	}
+	z->size = 0;
+
+	return; 
+}
+
+// convert the list to a table
+void totable(double* table, struct list* v) {
+	int i = 0;
+
+	struct entry* x;
+
+	for (x = v->head.lh_first; x != NULL; x = x->entries.le_next) {
+		table[i] = x->val;
+		i++;
+	}
+
+	return; 
+}
+
+int compare (const void * a, const void * b)
+{
+  	double x = *(double*)a;
+	double y = *(double*)b;
+
+	return ( x > y );
+}
+#endif
+
+/*! \fn int32_t calculate_median(struct list *loc_list)
+* \brief calculate the median of a list
+* \param loc_list is the list
+* \return the median value
+*/
+int32_t calculate_median(struct list *loc_list) {
+    int32_t median = 0;    
+    double* table = (double*) malloc(loc_list->size * sizeof(double));
+    totable(table, loc_list);
+    /// sort the table in ascending way
+    qsort (table, loc_list->size, sizeof(double), &compare);
+    /// median is the value at middle the sorted table
+    /// Q1 is the value at 1/4 the sorted table
+    /// Q3 is the value at 3/4 the sorted table
+    median = table[loc_list->size/2];
+    free(table);
+    return median;
+}
diff --git a/openair2/UTIL/LISTS/list.h b/openair2/UTIL/LISTS/list.h
index 36db0e0483baf0818f25406def5a2f30c71bc7b6..1c53af2bb8604b35978601a020c601be445cb26d 100755
--- a/openair2/UTIL/LISTS/list.h
+++ b/openair2/UTIL/LISTS/list.h
@@ -36,6 +36,9 @@
 #    endif
 //-----------------------------------------------------------------------------
 #include "platform_constants.h"
+#include<linux/types.h>
+#include<stdlib.h>
+#include<sys/queue.h>
 
 #define LIST_NAME_MAX_CHAR 32
 
@@ -75,5 +78,38 @@ public_list2( void         list2_add_head       (mem_block_t* , list2_t* );)
 public_list2( void         list2_add_tail       (mem_block_t* , list2_t* );)
 public_list2( void         list2_add_list       (list2_t* , list2_t* );)
 public_list2( void         list2_display        (list2_t* );)
+//-----------------------------------------------------------------------------      
+/* The following lists are used for sorting numbers */
+#ifndef LINUX_LIST       
+/*! \brief the node structure */           
+struct node {
+	struct node* next; /*!< \brief is a node pointer */ 
+	double val; /*!< \brief is a the value of a node pointer*/
+};
+//-----------------------------------------------------------------------------
+/*! \brief the list structure */           
+struct list {
+	struct node* head; /*!< \brief is a node pointer */
+	ssize_t size; /*!< \brief is the list size*/
+}; 
+#else
+//-----------------------------------------------------------------------------
+struct entry {
+        double val;
+        LIST_ENTRY(entry) entries;
+};
+//-----------------------------------------------------------------------------
+struct list {
+	LIST_HEAD(listhead, entry) head;
+	ssize_t size;
+};
+#endif
+//-----------------------------------------------------------------------------        
+public_list2( void   push_front  (struct list*, double); )
+public_list2( void   initialize  (struct list*);         )
+public_list2( void   del         (struct list*);         )
+public_list2( void   totable     (double*, struct list*);)
+public_list2( int compare (const void * a, const void * b);)
+public_list2( int32_t calculate_median(struct list *loc_list);)
 
 #endif