Index: trunk/kernel/libk/remote_rwlock.c
===================================================================
--- trunk/kernel/libk/remote_rwlock.c	(revision 457)
+++ trunk/kernel/libk/remote_rwlock.c	(revision 563)
@@ -31,26 +31,34 @@
 #include <remote_rwlock.h>
 
-///////////////////////////////////////////
-void remote_rwlock_init( xptr_t lock_xp )
+//////////////////////////////////////////////////////////////////////////////
+//                Extern global variables
+//////////////////////////////////////////////////////////////////////////////
+
+extern char * lock_type_str[];          // allocated in kernel_init.c
+
+
+//////////////////////////////////////////
+void remote_rwlock_init( xptr_t   lock_xp,
+                         uint32_t type )
 { 
     remote_rwlock_t * lock_ptr = GET_PTR( lock_xp );
     cxy_t             lock_cxy = GET_CXY( lock_xp );
 
-    hal_remote_sw ( XPTR( lock_cxy , &lock_ptr->ticket )  , 0 );
-    hal_remote_sw ( XPTR( lock_cxy , &lock_ptr->current ) , 0 );
-    hal_remote_sw ( XPTR( lock_cxy , &lock_ptr->count )   , 0 );
-
-#if DEBUG_REMOTE_RWLOCKS
-hal_remote_swd( XPTR( lock_cxy , &lock_ptr->owner )   , XPTR_NULL );
-xlist_entry_init( XPTR( lock_cxy , &lock_ptr->list ) );
-#endif
-
-}
-
-//////////////////////////////////////////////
-void remote_rwlock_rd_lock( xptr_t lock_xp )
+    hal_remote_s32 ( XPTR( lock_cxy , &lock_ptr->taken ) , 0 );
+    hal_remote_s32 ( XPTR( lock_cxy , &lock_ptr->count ) , 0 );
+
+    xlist_root_init( XPTR( lock_cxy , &lock_ptr->rd_xroot ) );
+    xlist_root_init( XPTR( lock_cxy , &lock_ptr->wr_xroot ) );
+
+    remote_busylock_init( XPTR( lock_cxy , &lock_ptr->lock ) , type ); 
+}
+
+///////////////////////////////////////////////
+void remote_rwlock_rd_acquire( xptr_t lock_xp )
 { 
-	reg_t      mode;
-    uint32_t   ticket;
+    thread_t * this = CURRENT_THREAD;
+
+    // check calling thread can yield
+    thread_assert_can_yield( this , __FUNCTION__ );
 
     // get cluster and local pointer on remote_rwlock
@@ -58,52 +66,70 @@
     cxy_t             lock_cxy = GET_CXY( lock_xp );
 
-    // get local pointer on local thread
-    thread_t          * thread_ptr = CURRENT_THREAD;
-
-    // extended pointers on ticket, current, count
-    xptr_t              ticket_xp  = XPTR( lock_cxy   , &lock_ptr->ticket );
-    xptr_t              current_xp = XPTR( lock_cxy   , &lock_ptr->current );
-    xptr_t              count_xp   = XPTR( lock_cxy   , &lock_ptr->count );
-
-    // disable interrupts
-    hal_disable_irq( &mode );
-
-    // get next free ticket
-    ticket = hal_remote_atomic_add( ticket_xp , 1 );
-
-    // busy waiting loop to take the lock 
-	while( ticket != hal_remote_lw( current_xp ) )
-	{
-        hal_fixed_delay( CONFIG_RWLOCK_DELAY );
-	}
-
-    ////////// From here we have the lock  ////////////
-
-    // increment count 
+    // build useful extended pointers
+    xptr_t busylock_xp = XPTR( lock_cxy , &lock_ptr->lock );
+    xptr_t taken_xp    = XPTR( lock_cxy , &lock_ptr->taken );
+    xptr_t count_xp    = XPTR( lock_cxy , &lock_ptr->count );
+    xptr_t rd_root_xp  = XPTR( lock_cxy , &lock_ptr->rd_xroot );
+
+    // get busylock
+    remote_busylock_acquire( busylock_xp );
+
+    // block and deschedule if lock taken
+    while( hal_remote_l32( taken_xp ) )
+    {
+
+#if DEBUG_RWLOCK
+if( DEBUG_RWLOCK < (uint32_t)hal_get_cycles() )
+{
+    uint32_t   type = hal_remote_l32( XPTR( lock_cxy , &lock_ptr->lock.type ) );
+    printk("\n[DBG] %s : thread %x (%s) READ BLOCK on rwlock %s [%x,%x] / cycle %d\n",
+    __FUNCTION__, this->trdid, thread_type_str(this->type),
+    lock_type_str[type], lock_cxy, lock_ptr, (uint32_t)hal_get_cycles() );
+}
+#endif
+        // get pointer on calling thread
+        thread_t * this = CURRENT_THREAD;
+
+        // register reader thread in waiting queue
+        xlist_add_last( rd_root_xp , XPTR( local_cxy , &this->wait_xlist ) );
+
+        // block reader thread
+        thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_LOCK );
+
+        // release busylock
+        remote_busylock_release( busylock_xp );
+
+        // deschedule
+        sched_yield("reader wait remote_rwlock");
+
+        // get busylock
+        remote_busylock_acquire( busylock_xp );
+    }
+
+#if DEBUG_RWLOCK
+if( DEBUG_RWLOCK < (uint32_t)hal_get_cycles() )
+{
+    uint32_t   type = hal_remote_l32( XPTR( lock_cxy , &lock_ptr->lock.type ) );
+    printk("\n[DBG] %s : thread %x (%s) READ ACQUIRE on rwlock %s [%x,%x] / cycle %d\n",
+    __FUNCTION__, this->trdid, thread_type_str(this->type),
+    lock_type_str[type], lock_cxy, lock_ptr, (uint32_t)hal_get_cycles() );
+}
+#endif
+
+    // increment number of readers
     hal_remote_atomic_add( count_xp , 1 );
 
-    // increment thread.remote_locks
-    thread_ptr->remote_locks++;
-
-#if DEBUG_REMOTE_RWLOCKS
-xlist_add_first( XPTR( local_cxy , &thread_ptr->xlocks_root ) ,
-                 XPTR( lock_cxy ,  &lock_ptr->list ) );
-#endif
-
-    // sync
-    hal_fence();
-
-    // release lock to allow several simultaneous readers
-    hal_remote_atomic_add( current_xp , 1 );
-
-    // enable interrupts
-	hal_restore_irq( mode );
-
-}  // end remote_rwlock_rd_lock()
-
-////////////////////////////////////////////////
-void remote_rwlock_rd_unlock( xptr_t lock_xp )
-{
-	reg_t               mode;
+    // release busylock
+    remote_busylock_release( busylock_xp );
+
+}  // end remote_rwlock_rd_acquire()
+
+///////////////////////////////////////////////
+void remote_rwlock_wr_acquire( xptr_t lock_xp )
+{ 
+    thread_t * this = CURRENT_THREAD;
+
+    // check calling thread can yield
+    thread_assert_can_yield( this , __FUNCTION__ );
 
     // get cluster and local pointer on remote_rwlock
@@ -111,36 +137,69 @@
     cxy_t             lock_cxy = GET_CXY( lock_xp );
 
-    // get cluster and local pointer on local thread
-    thread_t          * thread_ptr = CURRENT_THREAD;
-
-    // extended pointers on lock->count 
-    xptr_t              count_xp = XPTR( lock_cxy   , &lock_ptr->count );
-
-    // disable interrupts
-	hal_disable_irq( &mode );
-  
-    // decrement count
-    hal_remote_atomic_add( count_xp , -1 );
-
-    // decrement thread.remote_locks
-	thread_ptr->remote_locks--;
-
-#if DEBUG_REMOTE_RWLOCKS
-xlist_unlink( XPTR( lock_cxy , &lock_ptr->list ) );
-#endif
-
-    // enable interrupts
-	hal_restore_irq( mode );
-    
-    // deschedule if pending request
-    thread_check_sched();
-
-}  // end remote_rwlock_rd_unlock()
-
-//////////////////////////////////////////////
-void remote_rwlock_wr_lock( xptr_t lock_xp )
-{ 
-	reg_t      mode;
-    uint32_t   ticket;
+    // build useful extended pointers
+    xptr_t busylock_xp = XPTR( lock_cxy , &lock_ptr->lock );
+    xptr_t taken_xp    = XPTR( lock_cxy , &lock_ptr->taken );
+    xptr_t count_xp    = XPTR( lock_cxy , &lock_ptr->count );
+    xptr_t wr_root_xp  = XPTR( lock_cxy , &lock_ptr->wr_xroot );
+
+    // get busylock
+    remote_busylock_acquire( busylock_xp );
+
+    // block and deschedule if lock already taken or current readers
+    while( hal_remote_l32( taken_xp ) || hal_remote_l32( count_xp ) )
+    {
+
+#if DEBUG_RWLOCK
+if( DEBUG_RWLOCK < (uint32_t)hal_get_cycles() )
+{
+    uint32_t   type = hal_remote_l32( XPTR( lock_cxy , &lock_ptr->lock.type ) );
+    printk("\n[DBG] %s : thread %x (%s) WRITE BLOCK on rwlock %s [%x,%x] / cycle %d\n",
+    __FUNCTION__, this->trdid, thread_type_str(this->type),
+    lock_type_str[type], lock_cxy, lock_ptr, (uint32_t)hal_get_cycles() );
+}
+#endif
+        // get local pointer on calling thread
+        thread_t * this = CURRENT_THREAD;
+
+        // register writer thread in waiting queue
+        xlist_add_last( wr_root_xp , XPTR( local_cxy , &this->wait_xlist ) );
+
+        // block writer thread
+        thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_LOCK );
+
+        // release busylock
+        remote_busylock_release( busylock_xp );
+
+        // deschedule
+        sched_yield("writer wait remote_rwlock");
+
+        // get busylock
+        remote_busylock_acquire( busylock_xp );
+    }
+
+#if DEBUG_RWLOCK
+if( DEBUG_RWLOCK < (uint32_t)hal_get_cycles() )
+{
+    uint32_t   type = hal_remote_l32( XPTR( lock_cxy , &lock_ptr->lock.type ) );
+    printk("\n[DBG] %s : thread %x (%s) WRITE ACQUIRE on rwlock %s [%x,%x] / cycle %d\n",
+    __FUNCTION__, this->trdid, thread_type_str(this->type),
+    lock_type_str[type], lock_cxy, lock_ptr, (uint32_t)hal_get_cycles() );
+}
+#endif
+
+    // take rwlock
+    hal_remote_s32( taken_xp , 1 );
+
+    // release busylock
+    remote_busylock_release( busylock_xp );
+
+}  // end remote_rwlock_wr_acquire()
+
+
+///////////////////////////////////////////////
+void remote_rwlock_rd_release( xptr_t lock_xp )
+{
+    // memory barrier before lock release
+    hal_fence();
 
     // get cluster and local pointer on remote_rwlock
@@ -148,51 +207,102 @@
     cxy_t             lock_cxy = GET_CXY( lock_xp );
 
-    // get local pointer on local thread
-    thread_t          * thread_ptr = CURRENT_THREAD;
-
-    // compute extended pointers on lock->ticket, lock->owner
-    xptr_t              ticket_xp  = XPTR( lock_cxy   , &lock_ptr->ticket );
-    xptr_t              count_xp   = XPTR( lock_cxy   , &lock_ptr->count );
-    xptr_t              current_xp = XPTR( lock_cxy   , &lock_ptr->current );
-
-    // disable interrupts
-    hal_disable_irq( &mode );
-
-    // get next free ticket
-    ticket = hal_remote_atomic_add( ticket_xp , 1 );
-
-    // loop to take the lock 
-	while( ticket != hal_remote_lw( current_xp ) )
-	{
-        hal_fixed_delay( CONFIG_RWLOCK_DELAY );
-	}
-
-    ////////// From here we have the lock  ////////////
-
-    // wait completion of read accesses
-    while( hal_remote_lw( count_xp ) != 0 )
-    {
-        hal_fixed_delay( CONFIG_RWLOCK_DELAY );
-    }
-
-#if DEBUG_REMOTE_RWLOCKS
-hal_remote_swd( XPTR( lock_cxy  , &lock_ptr->owner ) ,
-                XPTR( local_cxy , thread_ptr ) );
-xlist_add_first( XPTR( local_cxy , &thread_ptr->xlocks_root ) ,
-                 XPTR( lock_cxy  , &lock_ptr->list ) );
-#endif    
-
-    // increment thread.remote_locks
-    thread_ptr->remote_locks++;
-
-    // enable interrupts
-	hal_restore_irq( mode );
-
-}  // end remote_rwlock_wr_lock()
-
-//////////////////////////////////////////////
-void remote_rwlock_wr_unlock( xptr_t lock_xp )
-{
-	reg_t               mode;
+    // build useful extended pointers
+    xptr_t busylock_xp = XPTR( lock_cxy , &lock_ptr->lock );
+    xptr_t count_xp    = XPTR( lock_cxy , &lock_ptr->count );
+    xptr_t rd_root_xp  = XPTR( lock_cxy , &lock_ptr->rd_xroot );
+    xptr_t wr_root_xp  = XPTR( lock_cxy , &lock_ptr->wr_xroot );
+
+    // get busylock
+    remote_busylock_acquire( busylock_xp );
+
+#if DEBUG_RWLOCK
+if( DEBUG_RWLOCK < (uint32_t)hal_get_cycles() )
+{
+    thread_t * this = CURRENT_THREAD;
+    uint32_t   type = hal_remote_l32( XPTR( lock_cxy , &lock_ptr->lock.type ) );
+    printk("\n[DBG] %s : thread %x (%s) READ RELEASE on rwlock %s [%x,%x] / cycle %d\n",
+    __FUNCTION__, this->trdid, thread_type_str(this->type),
+    lock_type_str[type], lock_cxy, lock_ptr, (uint32_t)hal_get_cycles() );
+}
+#endif
+
+	// decrement number of readers
+    hal_remote_atomic_add( count_xp , -1 );
+
+    // release first writer in waiting queue if no current readers
+    // and writers waiting queue non empty
+    if( (hal_remote_l32( count_xp ) == 0) && (xlist_is_empty( wr_root_xp ) == false) )
+    {
+        // get first writer thread
+        xptr_t      thread_xp  = XLIST_FIRST( wr_root_xp , thread_t, wait_xlist );
+        cxy_t       thread_cxy = GET_CXY( thread_xp ); 
+        thread_t *  thread_ptr = GET_PTR( thread_xp ); 
+
+        // remove this waiting thread from waiting list
+        xlist_unlink( XPTR( thread_cxy , &thread_ptr->wait_xlist ) );
+
+        // unblock this waiting thread
+        thread_unblock( thread_xp , THREAD_BLOCKED_LOCK );
+
+#if DEBUG_RWLOCK
+if( (uint32_t)hal_get_cycles() > DEBUG_RWLOCK )
+{
+    thread_t  * this        = CURRENT_THREAD;
+    uint32_t    lock_type   = hal_remote_l32( XPTR( lock_cxy , &lock_ptr->lock.type ) );
+    trdid_t     trdid       = hal_remote_l32( XPTR( thread_cxy , &thread_ptr->trdid ) );
+    uint32_t    thread_type = hal_remote_lpt( XPTR( thread_cxy , &thread_ptr->type ) );
+    printk("\n[DBG] %s : thread %x (%s) UNBLOCK thread %x (%s)"
+    " / rwlock %s [%x,%x] / cycle %d\n",
+    __FUNCTION__, this->trdid, thread_type_str(this->type), trdid, thread_type_str(thread_type), 
+    lock_type_str[lock_type], lock_cxy, lock_ptr, (uint32_t)hal_get_cycles() );
+}
+#endif
+
+    }
+
+    // release all readers in waiting queue if writers waiting queue empty
+    // and readers waiting queue non empty
+    else if( xlist_is_empty( wr_root_xp ) && (xlist_is_empty( rd_root_xp ) == false) )
+    {
+        while( xlist_is_empty( rd_root_xp ) == false )
+        {
+            // get first writer thread
+            xptr_t      thread_xp  = XLIST_FIRST( wr_root_xp , thread_t, wait_xlist );
+            cxy_t       thread_cxy = GET_CXY( thread_xp ); 
+            thread_t *  thread_ptr = GET_PTR( thread_xp ); 
+
+            // remove this waiting thread from waiting list
+            xlist_unlink( XPTR( thread_cxy , &thread_ptr->wait_xlist ) );
+
+            // unblock this waiting thread
+            thread_unblock( thread_xp , THREAD_BLOCKED_LOCK );
+
+#if DEBUG_RWLOCK
+if( (uint32_t)hal_get_cycles() > DEBUG_RWLOCK )
+{
+    thread_t  * this        = CURRENT_THREAD;
+    uint32_t    lock_type   = hal_remote_l32( XPTR( lock_cxy , &lock_ptr->lock.type ) );
+    trdid_t     trdid       = hal_remote_l32( XPTR( thread_cxy , &thread_ptr->trdid ) );
+    uint32_t    thread_type = hal_remote_lpt( XPTR( thread_cxy , &thread_ptr->type ) );
+    printk("\n[DBG] %s : thread %x (%s) UNBLOCK thread %x (%s)"
+    " / rwlock %s [%x,%x] / cycle %d\n",
+    __FUNCTION__, this->trdid, thread_type_str(this->type), trdid, thread_type_str(thread_type), 
+    lock_type_str[lock_type], lock_cxy, lock_ptr, (uint32_t)hal_get_cycles() );
+}
+#endif
+
+        }
+    }
+
+    // release busylock 
+    remote_busylock_release( busylock_xp );
+
+}  // end remote_rwlock_rd_release()
+
+///////////////////////////////////////////////
+void remote_rwlock_wr_release( xptr_t lock_xp )
+{ 
+    // memory barrier before lock release
+    hal_fence();
 
     // get cluster and local pointer on remote_rwlock
@@ -200,51 +310,95 @@
     cxy_t             lock_cxy = GET_CXY( lock_xp );
 
-    // get cluster and local pointer on local thread
-    thread_t          * thread_ptr = CURRENT_THREAD;
-
-    // compute extended pointer on lock->ticket 
-    xptr_t              current_xp = XPTR( lock_cxy   , &lock_ptr->current );
-
-    // disable interrupts
-	hal_disable_irq( &mode );
-  
-#if CONFIG_LOCKS_OWNER
-hal_remote_swd( XPTR( lock_cxy , &lock_ptr->owner ) , XPTR_NULL );
-xlist_unlink( XPTR( lock_cxy , &lock_ptr->list ) );
-#endif
-
-    // release lock
-    hal_remote_atomic_add( current_xp , 1 );
-
-    // decrement thread.remote_locks
-	thread_ptr->remote_locks--;
-
-    // enable interrupts
-	hal_restore_irq( mode );
-    
-    // deschedule if pending request
-    thread_check_sched();
-
-}  // end remote_rwlock_wr_unlock()
-
-///////////////////////////////////////////
-void remote_rwlock_print( xptr_t   lock_xp,
-                          char   * comment )
-{
-    uint32_t     ticket;                // first free ticket index
-    uint32_t     current;               // ticket index of current owner 
-    uint32_t     count;                 // current number of reader threads
-
-    // get cluster and local pointer on remote_rwlock
-    remote_rwlock_t * lock_ptr = GET_PTR( lock_xp );
-    cxy_t             lock_cxy = GET_CXY( lock_xp );
-
-    ticket  = hal_remote_lw ( XPTR( lock_cxy , &lock_ptr->ticket ) );
-    current = hal_remote_lw ( XPTR( lock_cxy , &lock_ptr->current ) );
-    count   = hal_remote_lw ( XPTR( lock_cxy , &lock_ptr->count ) );
-
-    printk("\n*** rwlock <%l> %s : ticket = %d / current = %d / count = %d\n",
-           lock_xp , comment , ticket , current , count ); 
-
-}  // end remote_rwlock_print()
-
+    // build useful extended pointers
+    xptr_t busylock_xp = XPTR( lock_cxy , &lock_ptr->lock );
+    xptr_t taken_xp    = XPTR( lock_cxy , &lock_ptr->taken );
+    xptr_t rd_root_xp  = XPTR( lock_cxy , &lock_ptr->rd_xroot );
+    xptr_t wr_root_xp  = XPTR( lock_cxy , &lock_ptr->wr_xroot );
+
+    // get busylock
+    remote_busylock_acquire( busylock_xp );
+
+#if DEBUG_RWLOCK
+if( DEBUG_RWLOCK < (uint32_t)hal_get_cycles() )
+{
+    thread_t * this = CURRENT_THREAD;
+    uint32_t   type = hal_remote_l32( XPTR( lock_cxy , &lock_ptr->lock.type ) );
+    printk("\n[DBG] %s : thread %x (%s) WRITE RELEASE on rwlock %s [%x,%x] / cycle %d\n",
+    __FUNCTION__, this->trdid, thread_type_str(this->type),
+    lock_type_str[type], lock_cxy, lock_ptr, (uint32_t)hal_get_cycles() );
+}
+#endif
+
+    // release rwlock
+    hal_remote_s32( taken_xp , 0 );
+
+    // unblock first waiting writer thread if writers waiting queue non empty
+    if( xlist_is_empty( wr_root_xp ) == false )
+    {
+        // get first writer thread
+        xptr_t      thread_xp  = XLIST_FIRST( wr_root_xp , thread_t, wait_xlist );
+        cxy_t       thread_cxy = GET_CXY( thread_xp ); 
+        thread_t *  thread_ptr = GET_PTR( thread_xp ); 
+
+        // remove this waiting thread from waiting list
+        xlist_unlink( XPTR( thread_cxy , &thread_ptr->wait_xlist ) );
+
+        // unblock this waiting thread
+        thread_unblock( thread_xp , THREAD_BLOCKED_LOCK );
+
+#if DEBUG_RWLOCK
+if( (uint32_t)hal_get_cycles() > DEBUG_RWLOCK )
+{
+    thread_t  * this        = CURRENT_THREAD;
+    uint32_t    lock_type   = hal_remote_l32( XPTR( lock_cxy , &lock_ptr->lock.type ) );
+    trdid_t     trdid       = hal_remote_l32( XPTR( thread_cxy , &thread_ptr->trdid ) );
+    uint32_t    thread_type = hal_remote_lpt( XPTR( thread_cxy , &thread_ptr->type ) );
+    printk("\n[DBG] %s : thread %x (%s) UNBLOCK thread %x (%s)"
+    " / rwlock %s [%x,%x] / cycle %d\n",
+    __FUNCTION__, this->trdid, thread_type_str(this->type), trdid, thread_type_str(thread_type), 
+    lock_type_str[lock_type], lock_cxy, lock_ptr, (uint32_t)hal_get_cycles() );
+}
+#endif
+
+    }
+
+    // check readers waiting queue and unblock all if writers waiting queue empty
+    else 
+    {
+        while( xlist_is_empty( rd_root_xp ) == false )
+        {
+            // get first writer thread
+            xptr_t      thread_xp  = XLIST_FIRST( rd_root_xp , thread_t, wait_xlist );
+            cxy_t       thread_cxy = GET_CXY( thread_xp ); 
+            thread_t *  thread_ptr = GET_PTR( thread_xp ); 
+
+            // remove this waiting thread from waiting list
+            xlist_unlink( XPTR( thread_cxy , &thread_ptr->wait_xlist ) );
+
+            // unblock this waiting thread
+            thread_unblock( thread_xp , THREAD_BLOCKED_LOCK );
+
+#if DEBUG_RWLOCK
+if( (uint32_t)hal_get_cycles() > DEBUG_RWLOCK )
+{
+    thread_t  * this        = CURRENT_THREAD;
+    uint32_t    lock_type   = hal_remote_l32( XPTR( lock_cxy , &lock_ptr->lock.type ) );
+    trdid_t     trdid       = hal_remote_l32( XPTR( thread_cxy , &thread_ptr->trdid ) );
+    uint32_t    thread_type = hal_remote_lpt( XPTR( thread_cxy , &thread_ptr->type ) );
+    printk("\n[DBG] %s : thread %x (%s) UNBLOCK thread %x (%s)"
+    " / rwlock %s [%x,%x] / cycle %d\n",
+    __FUNCTION__, this->trdid, thread_type_str(this->type), trdid, thread_type_str(thread_type), 
+    lock_type_str[lock_type], lock_cxy, lock_ptr, (uint32_t)hal_get_cycles() );
+}
+#endif
+
+        }
+    }
+
+    // release busylock 
+    remote_busylock_release( busylock_xp );
+
+}  // end remote_rwlock_wr_release()
+
+
+
