guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] 03/05: Fix fat_mutex owner corruption and other problems


From: Mark H. Weaver
Subject: [Guile-commits] 03/05: Fix fat_mutex owner corruption and other problems in fat_mutex_unlock.
Date: Mon, 20 Jun 2016 19:52:09 +0000 (UTC)

mhw pushed a commit to branch stable-2.0
in repository guile.

commit 1e86dc32a42af549fc9e4721ad48cdd7d296c042
Author: Mark H Weaver <address@hidden>
Date:   Fri Dec 18 02:29:48 2015 -0500

    Fix fat_mutex owner corruption and other problems in fat_mutex_unlock.
    
    Fixes <https://debbugs.gnu.org/22152>.
    Reported by Iwan Aucamp <address@hidden>.
    
    * libguile/threads.c (fat_mutex_unlock): Avoid repeatedly decrementing
      m->level and changing the owner of the mutex when 'block_self' returns
      EINTR.  Unblock asyncs before calling scm_syserror.  Refactor the code
      to clarify the EINTR loop, and to make it more apparent that the async
      blocks and unblocks are balanced.
---
 libguile/threads.c |   87 ++++++++++++++++++++++------------------------------
 1 file changed, 36 insertions(+), 51 deletions(-)

diff --git a/libguile/threads.c b/libguile/threads.c
index 6ae6818..dcbd24d 100644
--- a/libguile/threads.c
+++ b/libguile/threads.c
@@ -1607,70 +1607,55 @@ fat_mutex_unlock (SCM mutex, SCM cond,
        }
     }
 
+  if (m->level > 0)
+    m->level--;
+  if (m->level == 0)
+    {
+      /* Change the owner of MUTEX.  */
+      t->mutexes = scm_delq_x (mutex, t->mutexes);
+      m->owner = unblock_from_queue (m->waiting);
+    }
+
   if (! (SCM_UNBNDP (cond)))
     {
       c = SCM_CONDVAR_DATA (cond);
-      while (1)
-       {
-         int brk = 0;
-
-         if (m->level > 0)
-           m->level--;
-         if (m->level == 0)
-           {
-             /* Change the owner of MUTEX.  */
-             t->mutexes = scm_delq_x (mutex, t->mutexes);
-             m->owner = unblock_from_queue (m->waiting);
-           }
-
-         t->block_asyncs++;
+      t->block_asyncs++;
 
+      do
+       {
          err = block_self (c->waiting, cond, &m->lock, waittime);
          scm_i_pthread_mutex_unlock (&m->lock);
 
-         if (err == 0)
-           {
-             ret = 1;
-             brk = 1;
-           }
-         else if (err == ETIMEDOUT)
-           {
-             ret = 0;
-             brk = 1;
-           }
-         else if (err != EINTR)
-           {
-             errno = err;
-             scm_syserror (NULL);
-           }
-
-         if (brk)
-           {
-             if (relock)
-               scm_lock_mutex_timed (mutex, SCM_UNDEFINED, owner);
-             t->block_asyncs--;
-             break;
-           }
-
-         t->block_asyncs--;
-         scm_async_click ();
+          if (err == EINTR)
+            {
+              t->block_asyncs--;
+              scm_async_click ();
 
-         scm_remember_upto_here_2 (cond, mutex);
+              scm_remember_upto_here_2 (cond, mutex);
 
-         scm_i_scm_pthread_mutex_lock (&m->lock);
+              scm_i_scm_pthread_mutex_lock (&m->lock);
+              t->block_asyncs++;
+            }
        }
+      while (err == EINTR);
+
+      if (err == 0)
+        ret = 1;
+      else if (err == ETIMEDOUT)
+        ret = 0;
+      else
+        {
+          t->block_asyncs--;
+          errno = err;
+          scm_syserror (NULL);
+        }
+
+      if (relock)
+        scm_lock_mutex_timed (mutex, SCM_UNDEFINED, owner);
+      t->block_asyncs--;
     }
   else
     {
-      if (m->level > 0)
-       m->level--;
-      if (m->level == 0)
-       {
-         /* Change the owner of MUTEX.  */
-         t->mutexes = scm_delq_x (mutex, t->mutexes);
-         m->owner = unblock_from_queue (m->waiting);
-       }
-
       scm_i_pthread_mutex_unlock (&m->lock);
       ret = 1;
     }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]