Index: trunk/kernel/libk/rwlock.c
===================================================================
--- trunk/kernel/libk/rwlock.c	(revision 457)
+++ trunk/kernel/libk/rwlock.c	(revision 563)
@@ -1,4 +1,4 @@
 /*
- * rwlock.c - kernel read/write lock synchronization.
+ * rwlock.c - kernel local read/write lock implementation.
  * 
  * Author  Alain Greiner     (2016,2017,2018)
@@ -31,144 +31,296 @@
 #include <rwlock.h>
 
-///////////////////////////////////////
-void rwlock_init( rwlock_t * lock )
+//////////////////////////////////////////////////////////////////////////////
+//                Extern global variables
+//////////////////////////////////////////////////////////////////////////////
+
+extern char * lock_type_str[];          // allocated in kernel_init.c
+
+
+//////////////////////////////////
+void rwlock_init( rwlock_t * lock,
+                  uint32_t   type )
 {  
-	lock->ticket  = 0;
-    lock->current = 0;
+	lock->taken   = 0;
     lock->count   = 0;
 
-#if DEBUG_RWLOCKS
-lock->owner   = NULL;
-list_entry_init( &lock->list ); 
-#endif
-
-}
-
-//////////////////////////////////////
-void rwlock_rd_lock( rwlock_t * lock )
-{
-	reg_t               mode;
-	uint32_t            ticket;
-	thread_t          * this = CURRENT_THREAD;
-
-    // disable IRQs
-	hal_disable_irq( &mode );
-
-    // get next free ticket
-    ticket = hal_atomic_add( &lock->ticket , 1 );
-  
-    // poll the current ticket value
-	while( lock->current != ticket )
-    {
-        hal_fixed_delay( CONFIG_RWLOCK_DELAY );
-    }
-
-    ////////// From here we have the lock  ////////////
+    list_root_init( &lock->rd_root );
+    list_root_init( &lock->wr_root );
+
+    busylock_init( &lock->lock , type );
+}
+
+/////////////////////////////////////////
+void rwlock_rd_acquire( rwlock_t * lock )
+{
+    thread_t * this = CURRENT_THREAD;
+
+    // check calling thread can yield
+    thread_assert_can_yield( this , __FUNCTION__ );
+
+    // get busylock
+    busylock_acquire( &lock->lock );
+
+    // block and deschedule if lock already taken
+    while( lock->taken )
+    {
+
+#if DEBUG_RWLOCK
+if( DEBUG_RWLOCK < (uint32_t)hal_get_cycles() )
+{
+    printk("\n[DBG] %s : thread %x in process %x READ BLOCK on rwlock %s [%x,%x]\n",
+    __FUNCTION__, this->trdid, this->process->pid,
+    lock_type_str[lock->lock.type], local_cxy, lock );
+}
+#endif
+        // get pointer on calling thread
+        thread_t * this = CURRENT_THREAD;
+
+        // register reader thread in waiting queue
+        list_add_last( &lock->rd_root , &this->wait_list );
+
+        // block reader thread
+        thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_LOCK );
+        
+        // release busylock
+        busylock_release( &lock->lock );
+
+        // deschedule
+        sched_yield("reader wait rwlock");
+        
+        // get busylock
+        busylock_acquire( &lock->lock );
+    }
+
+#if DEBUG_RWLOCK
+if( DEBUG_RWLOCK < (uint32_t)hal_get_cycles() )
+{
+    printk("\n[DBG] %s : thread %x in process READ ACQUIRE on rwlock %s [%x,%x]\n",
+    __FUNCTION__, this->trdid, this->process->pid, 
+    lock_type_str[lock->lock.type], local_cxy, lock );
+}
+#endif
 
     // increment number of readers
     lock->count++;
-    this->local_locks++;
-
-#if DEBUG_RWLOCKS
-list_add_first( &this->locks_root , &lock->list );
-#endif
-
-    // consistency
+
+    // release busylock 
+    busylock_release( &lock->lock );
+
+}  // end rwlock_rd_acquire() 
+
+/////////////////////////////////////////
+void rwlock_wr_acquire( rwlock_t * lock )
+{
+    thread_t * this = CURRENT_THREAD;
+
+    // check calling thread can yield
+    thread_assert_can_yield( this , __FUNCTION__ );
+
+    // get busylock
+    busylock_acquire( &lock->lock );
+
+    // block and deschedule if lock already taken or existing read access
+    while( lock->taken || lock->count )
+    {
+
+#if DEBUG_RWLOCK
+if( DEBUG_RWLOCK < (uint32_t)hal_get_cycles() )
+{
+    printk("\n[DBG] %s : thread %x in process WRITE BLOCK on rwlock %s [%x,%x]\n",
+    __FUNCTION__, this->trdid, this->process->pid, 
+    lock_type_str[lock->lock.type], local_cxy, lock );
+}
+#endif
+        // get pointer on calling thread
+        thread_t * this = CURRENT_THREAD;
+
+        // register writer in waiting queue
+        list_add_last( &lock->wr_root , &this->wait_list );
+
+        // block reader thread
+        thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_LOCK );
+        
+        // release busylock
+        busylock_release( &lock->lock );
+
+        // deschedule
+        sched_yield("writer wait rwlock");
+        
+        // get busylock
+        busylock_acquire( &lock->lock );
+    }
+
+#if DEBUG_RWLOCK
+if( DEBUG_RWLOCK < (uint32_t)hal_get_cycles() )
+{
+    printk("\n[DBG] %s : thread %x in process WRITE ACQUIRE on rwlock %s [%x,%x]\n",
+    __FUNCTION__, this->trdid, this->process->pid, 
+    lock_type_str[lock->lock.type], local_cxy, lock );
+}
+#endif
+
+    // take the rwlock
+    lock->taken = 1;
+
+    // release busylock 
+    busylock_release( &lock->lock );
+
+}  // end rwlock_wr_acquire()
+
+/////////////////////////////////////////
+void rwlock_rd_release( rwlock_t * lock )
+{
+    // synchronize memory before lock release
     hal_fence();
 
-    // release the lock to allow several simultaneous readers
-    lock->current++;
-
-    // enable IRQs
-	hal_restore_irq( mode );
-
-}  // end  rwlock_rd_lock()
-
-////////////////////////////////////////
-void rwlock_rd_unlock( rwlock_t * lock )
-{
-    reg_t      mode;
-	thread_t * this = CURRENT_THREAD;
-
-    // disable IRQs
-	hal_disable_irq( &mode );
-  
+    // get busylock
+    busylock_acquire( &lock->lock );
+
+#if DEBUG_RWLOCK
+if( DEBUG_RWLOCK < (uint32_t)hal_get_cycles() )
+{
+    thread_t * this = CURRENT_THREAD;
+    printk("\n[DBG] %s : thread %x in process READ RELEASE on rwlock %s [%x,%x]\n",
+    __FUNCTION__, this->trdid, this->process->pid, 
+    lock_type_str[lock->lock.type], local_cxy, lock );
+}
+#endif
+
     // decrement number of readers
-    hal_atomic_add( &lock->count , -1 );
-    this->local_locks--;
-
-#if DEBUG_RWLOCKS
-list_unlink( &lock->list );
-#endif
-
-    // enable IRQs
-	hal_restore_irq( mode );
-
-    // deschedule if pending request
-    thread_check_sched();
-}
-
-//////////////////////////////////////
-void rwlock_wr_lock( rwlock_t * lock )
-{
-	reg_t              mode;
-    uint32_t           ticket;
-	thread_t         * this = CURRENT_THREAD;
-
-    // disable IRQs
-	hal_disable_irq( &mode );
-  
-    // get next free ticket
-    ticket = hal_atomic_add( &lock->ticket , 1 );
-  
-    // poll the current ticket value
-	while( lock->current != ticket )
-    {
-        hal_fixed_delay( CONFIG_RWLOCK_DELAY );
-    } 
-
-    ////////// From here we have the lock  ////////////
-
-    // wait completion of existing read access
-    while( lock->count != 0 )
-    {
-        hal_fixed_delay( CONFIG_RWLOCK_DELAY );
-    }
-
-    this->local_locks++;
-
-#if DEBUG_RWLOCKS
-lock->owner = this;
-list_add_first( &this->locks_root , &lock->list );
-#endif
-
-    // enable IRQs
-	hal_restore_irq( mode );
-
-}  // end rwlock_wr_lock()
-
-////////////////////////////////////////////
-void rwlock_wr_unlock( rwlock_t * lock )
-{
-    reg_t      mode;
-	thread_t * this = CURRENT_THREAD;
-
-    // disable IRQs
-	hal_disable_irq( &mode );
-  
-#if DEBUG_RWLOCKS
-lock->owner = NULL;
-list_unlink( &lock->list );
-#endif
-
-    // release lock
-    lock->current++;
-    this->local_locks--;
-
-    // enable IRQs
-	hal_restore_irq( mode );
-    
-    // deschedule if pending request
-    thread_check_sched();
-}
-
+    lock->count--;
+
+    // release first writer in waiting queue if no current readers
+    // and writers waiting queue non empty
+    if( (lock->count == 0) && (list_is_empty( &lock->wr_root ) == false) )
+    {
+        // get first writer thread
+        thread_t * thread = LIST_FIRST( &lock->wr_root , thread_t , wait_list );
+
+#if DEBUG_RWLOCK
+if( DEBUG_RWLOCK < (uint32_t)hal_get_cycles() )
+{
+    thread_t * this = CURRENT_THREAD;
+    printk("\n[DBG] %s : thread %x in process %x UNBLOCK thread %x in process %d"
+    " / rwlock %s [%x,%x]\n",
+    __FUNCTION__, this->trdid, this->process->pid, thread->trdid, thread->process->pid,
+    lock_type_str[lock->lock.type], local_cxy, lock );
+}
+#endif
+
+        // remove this waiting thread from waiting list
+        list_unlink( &thread->wait_list );
+
+        // unblock this waiting thread
+        thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_LOCK );
+    }
+    // release all readers in waiting queue if writers waiting queue empty
+    // and readers waiting queue non empty
+    else if( list_is_empty( &lock->wr_root ) && (list_is_empty( &lock->rd_root ) == false) )
+    {
+        while( list_is_empty( &lock->rd_root ) == false )
+        {
+            // get first reader thread 
+            thread_t * thread = LIST_FIRST( &lock->wr_root , thread_t , wait_list );
+
+#if DEBUG_RWLOCK
+if( DEBUG_RWLOCK < (uint32_t)hal_get_cycles() )
+{
+    thread_t * this = CURRENT_THREAD;
+    printk("\n[DBG] %s : thread %x in process %x UNBLOCK thread %x in process %d"
+    " / rwlock %s [%x,%x]\n",
+    __FUNCTION__, this->trdid, this->process->pid, thread->trdid, thread->process->pid,
+    lock_type_str[lock->lock.type], local_cxy, lock );
+}
+#endif
+   
+            // remove this waiting thread from waiting list
+            list_unlink( &thread->wait_list );
+
+            // unblock this waiting thread
+            thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_LOCK );
+        }
+    }
+
+    // release busylock 
+    busylock_release( &lock->lock );
+
+}  // end rwlock_rd_release()
+
+/////////////////////////////////////////
+void rwlock_wr_release( rwlock_t * lock )
+{
+    // synchronize memory before lock release
+    hal_fence();
+
+    // get busylock
+    busylock_acquire( &lock->lock );
+
+#if DEBUG_RWLOCK
+if( DEBUG_RWLOCK < (uint32_t)hal_get_cycles() )
+{
+    thread_t * this = CURRENT_THREAD;
+    printk("\n[DBG] %s : thread %x in process WRITE RELEASE on rwlock %s [%x,%x]\n",
+    __FUNCTION__, this->trdid, this->process->pid,
+    lock_type_str[lock->lock.type], local_cxy, lock );
+}
+#endif
+
+    // release the rwlock
+    lock->taken = 0;
+
+    // release first waiting writer thread if writers waiting queue non empty
+    if( list_is_empty( &lock->wr_root ) == false )
+    {
+        // get first writer thread
+        thread_t * thread = LIST_FIRST( &lock->wr_root , thread_t , wait_list );
+
+#if DEBUG_RWLOCK
+if( DEBUG_RWLOCK < (uint32_t)hal_get_cycles() )
+{
+    thread_t * this = CURRENT_THREAD;
+    printk("\n[DBG] %s : thread %x in process %x UNBLOCK thread %x in process %d"
+    " / rwlock %s [%x,%x]\n",
+    __FUNCTION__, this->trdid, this->process->pid, thread->trdid, thread->process->pid,
+    lock_type_str[lock->lock.type], local_cxy, lock );
+}
+#endif
+        // remove this waiting thread from waiting list
+        list_unlink( &thread->wait_list );
+
+        // unblock this waiting thread
+        thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_LOCK );
+    }
+
+    // check readers waiting queue and release all if writers waiting queue empty
+    else 
+    {
+        while( list_is_empty( &lock->rd_root ) == false )
+        {
+            // get first reader thread 
+            thread_t * thread = LIST_FIRST( &lock->rd_root , thread_t , wait_list );
+
+#if DEBUG_RWLOCK
+if( DEBUG_RWLOCK < (uint32_t)hal_get_cycles() )
+{
+    thread_t * this = CURRENT_THREAD;
+    printk("\n[DBG] %s : thread %x in process %x UNBLOCK thread %x in process %d"
+    " / rwlock %s [%x,%x]\n",
+    __FUNCTION__, this->trdid, this->process->pid, thread->trdid, thread->process->pid,
+    lock_type_str[lock->lock.type], local_cxy, lock );
+}
+#endif
+            // remove this waiting thread from waiting list
+            list_unlink( &thread->wait_list );
+
+            // unblock this waiting thread
+            thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_LOCK );
+        }
+    }
+
+    // release busylock 
+    busylock_release( &lock->lock );
+
+}  // end rwlock_wr_release()
+
+
