[pypy-commit] pypy default: Performance: avoid releasing the GIL around thread.lock.release(),

arigo noreply at buildbot.pypy.org
Wed Feb 18 12:34:13 CET 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r75975:b190e63c3c3c
Date: 2015-02-18 11:41 +0100
http://bitbucket.org/pypy/pypy/changeset/b190e63c3c3c/

Log:	Performance: avoid releasing the GIL around thread.lock.release(),
	as well as around uncontended thread.lock.acquire().

diff --git a/rpython/rlib/rthread.py b/rpython/rlib/rthread.py
--- a/rpython/rlib/rthread.py
+++ b/rpython/rlib/rthread.py
@@ -59,16 +59,18 @@
                                         rffi.INT,
                                         releasegil=True)    # release the GIL
 c_thread_releaselock = llexternal('RPyThreadReleaseLock', [TLOCKP], lltype.Void,
-                                  releasegil=True)    # release the GIL
+                                  _nowrapper=True)   # *don't* release the GIL
 
 # another set of functions, this time in versions that don't cause the
-# GIL to be released.  To use to handle the GIL lock itself.
+# GIL to be released.  Used to be there to handle the GIL lock itself,
+# but that was changed (see rgil.py).  Now here for performance only.
 c_thread_acquirelock_NOAUTO = llexternal('RPyThreadAcquireLock',
                                          [TLOCKP, rffi.INT], rffi.INT,
                                          _nowrapper=True)
-c_thread_releaselock_NOAUTO = llexternal('RPyThreadReleaseLock',
-                                         [TLOCKP], lltype.Void,
-                                         _nowrapper=True)
+c_thread_acquirelock_timed_NOAUTO = llexternal('RPyThreadAcquireLockTimed',
+                                         [TLOCKP, rffi.LONGLONG, rffi.INT],
+                                         rffi.INT, _nowrapper=True)
+c_thread_releaselock_NOAUTO = c_thread_releaselock
 
 
 def allocate_lock():
@@ -131,9 +133,21 @@
         self._lock = ll_lock
 
     def acquire(self, flag):
-        res = c_thread_acquirelock(self._lock, int(flag))
+        # fast-path: try to acquire the lock without releasing the GIL
+        res = c_thread_acquirelock_timed_NOAUTO(
+            self._lock,
+            rffi.cast(rffi.LONGLONG, 0),
+            rffi.cast(rffi.INT, 0))
         res = rffi.cast(lltype.Signed, res)
-        return bool(res)
+        if not flag:
+            # acquire(False): return a boolean that says if it worked
+            return res != 0
+        else:
+            # acquire(True): if res == 0, we must invoke the slow-path
+            # releasing the GIL.  This is done with conditional_call() to
+            # avoid JIT branches.
+            jit.conditional_call(res == 0, c_thread_acquirelock, self._lock, 1)
+            return True
 
     def acquire_timed(self, timeout):
         """Timeout is in microseconds.  Returns 0 in case of failure,


More information about the pypy-commit mailing list