diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c
index 36eba0efe3f6dab43eca7b5eabb117e62bcdcf65..d55c2d058655d047be11ddef324104b5914aedf4 100644
--- a/targets/RT/USER/lte-enb.c
+++ b/targets/RT/USER/lte-enb.c
@@ -163,6 +163,163 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst
 void stop_eNB(int nb_inst);
 
 
+inline void thread_top_init(char *thread_name,
+			    uint64_t runtime,
+			    uint64_t deadline,
+			    uint64_t period) {
+
+  MSC_START_USE();
+
+#ifdef DEADLINE_SCHEDULER
+  struct sched_attr attr;
+
+  unsigned int flags = 0;
+
+  attr.size = sizeof(attr);
+  attr.sched_flags = 0;
+  attr.sched_nice = 0;
+  attr.sched_priority = 0;
+
+  attr.sched_policy   = SCHED_DEADLINE;
+  attr.sched_runtime  = runtime;
+  attr.sched_deadline = deadline;
+  attr.sched_period   = period; 
+
+  if (sched_setattr(0, &attr, flags) < 0 ) {
+    perror("[SCHED] eNB tx thread: sched_setattr failed\n");
+    return &eNB_thread_rxtx_status;
+  }
+
+  LOG_I( HW, "[SCHED] eNB RXn-TXnp4 deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() );
+
+#else //LOW_LATENCY
+  int policy, s, j;
+  struct sched_param sparam;
+  char cpu_affinity[1024];
+  cpu_set_t cpuset;
+
+  /* Set affinity mask to include CPUs 1 to MAX_CPUS */
+  /* CPU 0 is reserved for UHD threads */
+  /* CPU 1 is reserved for all RX_TX threads */
+  /* Enable CPU Affinity only if number of CPUs >2 */
+  CPU_ZERO(&cpuset);
+
+#ifdef CPU_AFFINITY
+  if (get_nprocs() > 2)
+  {
+    for (j = 1; j < get_nprocs(); j++)
+        CPU_SET(j, &cpuset);
+    s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
+    if (s != 0)
+    {
+      perror( "pthread_setaffinity_np");
+      exit_fun("Error setting processor affinity");
+    }
+  }
+#endif //CPU_AFFINITY
+
+  /* Check the actual affinity mask assigned to the thread */
+  s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
+  if (s != 0) {
+    perror( "pthread_getaffinity_np");
+    exit_fun("Error getting processor affinity ");
+  }
+  memset(cpu_affinity,0,sizeof(cpu_affinity));
+  for (j = 0; j < CPU_SETSIZE; j++)
+    if (CPU_ISSET(j, &cpuset)) {  
+      char temp[1024];
+      sprintf (temp, " CPU_%d", j);
+      strcat(cpu_affinity, temp);
+    }
+
+  memset(&sparam, 0, sizeof(sparam));
+  sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
+  policy = SCHED_FIFO ; 
+  
+  s = pthread_setschedparam(pthread_self(), policy, &sparam);
+  if (s != 0) {
+    perror("pthread_setschedparam : ");
+    exit_fun("Error setting thread priority");
+  }
+  
+  s = pthread_getschedparam(pthread_self(), &policy, &sparam);
+  if (s != 0) {
+    perror("pthread_getschedparam : ");
+    exit_fun("Error getting thread priority");
+  }
+
+  LOG_I(HW, "[SCHED][eNB] %s started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n",thread_name,sched_getcpu(),gettid(),
+                   (policy == SCHED_FIFO)  ? "SCHED_FIFO" :
+                   (policy == SCHED_RR)    ? "SCHED_RR" :
+                   (policy == SCHED_OTHER) ? "SCHED_OTHER" :
+                   "???",
+                   sparam.sched_priority, cpu_affinity );
+
+#endif //LOW_LATENCY
+
+  mlockall(MCL_CURRENT | MCL_FUTURE);
+
+}
+
+inline void wait_sync(char *thread_name) {
+
+  printf( "waiting for sync (%s)\n",thread_name);
+  pthread_mutex_lock( &sync_mutex );
+  
+  while (sync_var<0)
+    pthread_cond_wait( &sync_cond, &sync_mutex );
+  
+  pthread_mutex_unlock(&sync_mutex);
+  
+  printf( "got sync (%s)\n", thread_name);
+
+}
+
+inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) {
+
+  struct timespec wait;
+  
+  wait.tv_sec=0;
+  wait.tv_nsec=5000000L;
+
+  if (pthread_mutex_timedlock(mutex,&wait) != 0) {
+    LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name);
+    exit_fun("nothing to add");
+    return(-1);
+  }
+  
+  while (*instance_cnt < 0) {
+    // most of the time the thread is waiting here
+    // proc->instance_cnt_rxtx is -1
+    pthread_cond_wait(cond,mutex); // this unlocks mutex_rxtx while waiting and then locks it again
+  }
+
+  if (pthread_mutex_unlock(mutex) != 0) {
+    LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for %s\n",name);
+    exit_fun("nothing to add");
+    return(-1);
+  }
+  return(0);
+}
+
+inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char *name) {
+
+  if (pthread_mutex_lock(mutex) != 0) {
+    LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name);
+    exit_fun("nothing to add");
+    return(-1);
+  }
+  
+  *instance_cnt=*instance_cnt-1;
+  
+  if (pthread_mutex_unlock(mutex) != 0) {
+    LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for %s\n",name);
+    exit_fun("nothing to add");
+    return(-1);
+  }
+  return(0);
+}
+
 void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) {
      
   unsigned int aa,slot_offset, slot_offset_F;
@@ -419,135 +576,19 @@ static void* eNB_thread_rxtx( void* param ) {
   PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id];
   LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
 
-  FILE  *tx_time_file = NULL;
-  char tx_time_name[101];
+  char thread_name[100];
+
 
-  
-  if (opp_enabled == 1) {
-    snprintf(tx_time_name, 100,"/tmp/%s_tx_time_thread_sf", "eNB");
-    tx_time_file = fopen(tx_time_name,"w");
-  }
   // set default return value
   eNB_thread_rxtx_status = 0;
 
-  MSC_START_USE();
-
-#ifdef DEADLINE_SCHEDULER
-  struct sched_attr attr;
-
-  unsigned int flags = 0;
-  uint64_t runtime  = 850000 ;  
-  uint64_t deadline = 1   *  1000000 ; // each tx thread will finish within 1ms
-  uint64_t period   = 1   * 10000000; // each tx thread has a period of 10ms from the starting point
-
-  attr.size = sizeof(attr);
-  attr.sched_flags = 0;
-  attr.sched_nice = 0;
-  attr.sched_priority = 0;
-
-  attr.sched_policy   = SCHED_DEADLINE;
-  attr.sched_runtime  = runtime;
-  attr.sched_deadline = deadline;
-  attr.sched_period   = period; 
-
-  if (sched_setattr(0, &attr, flags) < 0 ) {
-    perror("[SCHED] eNB tx thread: sched_setattr failed\n");
-    return &eNB_thread_rxtx_status;
-  }
-
-  LOG_I( HW, "[SCHED] eNB RXn-TXnp4 deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() );
-
-#else //LOW_LATENCY
-  int policy, s, j;
-  struct sched_param sparam;
-  char cpu_affinity[1024];
-  cpu_set_t cpuset;
-  struct timespec wait;
-
-  wait.tv_sec=0;
-  wait.tv_nsec=5000000L;
-
-  /* Set affinity mask to include CPUs 1 to MAX_CPUS */
-  /* CPU 0 is reserved for UHD threads */
-  /* CPU 1 is reserved for all RX_TX threads */
-  /* Enable CPU Affinity only if number of CPUs >2 */
-  CPU_ZERO(&cpuset);
-
-#ifdef CPU_AFFINITY
-  if (get_nprocs() > 2)
-  {
-    for (j = 1; j < get_nprocs(); j++)
-        CPU_SET(j, &cpuset);
-    s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
-    if (s != 0)
-    {
-      perror( "pthread_setaffinity_np");
-      exit_fun("Error setting processor affinity");
-    }
-  }
-#endif //CPU_AFFINITY
-
-  /* Check the actual affinity mask assigned to the thread */
-  s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
-  if (s != 0) {
-    perror( "pthread_getaffinity_np");
-    exit_fun("Error getting processor affinity ");
-  }
-  memset(cpu_affinity,0,sizeof(cpu_affinity));
-  for (j = 0; j < CPU_SETSIZE; j++)
-    if (CPU_ISSET(j, &cpuset)) {  
-      char temp[1024];
-      sprintf (temp, " CPU_%d", j);
-      strcat(cpu_affinity, temp);
-    }
-
-  memset(&sparam, 0, sizeof(sparam));
-  sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
-  policy = SCHED_FIFO ; 
-  
-  s = pthread_setschedparam(pthread_self(), policy, &sparam);
-  if (s != 0) {
-    perror("pthread_setschedparam : ");
-    exit_fun("Error setting thread priority");
-  }
-  
-  s = pthread_getschedparam(pthread_self(), &policy, &sparam);
-  if (s != 0) {
-    perror("pthread_getschedparam : ");
-    exit_fun("Error getting thread priority");
-  }
-
-  LOG_I(HW, "[SCHED][eNB] RXn_TXnp4 thread started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n",sched_getcpu(),gettid(),
-                   (policy == SCHED_FIFO)  ? "SCHED_FIFO" :
-                   (policy == SCHED_RR)    ? "SCHED_RR" :
-                   (policy == SCHED_OTHER) ? "SCHED_OTHER" :
-                   "???",
-                   sparam.sched_priority, cpu_affinity );
-
-#endif //LOW_LATENCY
-
-  mlockall(MCL_CURRENT | MCL_FUTURE);
+  sprintf(thread_name,"RXn_TXnp4_%d\n",&eNB->proc.proc_rxtx[0] == proc ? 0 : 1);
+  thread_top_init(thread_name,850000L,1000000L,2000000L);
 
   while (!oai_exit) {
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
 
-    if (pthread_mutex_timedlock(&proc->mutex_rxtx,&wait) != 0) {
-      LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB RXn-TXnp4\n");
-      exit_fun("nothing to add");
-      break;
-    }
-
-    while (proc->instance_cnt_rxtx < 0) {
-      // most of the time the thread is waiting here
-      // proc->instance_cnt_rxtx is -1
-      pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx ); // this unlocks mutex_rxtx while waiting and then locks it again
-    }
-
-    if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
-      LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB TX\n");
-      exit_fun("nothing to add");
-      break;
-    }
+    if (wait_on_condition(&proc->mutex_rxtx,&proc->cond_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break;
 
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 1 );
 
@@ -583,33 +624,10 @@ static void* eNB_thread_rxtx( void* param ) {
       
     }
 
-
-    if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
-      LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc\n");
-      exit_fun("nothing to add");
-      break;
-    }
-
-    proc->instance_cnt_rxtx--;
-
-    if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
-      LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB TX proc\n");
-      exit_fun("nothing to add");
-      break;
-    }
+    if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break;
 
     stop_meas( &softmodem_stats_rxtx_sf );
-
-    if (opp_enabled){
-      
-#ifdef DEADLINE_SCHEDULER
-      if(softmodem_stats_rxtx_sf.diff_now/(cpuf) > attr.sched_runtime){
-	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB, (softmodem_stats_rxtx_sf.diff_now/cpuf - attr.sched_runtime)/1000000.0);
-      }
-#endif 
-    }    
-    print_meas_now(&softmodem_stats_rxtx_sf,"eNB_TX_SF",tx_time_file);
-  }
+  } // while !oai_exit
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
 
@@ -795,125 +813,20 @@ static void* eNB_thread_asynch_rxtx( void* param ) {
 
   eNB_proc_t *proc = (eNB_proc_t*)param;
   PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id];
-  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
-
-  int subframe=0, frame=0; 
-
-
-#ifdef DEADLINE_SCHEDULER
-  struct sched_attr attr;
-  unsigned int flags = 0;
-  uint64_t runtime  = 870000 ;
-  uint64_t deadline = 1   *  1000000;
-  uint64_t period   = 1   * 10000000; // each rx thread has a period of 10ms from the starting point
- 
-  attr.size = sizeof(attr);
-  attr.sched_flags = 0;
-  attr.sched_nice = 0;
-  attr.sched_priority = 0;
-
-  attr.sched_policy = SCHED_DEADLINE;
-  attr.sched_runtime  = runtime;
-  attr.sched_deadline = deadline;
-  attr.sched_period   = period; 
-
-  if (sched_setattr(0, &attr, flags) < 0 ) {
-    perror("[SCHED] eNB FH sched_setattr failed\n");
-    return &eNB_thread_asynch_rx_status;
-  }
-
-  LOG_I( HW, "[SCHED] eNB asynch RX deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() );
-#else // LOW_LATENCY
-  int policy, s, j;
-  struct sched_param sparam;
-  char cpu_affinity[1024];
-  cpu_set_t cpuset;
-
-  /* Set affinity mask to include CPUs 1 to MAX_CPUS */
-  /* CPU 0 is reserved for UHD */
-  /* CPU 1 is reserved for all TX threads */
-  /* CPU 2..MAX_CPUS is reserved for all RX threads */
-  /* Set CPU Affinity only if number of CPUs >2 */
-  CPU_ZERO(&cpuset);
-#ifdef CPU_AFFINITY
-  if (get_nprocs() >2) {
-    for (j = 1; j < get_nprocs(); j++)
-      CPU_SET(j, &cpuset);
-  
-    s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
-    if (s != 0) {
-      perror( "pthread_setaffinity_np");  
-      exit_fun (" Error setting processor affinity :");
-    }
-  }
-#endif //CPU_AFFINITY
-  /* Check the actual affinity mask assigned to the thread */
-
-  s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
-  if (s != 0) {
-    perror ("pthread_getaffinity_np");
-    exit_fun (" Error getting processor affinity :");
-  }
-  memset(cpu_affinity,0, sizeof(cpu_affinity));
 
-  for (j = 0; j < CPU_SETSIZE; j++)
-    if (CPU_ISSET(j, &cpuset)) {  
-      char temp[1024];
-      sprintf (temp, " CPU_%d", j);
-      strcat(cpu_affinity, temp);
-    }
-
-  memset(&sparam, 0 , sizeof (sparam)); 
-  sparam.sched_priority = sched_get_priority_max(SCHED_FIFO);
-
-  policy = SCHED_FIFO ; 
-  s = pthread_setschedparam(pthread_self(), policy, &sparam);
-  if (s != 0) {
-    perror("pthread_setschedparam : ");
-    exit_fun("Error setting thread priority");     
-  }
-
-  memset(&sparam, 0 , sizeof (sparam));
-
-  s = pthread_getschedparam(pthread_self(), &policy, &sparam);
-  if (s != 0) {
-    perror("pthread_getschedparam");
-    exit_fun("Error getting thread priority");
-  }
-
-  LOG_I(HW, "[SCHED][eNB] eNB asynch RX thread started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(),
-	 (policy == SCHED_FIFO)  ? "SCHED_FIFO" :
-	 (policy == SCHED_RR)    ? "SCHED_RR" :
-	 (policy == SCHED_OTHER) ? "SCHED_OTHER" :
-	 "???",
-	 sparam.sched_priority, cpu_affinity);
-  
-  
-#endif // DEADLINE_SCHEDULER
 
+  int subframe=0, frame=0; 
 
-  mlockall(MCL_CURRENT | MCL_FUTURE);
+  thread_top_init("thread_asynch",870000L,1000000L,1000000L);
 
   // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe
-  printf( "waiting for sync (eNB_thread_asynch_rx)\n");
-  pthread_mutex_lock( &sync_mutex );
-
-  while (sync_var<0)
-    pthread_cond_wait( &sync_cond, &sync_mutex );
- 
-  pthread_mutex_unlock(&sync_mutex);
- 
-  printf( "got sync (eNB_thread_asynch_rx)\n" );
 
+  wait_sync("thread_asynch");
 
   // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe
   printf( "waiting for devices (eNB_thread_asynch_rx)\n");
-  pthread_mutex_lock( &proc->mutex_asynch_rxtx);
 
-  while (proc->instance_cnt_asynch_rxtx<0)
-    pthread_cond_wait( &proc->cond_asynch_rxtx, &proc->mutex_asynch_rxtx );
- 
-  pthread_mutex_unlock(&proc->mutex_asynch_rxtx);
+  wait_on_condition(&proc->mutex_asynch_rxtx,&proc->cond_asynch_rxtx,&proc->instance_cnt_asynch_rxtx,"thread_asynch");
 
   printf( "devices ok (eNB_thread_asynch_rx)\n");
 
@@ -1105,17 +1018,11 @@ void rx_fh_slave(PHY_VARS_eNB *eNB,int *frame,int *subframe) {
   // it just waits for an external event.  The actual rx_rh is handle by the asynchronous RX thread
   eNB_proc_t *proc=&eNB->proc;
 
-  if (pthread_mutex_lock(&proc->mutex_FH) != 0) {
-    LOG_E( PHY, "[SCHED][eNB] error locking mutex for FH Slave\n");
-    exit_fun( "error locking mutex" );
-  }
-  
-  while (proc->instance_cnt_FH < 0) {
-    pthread_cond_wait( &proc->cond_FH,&proc->mutex_FH ); 
-  }      
-  proc->instance_cnt_FH++;
-  
-  pthread_mutex_unlock( &proc->mutex_FH );
+  if (wait_on_condition(&proc->mutex_FH,&proc->cond_FH,&proc->instance_cnt_FH,"rx_fh_slave") < 0)
+    return;
+
+  release_thread(&proc->mutex_FH,&proc->instance_cnt_FH,"rx_fh_slave");
+
   
 }
 
@@ -1219,6 +1126,7 @@ void wakeup_slaves(eNB_proc_t *proc) {
  * \param param is a \ref eNB_proc_t structure which contains the info what to process.
  * \returns a pointer to an int. The storage is not on the heap and must not be freed.
  */
+
 static void* eNB_thread_FH( void* param ) {
   
   static int eNB_thread_FH_status;
@@ -1227,131 +1135,20 @@ static void* eNB_thread_FH( void* param ) {
   PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id];
   LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
 
-  FILE  *rx_time_file = NULL;
-  char rx_time_name[101];
-
   int subframe=0, frame=0; 
 
-  if (opp_enabled == 1) {
-    snprintf(rx_time_name, 100,"/tmp/%s_rx_time_thread_sf", "eNB");
-    rx_time_file = fopen(rx_time_name,"w");
-  }
   // set default return value
   eNB_thread_FH_status = 0;
 
-  MSC_START_USE();
-
-#ifdef DEADLINE_SCHEDULER
-  struct sched_attr attr;
-  unsigned int flags = 0;
-  uint64_t runtime  = 870000 ;
-  uint64_t deadline = 1   *  1000000;
-  uint64_t period   = 1   * 10000000; // each rx thread has a period of 10ms from the starting point
- 
-  attr.size = sizeof(attr);
-  attr.sched_flags = 0;
-  attr.sched_nice = 0;
-  attr.sched_priority = 0;
-
-  attr.sched_policy = SCHED_DEADLINE;
-  attr.sched_runtime  = runtime;
-  attr.sched_deadline = deadline;
-  attr.sched_period   = period; 
-
-  if (sched_setattr(0, &attr, flags) < 0 ) {
-    perror("[SCHED] eNB FH sched_setattr failed\n");
-    return &eNB_thread_FH_status;
-  }
-
-  LOG_I( HW, "[SCHED] eNB FH deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() );
-#else // LOW_LATENCY
-  int policy, s, j;
-  struct sched_param sparam;
-  char cpu_affinity[1024];
-  cpu_set_t cpuset;
-
-  /* Set affinity mask to include CPUs 1 to MAX_CPUS */
-  /* CPU 0 is reserved for UHD */
-  /* CPU 1 is reserved for all TX threads */
-  /* CPU 2..MAX_CPUS is reserved for all RX threads */
-  /* Set CPU Affinity only if number of CPUs >2 */
-  CPU_ZERO(&cpuset);
-#ifdef CPU_AFFINITY
-  if (get_nprocs() >2) {
-    for (j = 1; j < get_nprocs(); j++)
-      CPU_SET(j, &cpuset);
-  
-    s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
-    if (s != 0) {
-      perror( "pthread_setaffinity_np");  
-      exit_fun (" Error setting processor affinity :");
-    }
-  }
-#endif //CPU_AFFINITY
-  /* Check the actual affinity mask assigned to the thread */
-
-  s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
-  if (s != 0) {
-    perror ("pthread_getaffinity_np");
-    exit_fun (" Error getting processor affinity :");
-  }
-  memset(cpu_affinity,0, sizeof(cpu_affinity));
-
-  for (j = 0; j < CPU_SETSIZE; j++)
-    if (CPU_ISSET(j, &cpuset)) {  
-      char temp[1024];
-      sprintf (temp, " CPU_%d", j);
-      strcat(cpu_affinity, temp);
-    }
-
-  memset(&sparam, 0 , sizeof (sparam)); 
-  sparam.sched_priority = sched_get_priority_max(SCHED_FIFO);
-
-  policy = SCHED_FIFO ; 
-  s = pthread_setschedparam(pthread_self(), policy, &sparam);
-  if (s != 0) {
-    perror("pthread_setschedparam : ");
-    exit_fun("Error setting thread priority");     
-  }
-
-  memset(&sparam, 0 , sizeof (sparam));
+  thread_top_init("eNB_thread_FH",870000,1000000,1000000);
 
-  s = pthread_getschedparam(pthread_self(), &policy, &sparam);
-  if (s != 0) {
-    perror("pthread_getschedparam");
-    exit_fun("Error getting thread priority");
-  }
+  wait_sync("eNB_thread_FH");
 
-  LOG_I(HW, "[SCHED][eNB] FH thread started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(),
-	 (policy == SCHED_FIFO)  ? "SCHED_FIFO" :
-	 (policy == SCHED_RR)    ? "SCHED_RR" :
-	 (policy == SCHED_OTHER) ? "SCHED_OTHER" :
-	 "???",
-	 sparam.sched_priority, cpu_affinity);
-  
-  
-#endif // DEADLINE_SCHEDULER
-
-
-  mlockall(MCL_CURRENT | MCL_FUTURE);
-
-  // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe
-  printf( "waiting for sync (eNB_thread_FH)\n");
-  pthread_mutex_lock( &sync_mutex );
-
-  while (sync_var<0)
-    pthread_cond_wait( &sync_cond, &sync_mutex );
- 
-  pthread_mutex_unlock(&sync_mutex);
- 
-  printf( "got sync (eNB_thread_FH)\n" );
- 
 #if defined(ENABLE_ITTI)
   if (eNB->node_function < NGFI_RRU_IF5)
     wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB);
 #endif 
 
-
   // Start IF device if any
   if (eNB->start_if) 
     if (eNB->start_if(eNB) != 0)
@@ -1362,7 +1159,7 @@ static void* eNB_thread_FH( void* param ) {
     if (eNB->start_rf(eNB) != 0)
       LOG_E(HW,"Could not start the RF device\n");
 
-  // wakeup asnych_rxtx thread
+  // wakeup asnych_rxtx thread because the devices are ready at this point
   pthread_mutex_lock(&proc->mutex_asynch_rxtx);
   proc->instance_cnt_asynch_rxtx=0;
   pthread_mutex_unlock(&proc->mutex_asynch_rxtx);
@@ -1371,10 +1168,8 @@ static void* eNB_thread_FH( void* param ) {
   // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices
   while (!oai_exit) {
 
-    if (oai_exit) break;   
-
-
-    // this is to check that we are in synch with the fronthaul timing
+    // these are local subframe/frame counters to check that we are in synch with the fronthaul timing.
+    // They are set on the first rx/tx in the underly FH routines.
     if (subframe==9) { 
       subframe=0;
       frame++;
@@ -1399,30 +1194,7 @@ static void* eNB_thread_FH( void* param ) {
     if (wakeup_rxtx(proc,&proc->proc_rxtx[proc->subframe_rx&1],fp) < 0)
       break;
 
-    stop_meas( &softmodem_stats_rxtx_sf );
-#ifdef DEADLINE_SCHEDULER
-    if (opp_enabled){
-      if(softmodem_stats_rxtx_sf.diff_now/(cpuf) > attr.sched_runtime) {
-        VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RXTX_ENB, (softmodem_stats_rxtx_sf.diff_now/cpuf - attr.sched_runtime)/1000000.0);
-      }
-    }
-#endif // DEADLINE_SCHEDULER  
-    print_meas_now(&softmodem_stats_rx_sf,"eNB_RX_SF", rx_time_file);
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
-    
-    print_meas_now(&softmodem_stats_rx_sf,"eNB_RX_SF", rx_time_file);
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
-  
- 
-    if (eNB->node_timing == synch_to_ext_device) {
-      proc->instance_cnt_FH--;
-      
-      if (pthread_mutex_unlock(&proc->mutex_FH) != 0) {
-	LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for FH\n");
-	exit_fun( "error unlocking mutex" );
-      }
-    }
-
+    // artifical sleep for very slow fronthaul
     if (eNB->frame_parms.N_RB_DL==6)
       rt_sleep_ns(800000LL);
   }
@@ -1444,147 +1216,21 @@ static void* eNB_thread_prach( void* param ) {
 
   eNB_proc_t *proc = (eNB_proc_t*)param;
   PHY_VARS_eNB *eNB= PHY_vars_eNB_g[0][proc->CC_id];
-  /*
-  struct timespec wait;
 
-  wait.tv_sec=0;
-  wait.tv_nsec=5000000L;
-  */
   // set default return value
   eNB_thread_prach_status = 0;
 
-  MSC_START_USE();
-    
-#ifdef DEADLINE_SCHEDULER
-  struct sched_attr attr;
-  unsigned int flags = 0;
-  uint64_t runtime  = 870000 ;
-  uint64_t deadline = 1   *  1000000;
-  uint64_t period   = 1   * 10000000; // each prach thread has a period of 10ms from the starting point
- 
-  attr.size = sizeof(attr);
-  attr.sched_flags = 0;
-  attr.sched_nice = 0;
-  attr.sched_priority = 0;
-
-  attr.sched_policy = SCHED_DEADLINE;
-  attr.sched_runtime  = runtime;
-  attr.sched_deadline = deadline;
-  attr.sched_period   = period; 
-
-  if (sched_setattr(0, &attr, flags) < 0 ) {
-    perror("[SCHED] eNB PRACH sched_setattr failed\n");
-    return &eNB_thread_prach_status;
-  }
-
-  LOG_I( HW, "[SCHED] eNB PRACH deadline thread (TID %ld) started on CPU %d\n", 0, gettid(), sched_getcpu() );
-#else // LOW_LATENCY
-  int policy, s, j;
-  struct sched_param sparam;
-  char cpu_affinity[1024];
-  cpu_set_t cpuset;
-
-  /* Set affinity mask to include CPUs 1 to MAX_CPUS */
-  /* CPU 0 is reserved for UHD */
-  /* CPU 1 is reserved for all TX threads */
-  /* CPU 2..MAX_CPUS is reserved for all RX threads */
-  /* Set CPU Affinity only if number of CPUs >2 */
-  CPU_ZERO(&cpuset);
-#ifdef CPU_AFFINITY
-  if (get_nprocs() >2) {
-    for (j = 1; j < get_nprocs(); j++)
-      CPU_SET(j, &cpuset);
-  
-    s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
-    if (s != 0) {
-      perror( "pthread_setaffinity_np");  
-      exit_fun (" Error setting processor affinity :");
-    }
-  }
-#endif //CPU_AFFINITY
-
-  /* Check the actual affinity mask assigned to the thread */
-  s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
-  if (s != 0) {
-    perror ("pthread_getaffinity_np");
-    exit_fun (" Error getting processor affinity :");
-  }
-  memset(cpu_affinity,0, sizeof(cpu_affinity));
-
-  for (j = 0; j < CPU_SETSIZE; j++)
-    if (CPU_ISSET(j, &cpuset)) {  
-      char temp[1024];
-      sprintf (temp, " CPU_%d", j);
-      strcat(cpu_affinity, temp);
-    }
-
-  memset(&sparam, 0 , sizeof (sparam)); 
-  sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-2;
-
-  policy = SCHED_FIFO ; 
-  s = pthread_setschedparam(pthread_self(), policy, &sparam);
-  if (s != 0) {
-    perror("pthread_setschedparam : ");
-    exit_fun("Error setting thread priority");
-  }
-
-  memset(&sparam, 0 , sizeof (sparam));
-
-  s = pthread_getschedparam(pthread_self(), &policy, &sparam);
-  if (s != 0) {
-    perror("pthread_getschedparam");
-    exit_fun("Error getting thread priority");
-  }
-
-  LOG_I(HW, "[SCHED][eNB] PRACH thread started on CPU %d TID %ld, IC %d, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(),proc->instance_cnt_prach,
-	 (policy == SCHED_FIFO)  ? "SCHED_FIFO" :
-	 (policy == SCHED_RR)    ? "SCHED_RR" :
-	 (policy == SCHED_OTHER) ? "SCHED_OTHER" :
-	 "???",
-	 sparam.sched_priority, cpu_affinity);
-  
-#endif // DEADLINE_SCHEDULER
-
-  mlockall(MCL_CURRENT | MCL_FUTURE);
+  thread_top_init("eNB_thread_prach",500000L,1000000L,20000000L);
 
   while (!oai_exit) {
     
     if (oai_exit) break;
-        
-    if (pthread_mutex_lock(&proc->mutex_prach) != 0) {
-      LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH\n");
-      exit_fun( "error locking mutex" );
-      break;
-    }
-
-    while (proc->instance_cnt_prach < 0) {
-      // most of the time the thread is waiting here
-      // proc->instance_cnt_prach is -1
-      pthread_cond_wait( &proc->cond_prach, &proc->mutex_prach ); // this unlocks mutex_rxtx while waiting and then locks it again
-    }
 
-    if (pthread_mutex_unlock(&proc->mutex_prach) != 0) {
-      LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB PRACH\n");
-      exit_fun( "error unlocking mutex" );
-      break;
-    }
-   
+    if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break;
     
     prach_procedures(eNB);
     
-    if (pthread_mutex_lock(&proc->mutex_prach) != 0) {
-      LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH proc %d\n");
-      exit_fun( "error locking mutex" );
-      break;
-    }
-   
-    proc->instance_cnt_prach--;
-    
-    if (pthread_mutex_unlock(&proc->mutex_prach) != 0) {
-      LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB RX proc %d\n");
-      exit_fun( "error unlocking mutex" );
-      break;
-    } 
+    if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break;
   }
 
   printf( "Exiting eNB thread PRACH\n");
diff --git a/targets/RT/USER/rt_wrapper.c b/targets/RT/USER/rt_wrapper.c
index ed9eb4e79833152366c9dbc2109afd1437589b86..d80de635a6b407cf7f89b53627befab28060c5dc 100644
--- a/targets/RT/USER/rt_wrapper.c
+++ b/targets/RT/USER/rt_wrapper.c
@@ -78,8 +78,6 @@ void set_latency_target(void) {
 }
 
 
-#ifndef RTAI
-
 struct timespec interval, next, now, res;
 clockid_t clock_id = CLOCK_MONOTONIC; //other options are CLOCK_MONOTONIC, CLOCK_REALTIME, CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID
 RTIME rt_get_time_ns (void)
@@ -257,12 +255,7 @@ int sched_getattr(pid_t pid,struct sched_attr *attr,unsigned int size, unsigned
 
 #endif
 
-#else
 
-int rt_sleep_ns(RTIME x)
-{
-  rt_sleep(nano2count(x));
-  return(0);
-}
 
-#endif
+
+
diff --git a/targets/RT/USER/rt_wrapper.h b/targets/RT/USER/rt_wrapper.h
index d67632054b7ee2a14f7c555b7d509452d1851bba..ae668945fe3c526f8ea271eafe8fbf088a9272e8 100644
--- a/targets/RT/USER/rt_wrapper.h
+++ b/targets/RT/USER/rt_wrapper.h
@@ -28,7 +28,7 @@
  *******************************************************************************/
 
 /*! \file rt_wrapper.h
-* \brief provides a wrapper for the timing function for real-time opeartions depending on weather RTAI is used or not. It also implements an API for the SCHED_DEADLINE kernel scheduler.
+* \brief provides a wrapper for the timing function for real-time opeartions. It also implements an API for the SCHED_DEADLINE kernel scheduler.
 * \author F. Kaltenberger and Navid Nikaein
 * \date 2013
 * \version 0.1
@@ -39,9 +39,8 @@
 */
 
 
-void set_latency_target(void);
 
-#ifndef RTAI
+#define _GNU_SOURCE
 #include <time.h>
 #include <errno.h>
 #include <stdint.h>
@@ -52,11 +51,26 @@ void set_latency_target(void);
 #include <linux/types.h>
 #include <syscall.h>
 #include <math.h>
+#include <sched.h> 
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sched.h>
+#include <linux/sched.h>
+#include <signal.h>
+#include <execinfo.h>
+#include <getopt.h>
+#include <sys/sysinfo.h>
+
+#include "UTIL/LOG/log_extern.h"
+#include "msc.h"
 
 #define RTIME long long int
 
 #define rt_printk printf
 
+void set_latency_target(void);
+
 RTIME rt_get_time_ns (void);
 
 int rt_sleep_ns (RTIME x);
@@ -115,12 +129,3 @@ int sched_getattr(pid_t pid,struct sched_attr *attr,unsigned int size, unsigned
 
 #define gettid() syscall(__NR_gettid) // for gettid
 
-#else
-#include <rtai_hal.h>
-#include <rtai_lxrt.h>
-#include <rtai_sem.h>
-#include <rtai_msg.h>
-
-int rt_sleep_ns(RTIME x);
-
-#endif