This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author Daniel Colascione
Recipients Daniel Colascione
Date 2017-10-01.01:43:00
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1506822182.01.0.213398074469.issue31653@psf.upfronthosting.co.za>
In-reply-to
Content
Right now, the main loop in semlock_acquire looks like this:

    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());

Here, we unconditionally release the GIL even we could acquire the mutex without blocking! As a result, we could end up switching to another thread in the process and greatly increasing the latency of operations that lock and release multiple shared data structures.

Instead, we should unconditionally try sem_trywait, and only then, if we want to block, release the GIL and try sem_wait or sem_timedwait. This way, we'll churn only when we need to.

Note that threading.Lock works the way I propose.
History
Date User Action Args
2017-10-01 01:43:02Daniel Colascionesetrecipients: + Daniel Colascione
2017-10-01 01:43:02Daniel Colascionesetmessageid: <1506822182.01.0.213398074469.issue31653@psf.upfronthosting.co.za>
2017-10-01 01:43:01Daniel Colascionelinkissue31653 messages
2017-10-01 01:43:00Daniel Colascionecreate