changeset 2004:d3a8cc4f7931

* src/common/serial.c (serial_select): Swap the DSR locks and mutex locks around to avoid deadlocks with the rest of the code which uses this order.
author asl
date Tue, 28 Jun 2005 17:56:12 +0000
parents 7725d216c7bc
children 5d432466ea7c
files packages/io/serial/current/ChangeLog packages/io/serial/current/src/common/serial.c
diffstat 2 files changed, 18 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/packages/io/serial/current/ChangeLog
+++ b/packages/io/serial/current/ChangeLog
@@ -1,3 +1,9 @@
+2005-06-27  Andrew Lunn <andrew.lunn@ascom.ch>
+
+	* src/common/serial.c (serial_select): Swap the DSR locks and
+	mutex locks around to avoid deadlocks with the rest of the code
+	which uses this order.
+	
 2005-06-17  Andreas Gaer <andreas.gaer@baslerweb.com>
 
 	* src/common/serial.c (serial_select): Lock DSRs inside
--- a/packages/io/serial/current/src/common/serial.c
+++ b/packages/io/serial/current/src/common/serial.c
@@ -509,14 +509,14 @@ serial_select(cyg_io_handle_t handle, cy
     serial_channel *chan = (serial_channel *)t->priv;
     cyg_bool retval = false;
  
-    cyg_drv_dsr_lock(); // Avoid races
-    
     switch( which )
     {
     case CYG_FREAD:
         {
             cbuf_t *cbuf = &chan->in_cbuf;
+            
             cyg_drv_mutex_lock(&cbuf->lock);
+            cyg_drv_dsr_lock(); // Avoid races
             
             // Check for data in the input buffer. If there is none,
             // register the select operation, otherwise return true.
@@ -524,7 +524,9 @@ serial_select(cyg_io_handle_t handle, cy
             if( cbuf->nb == 0 )
                 cyg_selrecord( info, &cbuf->selinfo );
             else retval = true;
-            cyg_drv_mutex_unlock(&cbuf->lock);        
+
+            cyg_drv_dsr_unlock();
+            cyg_drv_mutex_unlock(&cbuf->lock);
         }
         break;
         
@@ -533,10 +535,13 @@ serial_select(cyg_io_handle_t handle, cy
             // Check for space in the output buffer. If there is none,
             // register the select operation, otherwise return true.
 
+            int space ;
             cbuf_t *cbuf = &chan->out_cbuf;
+            
             cyg_drv_mutex_lock(&cbuf->lock);
-            
-            int space = cbuf->len - cbuf->nb;
+            cyg_drv_dsr_lock(); // Avoid races
+
+            space = cbuf->len - cbuf->nb;
 #ifdef CYGPKG_IO_SERIAL_FLOW_CONTROL
             if ( (space < cbuf->low_water) ||
                  (chan->flow_desc.flags & CYG_SERIAL_FLOW_OUT_THROTTLED) )
@@ -546,7 +551,8 @@ serial_select(cyg_io_handle_t handle, cy
                 cyg_selrecord( info, &cbuf->selinfo );
 #endif
             else retval = true;
-            
+
+            cyg_drv_dsr_unlock();
             cyg_drv_mutex_unlock(&cbuf->lock);
         }
         break;
@@ -554,8 +560,6 @@ serial_select(cyg_io_handle_t handle, cy
     case 0: // exceptions - none supported
         break;
     }
-
-    cyg_drv_dsr_unlock();
     return retval;
 #else