diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 9aeafd17d60d253a4cec7d3caebcbed438f33643..310bc1f6d27e8588d2dca22eaf0b254e45897629 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -21,7 +21,7 @@
 
 # Author: laurent THOMAS, Lionel GAUTHIER
 
-cmake_minimum_required (VERSION 3.0)
+cmake_minimum_required (VERSION 2.8)
 
 #############################################
 # Base directories, compatible with legacy OAI building
diff --git a/openair1/PHY/defs_common.h b/openair1/PHY/defs_common.h
index c7e5897fff1f433eb970112e6ffb146dbedb9f54..78c12683c1b7df3353d7dcdcf6ca30614edb33e6 100644
--- a/openair1/PHY/defs_common.h
+++ b/openair1/PHY/defs_common.h
@@ -51,6 +51,7 @@
 #include <sys/sysinfo.h>
 
 
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <malloc.h>
@@ -60,6 +61,8 @@
 #include "msc.h"
 #include <common/utils/LOG/log.h>
 
+#include "assertions.h"
+
 
 //#include <complex.h>
 
@@ -1035,14 +1038,15 @@ typedef uint8_t(encoder_if_t)(uint8_t *input,
 
 
 static inline void wait_sync(char *thread_name) {
+  int rc;
 
   printf( "waiting for sync (%s,%d/%p,%p,%p)\n",thread_name,sync_var,&sync_var,&sync_cond,&sync_mutex);
-  pthread_mutex_lock( &sync_mutex );
+  AssertFatal((rc = pthread_mutex_lock( &sync_mutex ))==0,"sync mutex lock error");
   
   while (sync_var<0)
     pthread_cond_wait( &sync_cond, &sync_mutex );
   
-  pthread_mutex_unlock(&sync_mutex);
+  AssertFatal((rc = pthread_mutex_unlock( &sync_mutex ))==0,"sync mutex unlock error");
   
   printf( "got sync (%s)\n", thread_name);
   /*
@@ -1056,37 +1060,20 @@ static inline int wakeup_thread(pthread_mutex_t *mutex,pthread_cond_t *cond,int
   int rc;
   int sleep_cnt=0;
 
-  if ((rc = pthread_mutex_lock(mutex)) != 0) {
-    LOG_E(PHY, "wakeup_thread(): error locking mutex for %s (%d %s, %p)\n",
-        name, rc, strerror(rc), (void *)mutex);
-    exit_fun("nothing to add");
-    return(-1);
-  }
+  AssertFatal((rc = pthread_mutex_lock(mutex))==0,"wakeup_thread(): error locking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex);
+
   while (*instance_cnt == 0) {
-    if ((rc = pthread_mutex_unlock(mutex)) != 0) {
-       LOG_E(PHY, "wakeup_thread(): error unlocking mutex for %s (%d %s, %p)\n",
-          name, rc, strerror(rc), (void *)mutex);
-      exit_fun("nothing to add");
-      return(-1);
-    }
+
+    AssertFatal((rc = pthread_mutex_unlock(mutex))==0,"wakeup_thread(): error unlocking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex);
+
     sleep_cnt++;
     if (sleep_cnt>sleep_cnt_max) return(-1);
     usleep(sleeptime);
-    if ((rc = pthread_mutex_lock(mutex)) != 0) {
-      LOG_E(PHY, "wakeup_thread(): error locking mutex for %s (%d %s, %p)\n",
-          name, rc, strerror(rc), (void *)mutex);
-      exit_fun("nothing to add");
-      return(-1);
-    }
+    AssertFatal((rc = pthread_mutex_lock(mutex))==0,"wakeup_thread(): error locking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex);
   }
   *instance_cnt = *instance_cnt + 1;
 
-  if ((rc = pthread_mutex_unlock(mutex)) != 0) {
-    LOG_E(PHY, "wakeup_thread(): error locking mutex for %s (%d %s, %p)\n",
-        name, rc, strerror(rc), (void *)mutex);
-    exit_fun("nothing to add");
-    return(-1);
-  }
+  AssertFatal((rc = pthread_mutex_unlock(mutex))==0,"wakeup_thread(): error unlocking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex);
 
   // the thread can now be woken up
   if (pthread_cond_signal(cond) != 0) {
@@ -1095,41 +1082,50 @@ static inline int wakeup_thread(pthread_mutex_t *mutex,pthread_cond_t *cond,int
     return(-1);
   }
 
-  pthread_mutex_unlock(mutex);
+  AssertFatal((rc = pthread_mutex_unlock(mutex))==0,"wakeup_thread(): error unlocking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex);
   return(0);
 }
 
-static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) {
+static inline int timedwait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name,uint32_t time_ns) {
   int rc;
-  if ((rc = pthread_mutex_lock(mutex)) != 0) {
-    LOG_E(PHY, "[SCHED][eNB] wait_on_condition(): error locking mutex for %s (%d %s, %p)\n",
-        name, rc, strerror(rc), (void *)mutex);
-    exit_fun("nothing to add");
-    return(-1);
+  int waitret=0;
+  struct timespec now,abstime;
+
+  AssertFatal((rc = pthread_mutex_lock(mutex))==0,"[SCHED][eNB] timedwait_on_condition(): error locking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex);
+
+  clock_gettime(CLOCK_REALTIME,&now);
+  while (*instance_cnt < 0) {
+    // most of the time the thread is waiting here
+    // proc->instance_cnt_rxtx is -1
+    abstime.tv_sec=now.tv_sec;
+    abstime.tv_nsec = now.tv_nsec + time_ns;
+    if ((waitret = pthread_cond_timedwait(cond,mutex,&abstime))==ETIMEDOUT) break; // this unlocks mutex_rxtx while waiting and then locks it again
   }
 
+  AssertFatal((rc = pthread_mutex_unlock(mutex))==0,"[SCHED][eNB] timedwait_on_condition(): error unlocking mutex return %d for %s\n", rc, name);
+
+  return(0);
+}
+
+static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) {
+  int rc;
+
+  AssertFatal((rc = pthread_mutex_lock(mutex))==0,"[SCHED][eNB] wait_on_condition(): error locking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex);
+
   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);
-  }
+  AssertFatal((rc = pthread_mutex_unlock(mutex))==0,"[SCHED][eNB] wait_on_condition(): error unlocking mutex return %d for %s\n", rc, name);
+
   return(0);
 }
 
 static inline int wait_on_busy_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) {
   int rc;
-  if ((rc = pthread_mutex_lock(mutex)) != 0) {
-    LOG_E(PHY, "[SCHED][eNB] wait_on_busy_condition(): error locking mutex for %s (%d %s, %p)\n",
-        name, rc, strerror(rc), (void *)mutex);
-    exit_fun("nothing to add");
-    return(-1);
-  }
+  AssertFatal((rc = pthread_mutex_lock(mutex))==0,"[SCHED][eNB] wait_on_busy_condition(): error locking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex);
 
   while (*instance_cnt == 0) {
     // most of the time the thread will skip this
@@ -1137,30 +1133,20 @@ static inline int wait_on_busy_condition(pthread_mutex_t *mutex,pthread_cond_t *
     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);
-  }
+  AssertFatal((rc = pthread_mutex_unlock(mutex))==0,"[SCHED][eNB] wait_on_busy_condition(): error unlocking mutex return %d for %s\n", rc, name);
+
   return(0);
 }
 
 static inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char *name) {
   int rc;
-  if ((rc = pthread_mutex_lock(mutex)) != 0) {
-    LOG_E(PHY, "[SCHED][eNB] release_thread(): error locking mutex for %s (%d %s, %p)\n",
-        name, rc, strerror(rc), (void *)mutex);
-    exit_fun("nothing to add");
-    return(-1);
-  }
+
+  AssertFatal((rc = pthread_mutex_lock(mutex))==0,"[SCHED][eNB] release_thread(): error locking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex);
 
   *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);
-  }
+  AssertFatal((rc = pthread_mutex_unlock(mutex))==0,"[SCHED][eNB] release_thread(): error unlocking mutex return %d for %s\n", rc, name);
+
   return(0);
 }
 
diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c
index 9ade3f9ea8042205f1cc0b1e1f2dcecf9ed8621a..3dfa7e741ccdbfeb8345899be088f4252bb130d6 100644
--- a/targets/RT/USER/lte-enb.c
+++ b/targets/RT/USER/lte-enb.c
@@ -144,8 +144,8 @@ extern double cpuf;
 void init_eNB(int,int);
 void stop_eNB(int nb_inst);
 
-int wakeup_tx(PHY_VARS_eNB *eNB);
-int wakeup_txfh(L1_rxtx_proc_t *proc,int frame_tx,int subframe_tx,uint64_t timestamp_tx,PHY_VARS_eNB *eNB);
+int wakeup_tx(PHY_VARS_eNB *eNB ,int frame_rx,int subframe_rx,int frame_tx,int subframe_tx,uint64_t timestamp_tx);
+int wakeup_txfh(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc,int frame_tx,int subframe_tx,uint64_t timestamp_tx);
 void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe);
 #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
   void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe);
@@ -160,6 +160,7 @@ extern void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset);
 
 
 static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name) {
+  int ret;
   start_meas(&softmodem_stats_rxtx_sf);
 
   //L1_rxtx_proc_t *L1_proc_tx = &eNB->proc.L1_proc_tx;
@@ -237,10 +238,7 @@ static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name
     memcpy(&pre_scd_eNB_UE_stats,&RC.mac[0]->UE_list.eNB_UE_stats, sizeof(eNB_UE_STATS)*MAX_NUM_CCs*NUMBER_OF_UE_MAX);
     memcpy(&pre_scd_activeUE, &RC.mac[0]->UE_list.active, sizeof(boolean_t)*NUMBER_OF_UE_MAX);
 
-    if (pthread_mutex_lock(&ru->proc.mutex_pre_scd)!= 0) {
-      LOG_E( PHY, "[eNB] error locking proc mutex for eNB pre scd\n");
-      exit_fun("error locking mutex_time");
-    }
+    AssertFatal((ret= pthread_mutex_lock(&ru->proc.mutex_pre_scd))==0,"[eNB] error locking proc mutex for eNB pre scd, return %d\n",ret);
 
     ru->proc.instance_pre_scd++;
 
@@ -254,20 +252,18 @@ static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name
              proc->frame_rx,proc->subframe_rx,ru->proc.instance_pre_scd );
     }
 
-    if (pthread_mutex_unlock(&ru->proc.mutex_pre_scd)!= 0) {
-      LOG_E( PHY, "[eNB] error unlocking mutex_pre_scd mutex for eNB pre scd\n");
-      exit_fun("error unlocking mutex_pre_scd");
-    }
+    AssertFatal((ret= pthread_mutex_unlock(&ru->proc.mutex_pre_scd))==0,"[eNB] error unlocking proc mutex for eNB pre scd, return %d\n",ret);
+
   }
 
 #endif
-  pthread_mutex_lock(&eNB->UL_INFO_mutex);
+  AssertFatal((ret= pthread_mutex_lock(&eNB->UL_INFO_mutex))==0,"error locking UL_INFO_mutex, return %d\n",ret);
   eNB->UL_INFO.frame     = proc->frame_rx;
   eNB->UL_INFO.subframe  = proc->subframe_rx;
   eNB->UL_INFO.module_id = eNB->Mod_id;
   eNB->UL_INFO.CC_id     = eNB->CC_id;
   eNB->if_inst->UL_indication(&eNB->UL_INFO);
-  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
+  AssertFatal((ret= pthread_mutex_unlock(&eNB->UL_INFO_mutex))==0,"error unlocking UL_INFO_mutex, return %d\n",ret);
 
   /* this conflict resolution may be totally wrong, to be tested */
   /* CONFLICT RESOLUTION: BEGIN */
@@ -336,6 +332,7 @@ static void *L1_thread_tx(void *param) {
   char thread_name[100];
   sprintf(thread_name,"TXnp4_%d\n",&eNB->proc.L1_proc == proc ? 0 : 1);
   thread_top_init(thread_name,1,470000,500000,500000);
+  int ret;
 
   //wait_sync("tx_thread");
 
@@ -357,7 +354,7 @@ static void *L1_thread_tx(void *param) {
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_ENB,proc->frame_rx);
     LOG_D(PHY,"L1 TX processing %d.%d\n",proc->frame_tx,proc->subframe_tx);
     phy_procedures_eNB_TX(eNB, proc, 1);
-    pthread_mutex_lock( &proc->mutex );
+    AssertFatal((ret= pthread_mutex_lock( &proc->mutex ))==0,"error locking L1_proc_tx mutex, return %d\n",ret);
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_TX_IC,proc->instance_cnt);
 
     int subframe_tx = proc->subframe_tx;
@@ -374,8 +371,8 @@ static void *L1_thread_tx(void *param) {
       exit_fun( "ERROR pthread_cond_signal" );
     }
 
-    pthread_mutex_unlock( &proc->mutex );
-    wakeup_txfh(proc,frame_tx,subframe_tx,timestamp_tx,eNB);
+    AssertFatal((ret= pthread_mutex_unlock( &proc->mutex ))==0,"error unlocking L1_proc_tx mutex, return %d\n",ret);
+    wakeup_txfh(eNB,proc,frame_tx,subframe_tx,timestamp_tx);
   }
 
   return 0;
@@ -436,8 +433,8 @@ static void *L1_thread( void *param ) {
 
 
     if (NFAPI_MODE!=NFAPI_MODE_VNF) {
-      if(get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)      wakeup_tx(eNB);
-      else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT)     wakeup_txfh(proc,proc->frame_tx,proc->subframe_tx,proc->timestamp_tx,eNB);
+      if(get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)      wakeup_tx(eNB,proc->frame_rx,proc->subframe_rx,proc->frame_tx,proc->subframe_tx,proc->timestamp_tx);
+      else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT)     wakeup_txfh(eNB,proc,proc->frame_tx,proc->subframe_tx,proc->timestamp_tx);
     }
 
     if (release_thread(&proc->mutex,&proc->instance_cnt,thread_name)<0) break;
@@ -475,48 +472,58 @@ void eNB_top(PHY_VARS_eNB *eNB, int frame_rx, int subframe_rx, char *string,RU_t
   }
 }
 
-int wakeup_txfh(L1_rxtx_proc_t *proc,int frame_tx,int subframe_tx,uint64_t timestamp_tx,PHY_VARS_eNB *eNB) {
+int wakeup_txfh(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc,int frame_tx,int subframe_tx,uint64_t timestamp_tx) {
+
+  RU_t *ru;
   RU_proc_t *ru_proc;
   LTE_DL_FRAME_PARMS *fp; 
-
-
-  struct timespec wait;
-  wait.tv_sec=0;
-  wait.tv_nsec=5000000L;
+  int waitret,ret;
 
   LOG_D(PHY,"L1 TX Waking up TX FH %d.%d (IC RU TX %d)\n",frame_tx,subframe_tx,proc->instance_cnt_RUs);
 
   // grab the information for the RU due to the following wait 
 
-  if(wait_on_condition(&proc->mutex_RUs,&proc->cond_RUs,&proc->instance_cnt_RUs,"wakeup_txfh")<0) {
-    LOG_E(PHY,"Frame %d, subframe %d: TX FH not ready\n", frame_tx, subframe_tx);
-    return(-1);
-  }
+  waitret=timedwait_on_condition(&proc->mutex_RUs,&proc->cond_RUs,&proc->instance_cnt_RUs,"wakeup_txfh",1000000);
 
-  if (release_thread(&proc->mutex_RUs,&proc->instance_cnt_RUs,"wakeup_txfh")<0) return(-1);
+  AssertFatal(release_thread(&proc->mutex_RUs,&proc->instance_cnt_RUs,"wakeup_txfh")==0, "error releaseing eNB lock on RUs\n"); 
+
+  if (waitret == ETIMEDOUT) {
+     LOG_W(PHY,"Dropping TX slot (%d.%d) because FH is blocked more than 1 subframe times (1ms)\n",frame_tx,subframe_tx);
+
+     AssertFatal((ret=pthread_mutex_lock(&eNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret);
+     eNB->proc.RU_mask_tx = 0;
+     AssertFatal((ret=pthread_mutex_unlock(&eNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret);
+     AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RUs))==0,"mutex_lock returns %d\n",ret);
+     proc->instance_cnt_RUs = 0;
+     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs);
+     AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RUs))==0,"mutex_unlock returns %d\n",ret);
+     return(-1);
+  } 
 
   for(int ru_id=0; ru_id<eNB->num_RU; ru_id++){
-    ru_proc = &eNB->RU_list[ru_id]->proc;
-    fp = &eNB->RU_list[ru_id]->frame_parms;
+    ru      = eNB->RU_list[ru_id];
+    ru_proc = &ru->proc;
+    fp = &ru->frame_parms;
     if (((fp->frame_type == TDD) && (subframe_select(fp,proc->subframe_tx)==SF_UL))||
         (eNB->RU_list[ru_id]->state == RU_SYNC)||
         (eNB->RU_list[ru_id]->wait_cnt>0)){
-       pthread_mutex_lock(&proc->mutex_RUs);
+       AssertFatal((pthread_mutex_lock(&proc->mutex_RUs))==0, "mutex_lock returns %d\n",ret);
        proc->instance_cnt_RUs = 0;
-       pthread_mutex_unlock(&proc->mutex_RUs);
+       AssertFatal((pthread_mutex_unlock(&proc->mutex_RUs))==0, "mutex_unlock returns %d\n",ret);
        continue;//hacking only works when all RU_tx works on the same subframe #TODO: adding mask stuff
     }
 
+    AssertFatal((ret = pthread_mutex_lock(&ru_proc->mutex_eNBs))==0,"ERROR pthread_mutex_lock failed on mutex_eNBs L1_thread_tx with ret=%d\n",ret);
+
     if (ru_proc->instance_cnt_eNBs == 0) {
-        LOG_E(PHY,"Frame %d, subframe %d: TX FH thread busy, dropping Frame %d, subframe %d\n", ru_proc->frame_tx, ru_proc->subframe_tx, proc->frame_rx, proc->subframe_rx);
-        return(-1);
+      LOG_E(PHY,"Frame %d, subframe %d: TX FH thread busy, dropping Frame %d, subframe %d\n", ru_proc->frame_tx, ru_proc->subframe_tx, proc->frame_rx, proc->subframe_rx);
+      AssertFatal((ret=pthread_mutex_lock(&eNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret);
+      eNB->proc.RU_mask_tx = 0;
+      AssertFatal((ret=pthread_mutex_unlock(&eNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret);
+      AssertFatal((ret=pthread_mutex_unlock( &ru_proc->mutex_eNBs ))==0,"mutex_unlock return %d\n",ret);
+      return(-1);
     }
 
-    if (pthread_mutex_timedlock(&ru_proc->mutex_eNBs,&wait) != 0) {
-        LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX1 thread %d (IC %d)\n", ru_proc->subframe_rx&1,ru_proc->instance_cnt_eNBs );
-        exit_fun( "error locking mutex_eNB" );
-        return(-1);
-    }
     ru_proc->instance_cnt_eNBs = 0;
     ru_proc->timestamp_tx = timestamp_tx;
     ru_proc->subframe_tx  = subframe_tx;
@@ -524,31 +531,23 @@ int wakeup_txfh(L1_rxtx_proc_t *proc,int frame_tx,int subframe_tx,uint64_t times
 
     LOG_D(PHY,"L1 TX Waking up TX FH (2) %d.%d\n",frame_tx,subframe_tx);
     // the thread can now be woken up
-    if (pthread_cond_signal(&ru_proc->cond_eNBs) != 0) {
-       LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
-       exit_fun( "ERROR pthread_cond_signal" );
-       return(-1);
-    }
-    pthread_mutex_unlock( &ru_proc->mutex_eNBs );
+    AssertFatal(pthread_cond_signal(&ru_proc->cond_eNBs) == 0,
+               "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
+    AssertFatal((ret=pthread_mutex_unlock(&ru_proc->mutex_eNBs))==0,"mutex_unlock returned %d\n",ret);
   }
   return(0);
 }
 
-int wakeup_tx(PHY_VARS_eNB *eNB) {
-  L1_proc_t *proc=&eNB->proc;
-  L1_rxtx_proc_t *L1_proc_tx = &proc->L1_proc_tx;
-  L1_rxtx_proc_t *L1_proc    = &proc->L1_proc;
-  struct timespec wait;
-  wait.tv_sec=0;
-  wait.tv_nsec=5000000L;
+int wakeup_tx(PHY_VARS_eNB *eNB, int frame_rx,int subframe_rx,int frame_tx,int subframe_tx,uint64_t timestamp_tx) {
+
+  L1_rxtx_proc_t *L1_proc = &eNB->proc.L1_proc;
+  L1_rxtx_proc_t *L1_proc_tx = &eNB->proc.L1_proc_tx;
+
+  int ret;
 
   LOG_D(PHY,"ENTERED wakeup_tx (IC %d)\n",L1_proc_tx->instance_cnt);
   
-  if (pthread_mutex_timedlock(&L1_proc_tx->mutex,&wait) != 0) {
-    LOG_E(PHY, "[SCHED][eNB] ERROR locking mutex for eNB L1_thread_tx\n");
-    exit_fun("ERROR pthread_lock");
-    return(-1);
-  }
+  AssertFatal((ret = pthread_mutex_lock(&L1_proc_tx->mutex))==0,"mutex_lock returns %d\n",ret);
 
   LOG_D(PHY,"L1 RX %d.%d Waiting to wake up L1 TX %d.%d (IC L1TX %d)\n",L1_proc->frame_rx,L1_proc->subframe_rx,L1_proc->frame_tx,L1_proc->subframe_tx,L1_proc_tx->instance_cnt);
 
@@ -560,21 +559,17 @@ int wakeup_tx(PHY_VARS_eNB *eNB) {
   VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_TX_IC,L1_proc_tx->instance_cnt);
   L1_proc_tx->instance_cnt = 0;
   VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_TX_IC,L1_proc_tx->instance_cnt);
-  L1_proc_tx->subframe_rx   = L1_proc->subframe_rx;
-  L1_proc_tx->frame_rx      = L1_proc->frame_rx;
-  L1_proc_tx->subframe_tx   = L1_proc->subframe_tx;
-  L1_proc_tx->frame_tx      = L1_proc->frame_tx;
-  L1_proc_tx->timestamp_tx  = L1_proc->timestamp_tx;
+  L1_proc_tx->subframe_rx   = subframe_rx;
+  L1_proc_tx->frame_rx      = frame_rx;
+  L1_proc_tx->subframe_tx   = subframe_tx;
+  L1_proc_tx->frame_tx      = frame_tx;
+  L1_proc_tx->timestamp_tx  = timestamp_tx;
 
   // the thread can now be woken up
   LOG_D(PHY,"L1 RX Waking up L1 TX %d.%d\n",L1_proc->frame_tx,L1_proc->subframe_tx);
-  if (pthread_cond_signal(&L1_proc_tx->cond) != 0) {
-    LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n");
-    exit_fun( "ERROR pthread_cond_signal" );
-    return(-1);
-  }
+  AssertFatal(pthread_cond_signal(&L1_proc_tx->cond) == 0, "ERROR pthread_cond_signal for eNB L1 thread tx\n");
 
-  pthread_mutex_unlock( &L1_proc_tx->mutex);
+  AssertFatal((ret=pthread_mutex_unlock(&L1_proc_tx->mutex))==0,"mutex_unlock returns %d\n",ret);
   return(0);
 }
 
@@ -583,57 +578,43 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) {
   RU_proc_t *ru_proc=&ru->proc;
   L1_rxtx_proc_t *L1_proc=&proc->L1_proc;
   LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
+
+  int i,ret;
   
   LOG_D(PHY,"ENTERED wakeup_rxtx, %d.%d\n",ru_proc->frame_rx,ru_proc->subframe_rx);
-  
-  struct timespec wait;
-  int sleep_cnt=0;
-  
-  wait.tv_sec=0;
-  wait.tv_nsec=5000000L;
 
-  // wake up TX for subframe n+sf_ahead
-  // lock the TX mutex and make sure the thread is ready
-  if (pthread_mutex_timedlock(&L1_proc->mutex,&wait) != 0) {
-    LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", L1_proc->subframe_rx&1,L1_proc->instance_cnt );
-    exit_fun( "error locking mutex_rxtx" );
-    return(-1);
-  }
-  if (L1_proc->instance_cnt == 0) {
-    pthread_mutex_unlock(&L1_proc->mutex);
-    usleep(200);
-    if (pthread_mutex_timedlock(&L1_proc->mutex,&wait) != 0) {
-      LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", L1_proc->subframe_rx&1,L1_proc->instance_cnt );
-      exit_fun( "error locking mutex_rxtx" );
-      return(-1);
+
+  
+  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU))==0,"mutex_lock returns %d\n",ret);
+  for (i=0;i<eNB->num_RU;i++) {
+    if (ru == eNB->RU_list[i]) {
+      if ((proc->RU_mask[ru_proc->subframe_rx]&(1<<i)) > 0)
+	LOG_E(PHY,"eNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n",
+	      eNB->Mod_id,proc->frame_rx,proc->subframe_rx,ru->idx,eNB->num_RU,proc->RU_mask[ru_proc->subframe_rx]);
+      proc->RU_mask[ru_proc->subframe_rx] |= (1<<i);
     }
-    if (L1_proc->instance_cnt == 0) LOG_E(PHY,"Frame %d, subframe %d: RXTX0 thread busy, dropping\n",ru_proc->frame_rx,ru_proc->subframe_rx);
   }
-  if (L1_proc->instance_cnt == -1) {
-    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_IC,L1_proc->instance_cnt);
-    ++L1_proc->instance_cnt;
-    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_IC,L1_proc->instance_cnt);
-
-  // We have just received and processed the common part of a subframe, say n. 
-  // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired 
-
+  if (proc->RU_mask[ru_proc->subframe_rx] != (1<<eNB->num_RU)-1) {  // not all RUs have provided their information so return
+    LOG_E(PHY,"Not all RUs have provided their info\n");
+    AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"mutex_unlock returns %d\n",ret);
+    return(0);
+  }
+  else { // all RUs have provided their information so continue on and wakeup eNB processing
+    proc->RU_mask[ru_proc->subframe_rx] = 0;
+    AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"mutex_unlock returns %d\n",ret);
+  }
 
-  LOG_D(PHY,"RU RX Waking up rxtx %d.%d (IC L1RX %d)\n",ru_proc->frame_rx,ru_proc->subframe_rx,L1_proc->instance_cnt);
 
-  while (L1_proc->instance_cnt == 0) {
-    pthread_mutex_unlock( &L1_proc->mutex);
-    if (++sleep_cnt == ru->wakeup_L1_sleep_cnt_max) {
-      LOG_E(PHY,"Frame %d, subframe %d: RXTX0 thread busy, dropping\n",L1_proc->frame_rx,L1_proc->subframe_rx);
-      return(-1);
-    }
-    usleep(ru->wakeup_L1_sleeptime);
+  // wake up TX for subframe n+sl_ahead
+  // lock the TX mutex and make sure the thread is ready
+  AssertFatal((ret=pthread_mutex_lock(&L1_proc->mutex)) == 0,"mutex_lock returns %d\n", ret);
 
-    if (pthread_mutex_timedlock(&L1_proc->mutex,&wait) != 0) {
-      LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", L1_proc->subframe_rx&1,L1_proc->instance_cnt );
-      exit_fun( "error locking mutex_rxtx" );
-      return(-1);
-    }
+  if (L1_proc->instance_cnt == 0) { // L1_thread is busy so abort the subframe
+   AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"mutex_unlock return %d\n",ret);
+   LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->subframe_rx); 
+   return(0);
   }
+ 
 
   ++L1_proc->instance_cnt;
   // We have just received and processed the common part of a subframe, say n.
@@ -642,38 +623,39 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) {
   // The last (TS_rx mod samples_per_frame) was n*samples_per_tti,
   // we want to generate subframe (n+sf_ahead), so TS_tx = TX_rx+sf_ahead*samples_per_tti,
   // and proc->subframe_tx = proc->subframe_rx+sf_ahead
-    L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_tti);
-    L1_proc->frame_rx     = ru_proc->frame_rx;
-    L1_proc->subframe_rx  = ru_proc->subframe_rx;
-    L1_proc->frame_tx     = (L1_proc->subframe_rx > (9-sf_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx;
-    L1_proc->subframe_tx  = (L1_proc->subframe_rx + sf_ahead)%10;
+  L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_tti);
+  L1_proc->frame_rx     = ru_proc->frame_rx;
+  L1_proc->subframe_rx  = ru_proc->subframe_rx;
+  L1_proc->frame_tx     = (L1_proc->subframe_rx > (9-sf_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx;
+  L1_proc->subframe_tx  = (L1_proc->subframe_rx + sf_ahead)%10;
 
-    LOG_D(PHY,"wakeup_rxtx: L1_proc->subframe_rx %d, L1_proc->subframe_tx %d, RU %d\n",L1_proc->subframe_rx,L1_proc->subframe_tx,ru->idx);
+  LOG_D(PHY,"wakeup_rxtx: L1_proc->subframe_rx %d, L1_proc->subframe_tx %d, RU %d\n",L1_proc->subframe_rx,L1_proc->subframe_tx,ru->idx);
 
-    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_RXTX_RX_RU+ru->idx, L1_proc->frame_rx);
-    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_RXTX_RX_RU+ru->idx, L1_proc->subframe_rx);
-    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_RXTX_TX_RU+ru->idx, L1_proc->frame_tx);
-    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_RXTX_TX_RU+ru->idx, L1_proc->subframe_tx);
+  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_RXTX_RX_RU+ru->idx, L1_proc->frame_rx);
+  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_RXTX_RX_RU+ru->idx, L1_proc->subframe_rx);
+  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_RXTX_TX_RU+ru->idx, L1_proc->frame_tx);
+  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_RXTX_TX_RU+ru->idx, L1_proc->subframe_tx);
 
   // the thread can now be woken up
-    if (pthread_cond_signal(&L1_proc->cond) != 0) {
-      LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n");
-      exit_fun( "ERROR pthread_cond_signal" );
-      return(-1);
-    }
+  if (pthread_cond_signal(&L1_proc->cond) != 0) {
+    LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n");
+    exit_fun( "ERROR pthread_cond_signal" );
+    return(-1);
   }
-  pthread_mutex_unlock( &L1_proc->mutex);
+
+  AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"mutex_unlock return %d\n",ret);
+
   return(0);
 }
 
 void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
   L1_proc_t *proc = &eNB->proc;
   LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
-  int i;
+  int i,ret;
 
   if (ru!=NULL) {
-    pthread_mutex_lock(&proc->mutex_RU_PRACH);
 
+    AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU_PRACH))==0,"mutex_lock return %d\n",ret);
     for (i=0; i<eNB->num_RU; i++) {
       if (ru == eNB->RU_list[i]) {
         LOG_D(PHY,"frame %d, subframe %d: RU %d for eNB %d signals PRACH (mask %x, num_RU %d)\n",frame,subframe,i,eNB->Mod_id,proc->RU_mask_prach,eNB->num_RU);
@@ -687,11 +669,11 @@ void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
     }
 
     if (proc->RU_mask_prach != (1<<eNB->num_RU)-1) {  // not all RUs have provided their information so return
-      pthread_mutex_unlock(&proc->mutex_RU_PRACH);
+      AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU_PRACH))==0,"mutex_unlock return %d\n",ret);
       return;
     } else { // all RUs have provided their information so continue on and wakeup eNB processing
       proc->RU_mask_prach = 0;
-      pthread_mutex_unlock(&proc->mutex_RU_PRACH);
+      AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU_PRACH))==0,"mutex_unlock return %d\n",ret);
     }
   }
 
@@ -705,11 +687,7 @@ void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
     }
 
     // wake up thread for PRACH RX
-    if (pthread_mutex_lock(&proc->mutex_prach) != 0) {
-      LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach);
-      exit_fun( "error locking mutex_prach" );
-      return;
-    }
+    AssertFatal((ret=pthread_mutex_lock(&proc->mutex_prach))==0,"[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach);
 
     ++proc->instance_cnt_prach;
     // set timing for prach thread
@@ -723,7 +701,7 @@ void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
       return;
     }
 
-    pthread_mutex_unlock( &proc->mutex_prach );
+    AssertFatal((ret=pthread_mutex_unlock( &proc->mutex_prach))==0,"mutex_unlock return %d\n",ret);
   }
 }
 
@@ -731,10 +709,10 @@ void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
 void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
   L1_proc_t *proc = &eNB->proc;
   LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
-  int i;
+  int i,ret;
 
   if (ru!=NULL) {
-    pthread_mutex_lock(&proc->mutex_RU_PRACH_br);
+    AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU_PRACH_br))==0,"mutex_lock return %d\n",ret);
 
     for (i=0; i<eNB->num_RU; i++) {
       if (ru == eNB->RU_list[i]) {
@@ -749,11 +727,11 @@ void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
     }
 
     if (proc->RU_mask_prach_br != (1<<eNB->num_RU)-1) {  // not all RUs have provided their information so return
-      pthread_mutex_unlock(&proc->mutex_RU_PRACH_br);
+      AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU_PRACH_br))==0,"mutex_unlock return %d\n",ret);
       return;
     } else { // all RUs have provided their information so continue on and wakeup eNB processing
       proc->RU_mask_prach_br = 0;
-      pthread_mutex_unlock(&proc->mutex_RU_PRACH_br);
+      AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU_PRACH_br))==0,"mutex_unlock return %d\n",ret);
     }
   }
 
@@ -767,11 +745,7 @@ void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
     }
 
     // wake up thread for PRACH RX
-    if (pthread_mutex_lock(&proc->mutex_prach_br) != 0) {
-      LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach_br);
-      exit_fun( "error locking mutex_prach" );
-      return;
-    }
+    AssertFatal((ret=pthread_mutex_lock(&proc->mutex_prach_br))==0,"[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach_br);
 
     ++proc->instance_cnt_prach_br;
     // set timing for prach thread
@@ -785,7 +759,7 @@ void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
       return;
     }
 
-    pthread_mutex_unlock( &proc->mutex_prach_br );
+    AssertFatal((ret=pthread_mutex_unlock( &proc->mutex_prach_br))==0,"mutex_unlock return %d\n",ret);
   }
 }
 #endif
@@ -1029,6 +1003,7 @@ void kill_eNB_proc(int inst) {
   PHY_VARS_eNB *eNB;
   L1_proc_t *proc;
   L1_rxtx_proc_t *L1_proc, *L1_proc_tx;
+  int ret;
 
   for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
     eNB=RC.eNB[inst][CC_id];
@@ -1044,32 +1019,32 @@ void kill_eNB_proc(int inst) {
     LOG_I(PHY, "Killing TX CC_id %d inst %d\n", CC_id, inst );
 
     if ((get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) && NFAPI_MODE!=NFAPI_MODE_VNF) {
-      pthread_mutex_lock(&L1_proc->mutex);
+      AssertFatal((ret=pthread_mutex_lock(&L1_proc->mutex))==0,"mutex_lock return %d\n",ret);
       L1_proc->instance_cnt = 0;
       pthread_cond_signal(&L1_proc->cond);
-      pthread_mutex_unlock(&L1_proc->mutex);
-      pthread_mutex_lock(&L1_proc_tx->mutex);
+      AssertFatal((ret=pthread_mutex_unlock(&L1_proc->mutex))==0,"mutex_unlock return %d\n",ret);
+      AssertFatal((ret=pthread_mutex_lock(&L1_proc_tx->mutex))==0,"mutex_lock return %d\n",ret);
       L1_proc_tx->instance_cnt = 0;
       pthread_cond_signal(&L1_proc_tx->cond);
-      pthread_mutex_unlock(&L1_proc_tx->mutex);
+      AssertFatal((ret=pthread_mutex_unlock(&L1_proc_tx->mutex))==0,"muex_unlock return %d\n",ret);
     }
 
-    pthread_mutex_lock(&proc->mutex_prach);
+    AssertFatal((ret=pthread_mutex_lock(&proc->mutex_prach))==0,"mutex_lock return %d\n",ret);
     proc->instance_cnt_prach = 0;
     pthread_cond_signal( &proc->cond_prach );
-    pthread_mutex_unlock(&proc->mutex_prach);
+    AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_prach))==0,"mutex_unlock return %d\n",ret);
     pthread_cond_signal( &proc->cond_asynch_rxtx );
     pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
     LOG_D(PHY, "joining pthread_prach\n");
     pthread_join( proc->pthread_prach, (void **)&status );
     LOG_I(PHY, "Destroying prach mutex/cond\n");
-    pthread_mutex_destroy( &proc->mutex_prach );
+    pthread_mutex_destroy( &proc->mutex_prach);
     pthread_cond_destroy( &proc->cond_prach );
 #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
     proc->instance_cnt_prach_br = 0;
     pthread_cond_signal( &proc->cond_prach_br );
     pthread_join( proc->pthread_prach_br, (void **)&status );
-    pthread_mutex_destroy( &proc->mutex_prach_br );
+    pthread_mutex_destroy( &proc->mutex_prach_br);
     pthread_cond_destroy( &proc->cond_prach_br );
 #endif
     LOG_I(PHY, "Destroying UL_INFO mutex\n");