guile-commits
[Top][All Lists]
Advanced

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

[Guile-commits] 07/08: Optimize lock-mutex


From: Andy Wingo
Subject: [Guile-commits] 07/08: Optimize lock-mutex
Date: Sun, 13 Nov 2016 14:58:54 +0000 (UTC)

wingo pushed a commit to branch master
in repository guile.

commit e0f17417e681aa4591e41f7edb52c7684ca59aae
Author: Andy Wingo <address@hidden>
Date:   Sun Nov 13 15:47:21 2016 +0100

    Optimize lock-mutex
    
    * libguile/threads.c (lock_mutex, scm_timed_lock_mutex): As with
      unlock_mutex before, optimize by specializing to the mutex kind.
      Also, avoid lock thrashing after a return from block_self.
---
 libguile/threads.c |  130 ++++++++++++++++++++++++++++++++++------------------
 1 file changed, 85 insertions(+), 45 deletions(-)

diff --git a/libguile/threads.c b/libguile/threads.c
index fb20f11..f4388ce 100644
--- a/libguile/threads.c
+++ b/libguile/threads.c
@@ -1139,6 +1139,71 @@ scm_lock_mutex (SCM mx)
   return scm_timed_lock_mutex (mx, SCM_UNDEFINED);
 }
 
+static inline SCM
+lock_mutex (enum scm_mutex_kind kind, struct scm_mutex *m,
+            scm_i_thread *current_thread, scm_t_timespec *waittime)
+#define FUNC_NAME "lock-mutex"
+{
+  scm_i_scm_pthread_mutex_lock (&m->lock);
+
+  if (scm_is_eq (m->owner, SCM_BOOL_F))
+    {
+      m->owner = current_thread->handle;
+      scm_i_pthread_mutex_unlock (&m->lock);
+      return SCM_BOOL_T;
+    }
+  else if (kind == SCM_MUTEX_RECURSIVE &&
+           scm_is_eq (m->owner, current_thread->handle))
+    {
+      m->level++;
+      scm_i_pthread_mutex_unlock (&m->lock);
+      return SCM_BOOL_T;
+    }
+  else if (kind == SCM_MUTEX_STANDARD &&
+           scm_is_eq (m->owner, current_thread->handle))
+    {
+      scm_i_pthread_mutex_unlock (&m->lock);
+      SCM_MISC_ERROR ("mutex already locked by thread", SCM_EOL);
+    }
+  else
+    while (1)
+      {
+        int err = block_self (m->waiting, &m->lock, waittime);
+
+        if (err == 0)
+          {
+            if (scm_is_eq (m->owner, SCM_BOOL_F))
+              {
+                m->owner = current_thread->handle;
+                scm_i_pthread_mutex_unlock (&m->lock);
+                return SCM_BOOL_T;
+              }
+            else
+              continue;
+          }
+        else if (err == ETIMEDOUT)
+          {
+            scm_i_pthread_mutex_unlock (&m->lock);
+            return SCM_BOOL_F;
+          }
+        else if (err == EINTR)
+          {
+            scm_i_pthread_mutex_unlock (&m->lock);
+            scm_async_tick ();
+            scm_i_scm_pthread_mutex_lock (&m->lock);
+            continue;
+          }
+        else
+          {
+            /* Shouldn't happen.  */
+            scm_i_pthread_mutex_unlock (&m->lock);
+            errno = err;
+            SCM_SYSERROR;
+          }
+      }
+}
+#undef FUNC_NAME
+
 SCM_DEFINE (scm_timed_lock_mutex, "lock-mutex", 1, 1, 0,
            (SCM mutex, SCM timeout),
            "Lock mutex @var{mutex}. If the mutex is already locked, "
@@ -1146,9 +1211,9 @@ SCM_DEFINE (scm_timed_lock_mutex, "lock-mutex", 1, 1, 0,
 #define FUNC_NAME s_scm_timed_lock_mutex
 {
   scm_t_timespec cwaittime, *waittime = NULL;
-  struct timeval current_time;
   struct scm_mutex *m;
-  SCM new_owner = scm_current_thread();
+  scm_i_thread *t = SCM_I_CURRENT_THREAD;
+  SCM ret;
 
   SCM_VALIDATE_MUTEX (1, mutex);
   m = SCM_MUTEX_DATA (mutex);
@@ -1159,51 +1224,26 @@ SCM_DEFINE (scm_timed_lock_mutex, "lock-mutex", 1, 1, 0,
       waittime = &cwaittime;
     }
 
-  scm_i_scm_pthread_mutex_lock (&m->lock);
-
-  while (1)
+  /* Specialized lock_mutex implementations according to the mutex
+     kind.  */
+  switch (SCM_MUTEX_KIND (mutex))
     {
-      if (scm_is_eq (m->owner, SCM_BOOL_F))
-       {
-         m->owner = new_owner;
-          scm_i_pthread_mutex_unlock (&m->lock);
-          return SCM_BOOL_T;
-       }
-      else if (scm_is_eq (m->owner, new_owner) &&
-               SCM_MUTEX_KIND (mutex) != SCM_MUTEX_UNOWNED)
-       {
-         if (SCM_MUTEX_KIND (mutex) == SCM_MUTEX_RECURSIVE)
-           {
-             m->level++;
-              scm_i_pthread_mutex_unlock (&m->lock);
-              return SCM_BOOL_T;
-           }
-         else
-           {
-              scm_i_pthread_mutex_unlock (&m->lock);
-             SCM_MISC_ERROR ("mutex already locked by thread", SCM_EOL);
-           }
-       }
-      else
-       {
-         if (waittime != NULL)
-           {
-             gettimeofday (&current_time, NULL);
-             if (current_time.tv_sec > waittime->tv_sec ||
-                 (current_time.tv_sec == waittime->tv_sec &&
-                  current_time.tv_usec * 1000 > waittime->tv_nsec))
-               {
-                  scm_i_pthread_mutex_unlock (&m->lock);
-                  return SCM_BOOL_F;
-               }
-           }
-          block_self (m->waiting, &m->lock, waittime);
-          scm_remember_upto_here_1 (mutex);
-         scm_i_pthread_mutex_unlock (&m->lock);
-         SCM_TICK;
-         scm_i_scm_pthread_mutex_lock (&m->lock);
-       }
+    case SCM_MUTEX_STANDARD:
+      ret = lock_mutex (SCM_MUTEX_STANDARD, m, t, waittime);
+      break;
+    case SCM_MUTEX_RECURSIVE:
+      ret = lock_mutex (SCM_MUTEX_RECURSIVE, m, t, waittime);
+      break;
+    case SCM_MUTEX_UNOWNED:
+      ret = lock_mutex (SCM_MUTEX_UNOWNED, m, t, waittime);
+      break;
+    default:
+      abort ();
     }
+
+  scm_remember_upto_here_1 (mutex);
+
+  return ret;
 }
 #undef FUNC_NAME
 



reply via email to

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