summaryrefslogtreecommitdiffstats
path: root/Modules/_threadmodule.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_threadmodule.c')
-rw-r--r--Modules/_threadmodule.c60
1 files changed, 31 insertions, 29 deletions
diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c
index 4f8ec2d..d1dc61d 100644
--- a/Modules/_threadmodule.c
+++ b/Modules/_threadmodule.c
@@ -23,6 +23,7 @@ typedef struct {
PyObject_HEAD
PyThread_type_lock lock_lock;
PyObject *in_weakreflist;
+ char locked; /* for sanity checking */
} lockobject;
static void
@@ -32,9 +33,8 @@ lock_dealloc(lockobject *self)
PyObject_ClearWeakRefs((PyObject *) self);
if (self->lock_lock != NULL) {
/* Unlock the lock so it's safe to free it */
- PyThread_acquire_lock(self->lock_lock, 0);
- PyThread_release_lock(self->lock_lock);
-
+ if (self->locked)
+ PyThread_release_lock(self->lock_lock);
PyThread_free_lock(self->lock_lock);
}
PyObject_Del(self);
@@ -53,6 +53,7 @@ acquire_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds)
_PyTime_timeval curtime;
_PyTime_timeval endtime;
+
if (microseconds > 0) {
_PyTime_gettimeofday(&endtime);
endtime.tv_sec += microseconds / (1000 * 1000);
@@ -61,9 +62,13 @@ acquire_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds)
do {
- Py_BEGIN_ALLOW_THREADS
- r = PyThread_acquire_lock_timed(lock, microseconds, 1);
- Py_END_ALLOW_THREADS
+ /* first a simple non-blocking try without releasing the GIL */
+ r = PyThread_acquire_lock_timed(lock, 0, 0);
+ if (r == PY_LOCK_FAILURE && microseconds != 0) {
+ Py_BEGIN_ALLOW_THREADS
+ r = PyThread_acquire_lock_timed(lock, microseconds, 1);
+ Py_END_ALLOW_THREADS
+ }
if (r == PY_LOCK_INTR) {
/* Run signal handlers if we were interrupted. Propagate
@@ -75,7 +80,7 @@ acquire_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds)
/* If we're using a timeout, recompute the timeout after processing
* signals, since those can take time. */
- if (microseconds >= 0) {
+ if (microseconds > 0) {
_PyTime_gettimeofday(&curtime);
microseconds = ((endtime.tv_sec - curtime.tv_sec) * 1000000 +
(endtime.tv_usec - curtime.tv_usec));
@@ -134,6 +139,8 @@ lock_PyThread_acquire_lock(lockobject *self, PyObject *args, PyObject *kwds)
return NULL;
}
+ if (r == PY_LOCK_ACQUIRED)
+ self->locked = 1;
return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
}
@@ -152,13 +159,13 @@ static PyObject *
lock_PyThread_release_lock(lockobject *self)
{
/* Sanity check: the lock must be locked */
- if (PyThread_acquire_lock(self->lock_lock, 0)) {
- PyThread_release_lock(self->lock_lock);
+ if (!self->locked) {
PyErr_SetString(ThreadError, "release unlocked lock");
return NULL;
}
PyThread_release_lock(self->lock_lock);
+ self->locked = 0;
Py_INCREF(Py_None);
return Py_None;
}
@@ -174,11 +181,7 @@ but it needn't be locked by the same thread that unlocks it.");
static PyObject *
lock_locked_lock(lockobject *self)
{
- if (PyThread_acquire_lock(self->lock_lock, 0)) {
- PyThread_release_lock(self->lock_lock);
- return PyBool_FromLong(0L);
- }
- return PyBool_FromLong(1L);
+ return PyBool_FromLong((long)self->locked);
}
PyDoc_STRVAR(locked_doc,
@@ -312,14 +315,7 @@ rlock_acquire(rlockobject *self, PyObject *args, PyObject *kwds)
self->rlock_count = count;
Py_RETURN_TRUE;
}
-
- if (self->rlock_count > 0 ||
- !PyThread_acquire_lock(self->rlock_lock, 0)) {
- if (microseconds == 0) {
- Py_RETURN_FALSE;
- }
- r = acquire_timed(self->rlock_lock, microseconds);
- }
+ r = acquire_timed(self->rlock_lock, microseconds);
if (r == PY_LOCK_ACQUIRED) {
assert(self->rlock_count == 0);
self->rlock_owner = tid;
@@ -413,6 +409,12 @@ rlock_release_save(rlockobject *self)
long owner;
unsigned long count;
+ if (self->rlock_count == 0) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "cannot release un-acquired lock");
+ return NULL;
+ }
+
owner = self->rlock_owner;
count = self->rlock_count;
self->rlock_count = 0;
@@ -541,6 +543,7 @@ newlockobject(void)
if (self == NULL)
return NULL;
self->lock_lock = PyThread_allocate_lock();
+ self->locked = 0;
self->in_weakreflist = NULL;
if (self->lock_lock == NULL) {
Py_DECREF(self);
@@ -1225,11 +1228,9 @@ the suggested approach in the absence of more specific information).");
static PyMethodDef thread_methods[] = {
{"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread,
- METH_VARARGS,
- start_new_doc},
+ METH_VARARGS, start_new_doc},
{"start_new", (PyCFunction)thread_PyThread_start_new_thread,
- METH_VARARGS,
- start_new_doc},
+ METH_VARARGS, start_new_doc},
{"allocate_lock", (PyCFunction)thread_PyThread_allocate_lock,
METH_NOARGS, allocate_doc},
{"allocate", (PyCFunction)thread_PyThread_allocate_lock,
@@ -1245,8 +1246,7 @@ static PyMethodDef thread_methods[] = {
{"_count", (PyCFunction)thread__count,
METH_NOARGS, _count_doc},
{"stack_size", (PyCFunction)thread_stack_size,
- METH_VARARGS,
- stack_size_doc},
+ METH_VARARGS, stack_size_doc},
{NULL, NULL} /* sentinel */
};
@@ -1310,7 +1310,9 @@ PyInit__thread(void)
/* Add a symbolic constant */
d = PyModule_GetDict(m);
- ThreadError = PyErr_NewException("_thread.error", NULL, NULL);
+ ThreadError = PyExc_RuntimeError;
+ Py_INCREF(ThreadError);
+
PyDict_SetItemString(d, "error", ThreadError);
Locktype.tp_doc = lock_doc;
Py_INCREF(&Locktype);