]> granicus.if.org Git - python/commitdiff
bpo-31653: Don't release the GIL if we can acquire a multiprocessing semaphore immedi...
authorAntoine Pitrou <pitrou@free.fr>
Sun, 22 Oct 2017 11:10:46 +0000 (13:10 +0200)
committerGitHub <noreply@github.com>
Sun, 22 Oct 2017 11:10:46 +0000 (13:10 +0200)
Misc/NEWS.d/next/Library/2017-10-22-12-43-03.bpo-31653.ttfGvq.rst [new file with mode: 0644]
Modules/_multiprocessing/semaphore.c

diff --git a/Misc/NEWS.d/next/Library/2017-10-22-12-43-03.bpo-31653.ttfGvq.rst b/Misc/NEWS.d/next/Library/2017-10-22-12-43-03.bpo-31653.ttfGvq.rst
new file mode 100644 (file)
index 0000000..0587a08
--- /dev/null
@@ -0,0 +1,2 @@
+Don't release the GIL if we can acquire a multiprocessing semaphore
+immediately.
index 79e8715a061fb6e0a79138ced6e5018a53994168..337e89432127fa4246daf4fe82fdc9b83367f68e 100644 (file)
@@ -304,19 +304,29 @@ semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds)
         deadline.tv_nsec %= 1000000000;
     }
 
+    /* Check whether we can acquire without releasing the GIL and blocking */
     do {
-        Py_BEGIN_ALLOW_THREADS
-        if (blocking && timeout_obj == Py_None)
-            res = sem_wait(self->handle);
-        else if (!blocking)
-            res = sem_trywait(self->handle);
-        else
-            res = sem_timedwait(self->handle, &deadline);
-        Py_END_ALLOW_THREADS
+        res = sem_trywait(self->handle);
         err = errno;
-        if (res == MP_EXCEPTION_HAS_BEEN_SET)
-            break;
     } while (res < 0 && errno == EINTR && !PyErr_CheckSignals());
+    errno = err;
+
+    if (res < 0 && errno == EAGAIN && blocking) {
+        /* Couldn't acquire immediately, need to block */
+        do {
+            Py_BEGIN_ALLOW_THREADS
+            if (blocking && timeout_obj == Py_None)
+                res = sem_wait(self->handle);
+            else if (!blocking)
+                res = sem_trywait(self->handle);
+            else
+                res = sem_timedwait(self->handle, &deadline);
+            Py_END_ALLOW_THREADS
+            err = errno;
+            if (res == MP_EXCEPTION_HAS_BEEN_SET)
+                break;
+        } while (res < 0 && errno == EINTR && !PyErr_CheckSignals());
+    }
 
     if (res < 0) {
         errno = err;