Index: trunk/kernel/libk/remote_sem.c
===================================================================
--- trunk/kernel/libk/remote_sem.c	(revision 469)
+++ trunk/kernel/libk/remote_sem.c	(revision 563)
@@ -1,6 +1,6 @@
 /*
- * remote_sem.c - Kernel function implementing the semaphore related syscalls.
+ * remote_sem.c - POSIX unnamed semaphore implementation.
  * 
- * Author   Alain Greiner  (2016)
+ * Author   Alain Greiner  (2016,2017,2018)
  *
  * Copyright (c) UPMC Sorbonne Universites
@@ -33,5 +33,5 @@
 
 ///////////////////////////////////////////////
-xptr_t remote_sem_from_vaddr( intptr_t  vaddr )
+xptr_t remote_sem_from_ident( intptr_t  ident )
 {
     // get pointer on local process_descriptor
@@ -45,7 +45,11 @@
     process_t    * ref_ptr = GET_PTR( ref_xp );
 
-    // get extended pointer on root of semaphores list 
+    // get extended pointer on semaphores list 
     xptr_t root_xp = XPTR( ref_cxy , &ref_ptr->sem_root );
+    xptr_t lock_xp = XPTR( ref_cxy , &ref_ptr->sync_lock );
    
+    // get lock protecting synchro lists
+    remote_queuelock_acquire( lock_xp );
+ 
     // scan reference process semaphores list
     xptr_t         iter_xp;
@@ -53,5 +57,5 @@
     cxy_t          sem_cxy;
     remote_sem_t * sem_ptr;
-    intptr_t       ident;
+    intptr_t       current;
     bool_t         found = false;
             
@@ -61,7 +65,7 @@
         sem_cxy = GET_CXY( sem_xp );
         sem_ptr = GET_PTR( sem_xp );
-        ident   = (intptr_t)hal_remote_lpt( XPTR( sem_cxy , &sem_ptr->ident ) );   
-
-        if( ident == vaddr )
+        current = (intptr_t)hal_remote_lpt( XPTR( sem_cxy , &sem_ptr->ident ) );   
+
+        if( current == ident )
         {
             found = true;
@@ -70,13 +74,15 @@
     }
 
+    // relese lock protecting synchros lists
+    remote_queuelock_release( lock_xp );
+ 
     if( found == false )  return XPTR_NULL;
     else                  return sem_xp;
 
-}  // end remote_sem_from_vaddr()
+}  // end remote_sem_from_ident()
 
 ///////////////////////////////////////////
 error_t remote_sem_create( intptr_t   vaddr,
-                           uint32_t   value,
-                           xptr_t     sem_xp_xp )
+                           uint32_t   value )
 {
     remote_sem_t * sem_ptr;
@@ -108,26 +114,35 @@
     }
 
-    if( sem_xp == XPTR_NULL ) return -1;
+    if( sem_xp == XPTR_NULL ) return 0xFFFFFFFF;
 
     // initialise semaphore 
-    hal_remote_sw ( XPTR( ref_cxy , &sem_ptr->count ) , value );
+    hal_remote_s32 ( XPTR( ref_cxy , &sem_ptr->count ) , value );
 	hal_remote_spt( XPTR( ref_cxy , &sem_ptr->ident ) , (void *)vaddr );
-    remote_spinlock_init( XPTR( ref_cxy , &sem_ptr->lock ) );
 	xlist_root_init( XPTR( ref_cxy , &sem_ptr->root ) );
 	xlist_entry_init( XPTR( ref_cxy , &sem_ptr->list ) );
-
-    // register semaphore in reference process xlist
+    remote_busylock_init( XPTR( ref_cxy , &sem_ptr->lock ), LOCK_SEM_STATE );
+
     xptr_t root_xp = XPTR( ref_cxy , &ref_ptr->sem_root );
-    xptr_t xp_list = XPTR( ref_cxy , &sem_ptr->list );
-    remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
-    xlist_add_first( root_xp , xp_list );
-    remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
-
-    // write extended pointer on semaphore in calling thread buffer
-    hal_remote_swd( sem_xp_xp , sem_xp );
+    xptr_t list_xp = XPTR( ref_cxy , &sem_ptr->list );
+
+    // get lock protecting user synchro lists
+    remote_queuelock_acquire( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
+
+    // register semaphore in reference process list of semaphores
+    xlist_add_first( root_xp , list_xp );
+
+    // release lock protecting user synchro lists
+    remote_queuelock_release( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
+
+#if DEBUG_SEM
+thread_t * this = CURRENT_THREAD;
+if( (uint32_t)hal_get_cycles() > DEBUG_SEM )
+printk("\n[DBG] %s : thread %x in process %x INITIALIZE sem(%x,%x) / value %d\n",
+__FUNCTION__, this->trdid, this->process->pid, local_cxy, sem_ptr, value );
+#endif
 
     return 0;
 
-}  // en remote_sem_create()
+}  // end remote_sem_create()
  
 ////////////////////////////////////////
@@ -146,9 +161,6 @@
     // get semaphore cluster and local pointer
     cxy_t          sem_cxy = GET_CXY( sem_xp );
-    remote_sem_t * sem_ptr = (remote_sem_t *)GET_PTR( sem_xp );
-
-    // get lock protecting semaphore
-    remote_spinlock_lock( XPTR( sem_cxy , &sem_ptr->lock ) );
-  
+    remote_sem_t * sem_ptr = GET_PTR( sem_xp );
+
     // get remote pointer on waiting queue root
     xptr_t root_xp = XPTR( sem_cxy , &sem_ptr->root );
@@ -161,14 +173,8 @@
     }
 
-    // reset semaphore count
-    hal_remote_sw( XPTR( sem_cxy , &sem_ptr->count ) , 0 );
-
     // remove semaphore from reference process xlist
-    remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
+    remote_queuelock_acquire( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
     xlist_unlink( XPTR( sem_cxy , &sem_ptr->list ) );
-    remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
-
-    // release lock
-    remote_spinlock_unlock( XPTR( sem_cxy , &sem_ptr->lock ) );
+    remote_queuelock_release( XPTR( ref_cxy , &ref_ptr->sync_lock ) );
 
     // release memory allocated for semaphore descriptor
@@ -190,37 +196,68 @@
 void remote_sem_wait( xptr_t sem_xp )
 { 
+    thread_t * this = CURRENT_THREAD;
+
+// check calling thread can yield
+assert( (this->busylocks == 0),
+"cannot yield : busylocks = %d\n", this->busylocks );
+
+
     // get semaphore cluster and local pointer
     cxy_t          sem_cxy = GET_CXY( sem_xp );
     remote_sem_t * sem_ptr = GET_PTR( sem_xp );
 
-    // get lock protecting semaphore     
-	remote_spinlock_lock( XPTR( sem_cxy , &sem_ptr->lock ) );
+    // get extended pointers on sem fields 
+    xptr_t           count_xp = XPTR( sem_cxy , &sem_ptr->count );
+    xptr_t           root_xp  = XPTR( sem_cxy , &sem_ptr->root );
+    xptr_t           lock_xp  = XPTR( sem_cxy , &sem_ptr->lock );
+
+    while( 1 )
+    {
+        // get busylock protecting semaphore     
+	    remote_busylock_acquire( lock_xp );
   
-    // get semaphore current value
-    uint32_t count = hal_remote_lw( XPTR( sem_cxy , &sem_ptr->count ) );
-
-	if( count > 0 )       // success
-	{
-        // decrement semaphore value
-        hal_remote_sw( XPTR( sem_cxy , &sem_ptr->count ) , count - 1 );
-
-        // release lock
-	    remote_spinlock_unlock( XPTR( sem_cxy , &sem_ptr->lock ) );
-	}
-	else                 // failure
-	{
-        thread_t * this = CURRENT_THREAD;
-
-        // register thread in waiting queue
-        xptr_t root_xp = XPTR( sem_cxy   , &sem_ptr->root );
-        xptr_t list_xp = XPTR( local_cxy , &this->wait_list );
-		xlist_add_last( root_xp , list_xp );
-
-        // release lock
-	    remote_spinlock_unlock( XPTR( sem_cxy , &sem_ptr->lock ) );
-
-        // block and deschedule
-        thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_SEM );  
-        sched_yield("blocked on semaphore");
+        // get semaphore current value
+        uint32_t count = hal_remote_l32( count_xp );
+
+	    if( count > 0 )                     // success
+	    {
+            // decrement semaphore value
+            hal_remote_s32( count_xp , count - 1 );
+
+#if DEBUG_SEM
+if( (uint32_t)hal_get_cycles() > DEBUG_SEM )
+printk("\n[DBG] %s : thread %x in process %x DECREMENT sem(%x,%x) / value %d\n",
+__FUNCTION__, this->trdid, this->process->pid, sem_cxy, sem_ptr, count-1 );
+#endif
+            // release busylock protecting semaphore
+	        remote_busylock_release( XPTR( sem_cxy , &sem_ptr->lock ) );
+
+            return;
+        }
+	    else                               // failure
+	    {
+            // get cluster and pointers on calling thread
+            cxy_t            caller_cxy = local_cxy;
+            thread_t       * caller_ptr = CURRENT_THREAD;
+            xptr_t           caller_xp  = XPTR( caller_cxy , caller_ptr );
+
+            // block the calling thread
+            thread_block( caller_xp , THREAD_BLOCKED_SEM );  
+
+            // register calling thread in waiting queue
+            xptr_t entry_xp = XPTR( caller_cxy , &caller_ptr->wait_xlist );
+		    xlist_add_last( root_xp , entry_xp );
+
+#if DEBUG_SEM
+if( (uint32_t)hal_get_cycles() > DEBUG_SEM )
+printk("\n[DBG] %s : thread %x in process %x BLOCK on sem(%x,%x) / value %d\n",
+__FUNCTION__, this->trdid, this->process->pid, sem_cxy, sem_ptr, count );
+#endif
+            // release busylock protecting semaphore
+	        remote_busylock_release( XPTR( sem_cxy , &sem_ptr->lock ) );
+
+            // deschedule calling thread
+            sched_yield("blocked on semaphore");
+        }
 	}
 }  // end remote_sem_wait()
@@ -229,38 +266,59 @@
 void remote_sem_post( xptr_t sem_xp )
 {
+    // memory barrier before sem release
+    hal_fence();
+
     // get semaphore cluster and local pointer
     cxy_t          sem_cxy = GET_CXY( sem_xp );
     remote_sem_t * sem_ptr = GET_PTR( sem_xp );
 
-    // get lock protecting semaphore
-	remote_spinlock_lock( XPTR( sem_cxy , &sem_ptr->lock ) );
+    // get extended pointers on sem fields 
+    xptr_t           count_xp = XPTR( sem_cxy , &sem_ptr->count );
+    xptr_t           root_xp  = XPTR( sem_cxy , &sem_ptr->root );
+    xptr_t           lock_xp  = XPTR( sem_cxy , &sem_ptr->lock );
+
+    // get busylock protecting semaphore
+	remote_busylock_acquire( lock_xp );
   
-    // get semaphore current value
-    uint32_t count = hal_remote_lw( XPTR( sem_cxy , &sem_ptr->count ) );
-
-    // get remote pointer on waiting queue root
-    xptr_t root_xp = XPTR( sem_cxy , &sem_ptr->root );
-  
-	if( xlist_is_empty( root_xp ) )   // no waiting thread
-    {
-        // increment semaphore value
-        hal_remote_sw( XPTR( sem_cxy , &sem_ptr->count ) , count + 1 );
-    }
-    else
+    // increment semaphore value
+    hal_remote_atomic_add( count_xp , 1 );
+
+#if DEBUG_SEM
+uint32_t count = hal_remote_l32( count_xp );
+thread_t * this = CURRENT_THREAD;
+if( (uint32_t)hal_get_cycles() > DEBUG_SEM )
+printk("\n[DBG] %s : thread %x in process %x INCREMENT sem(%x,%x) / value %d\n",
+__FUNCTION__, this->trdid, this->process->pid, sem_cxy, sem_ptr, count );
+#endif
+
+    // scan waiting queue to unblock all waiting threads
+	while( xlist_is_empty( root_xp ) == false )   // waiting queue non empty
     {
         // get first waiting thread from queue
-        xptr_t thread_xp = XLIST_FIRST_ELEMENT( root_xp , thread_t , wait_list );
-
-        // get thread cluster and local poiner
+        xptr_t     thread_xp  = XLIST_FIRST( root_xp , thread_t , wait_xlist );
         cxy_t      thread_cxy = GET_CXY( thread_xp );
         thread_t * thread_ptr = GET_PTR( thread_xp );
 
-        // remove this thread from the waiting queue, and unblock it
-        xlist_unlink( XPTR( thread_cxy , &thread_ptr->wait_list ) );
+        // remove this thread from the waiting queue
+        xlist_unlink( XPTR( thread_cxy , &thread_ptr->wait_xlist ) );
+
+        // unblock this waiting thread
 		thread_unblock( thread_xp , THREAD_BLOCKED_SEM );
-    }
-
-    // release lock
-	remote_spinlock_unlock( XPTR( sem_cxy , &sem_ptr->lock ) );
+
+#if DEBUG_SEM
+if( (uint32_t)hal_get_cycles() > DEBUG_SEM )
+{
+trdid_t     trdid   = hal_remote_l32( XPTR( thread_cxy , &thread_ptr->trdid ) );
+process_t * process = hal_remote_lpt( XPTR( thread_cxy , &thread_ptr->process ) );
+pid_t       pid     = hal_remote_l32( XPTR( thread_cxy , &process->pid ) );
+printk("\n[DBG] %s : thread %x in process %x UNBLOCK thread %x in process %x / sem(%x,%x)\n",
+__FUNCTION__, this->trdid, this->process->pid, trdid, pid, sem_cxy, sem_ptr );
+}
+#endif
+
+    }
+
+    // release busylock protecting the semaphore
+	remote_busylock_release( XPTR( sem_cxy , &sem_ptr->lock ) );
 
 }  // end remote_sem_post()
@@ -275,5 +333,5 @@
     remote_sem_t * sem_ptr = GET_PTR( sem_xp );
 
-    *data = hal_remote_lw( XPTR( sem_cxy , &sem_ptr->count ) );
+    *data = hal_remote_l32( XPTR( sem_cxy , &sem_ptr->count ) );
 
 }  // end remote_sem_get_value()
