| LEFT | RIGHT |
| 1 | 1 |
| 2 /* Thread module */ | 2 /* Thread module */ |
| 3 /* Interface to Sjoerd's portable C thread library */ | 3 /* Interface to Sjoerd's portable C thread library */ |
| 4 | 4 |
| 5 #include "Python.h" | 5 #include "Python.h" |
| 6 #include "structmember.h" /* offsetof */ | 6 #include "structmember.h" /* offsetof */ |
| 7 | 7 |
| 8 #ifndef WITH_THREAD | 8 #ifndef WITH_THREAD |
| 9 #error "Error! The rest of Python is not compiled with thread support." | 9 #error "Error! The rest of Python is not compiled with thread support." |
| 10 #error "Rerun configure, adding a --with-threads option." | 10 #error "Rerun configure, adding a --with-threads option." |
| 11 #error "Then run `make clean' followed by `make'." | 11 #error "Then run `make clean' followed by `make'." |
| 12 #endif | 12 #endif |
| 13 | 13 |
| 14 #include "pythread.h" | 14 #include "pythread.h" |
| 15 | 15 |
| 16 static PyObject *ThreadError; | 16 static PyObject *ThreadError; |
| 17 static long nb_threads = 0; | 17 static long nb_threads = 0; |
| 18 static PyObject *str_dict; | 18 static PyObject *str_dict; |
| 19 | 19 |
| 20 /* Lock objects */ | 20 /* Lock objects */ |
| 21 | 21 |
| 22 typedef struct { | 22 typedef struct { |
| 23 PyObject_HEAD | 23 PyObject_HEAD |
| 24 PyThread_type_lock lock_lock; | 24 PyThread_type_lock lock_lock; |
| 25 PyObject *in_weakreflist; | 25 PyObject *in_weakreflist; |
| 26 char locked; /* for sanity checking */ |
| 26 } lockobject; | 27 } lockobject; |
| 27 | 28 |
| 28 static void | 29 static void |
| 29 lock_dealloc(lockobject *self) | 30 lock_dealloc(lockobject *self) |
| 30 { | 31 { |
| 31 if (self->in_weakreflist != NULL) | 32 if (self->in_weakreflist != NULL) |
| 32 PyObject_ClearWeakRefs((PyObject *) self); | 33 PyObject_ClearWeakRefs((PyObject *) self); |
| 33 if (self->lock_lock != NULL) { | 34 if (self->lock_lock != NULL) { |
| 34 /* Unlock the lock so it's safe to free it */ | 35 /* Unlock the lock so it's safe to free it */ |
| 35 PyThread_acquire_lock(self->lock_lock, 0); | 36 if (self->locked) |
| 36 PyThread_release_lock(self->lock_lock); | 37 PyThread_release_lock(self->lock_lock); |
| 37 | |
| 38 PyThread_free_lock(self->lock_lock); | 38 PyThread_free_lock(self->lock_lock); |
| 39 } | 39 } |
| 40 PyObject_Del(self); | 40 PyObject_Del(self); |
| 41 } | 41 } |
| 42 | 42 |
| 43 /* Helper to acquire an interruptible lock with a timeout. If the lock acquire | 43 /* Helper to acquire an interruptible lock with a timeout. If the lock acquire |
| 44 * is interrupted, signal handlers are run, and if they raise an exception, | 44 * is interrupted, signal handlers are run, and if they raise an exception, |
| 45 * PY_LOCK_INTR is returned. Otherwise, PY_LOCK_ACQUIRED or PY_LOCK_FAILURE | 45 * PY_LOCK_INTR is returned. Otherwise, PY_LOCK_ACQUIRED or PY_LOCK_FAILURE |
| 46 * are returned, depending on whether the lock can be acquired withing the | 46 * are returned, depending on whether the lock can be acquired withing the |
| 47 * timeout. | 47 * timeout. |
| 48 */ | 48 */ |
| 49 static PyLockStatus | 49 static PyLockStatus |
| 50 acquire_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds) | 50 acquire_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds) |
| 51 { | 51 { |
| 52 PyLockStatus r; | 52 PyLockStatus r; |
| 53 _PyTime_timeval curtime; | 53 _PyTime_timeval curtime; |
| 54 _PyTime_timeval endtime; | 54 _PyTime_timeval endtime; |
| 55 | 55 |
| 56 | 56 |
| 57 if (microseconds > 0) { | 57 if (microseconds > 0) { |
| 58 _PyTime_gettimeofday(&endtime); | 58 _PyTime_gettimeofday(&endtime); |
| 59 endtime.tv_sec += microseconds / (1000 * 1000); | 59 endtime.tv_sec += microseconds / (1000 * 1000); |
| 60 endtime.tv_usec += microseconds % (1000 * 1000); | 60 endtime.tv_usec += microseconds % (1000 * 1000); |
| 61 } | 61 } |
| 62 | 62 |
| 63 | 63 |
| 64 do { | 64 do { |
| 65 Py_BEGIN_ALLOW_THREADS | 65 /* first a simple non-blocking try without releasing the GIL */ |
| 66 r = PyThread_acquire_lock_timed(lock, microseconds, 1); | 66 r = PyThread_acquire_lock_timed(lock, 0, 0); |
| 67 Py_END_ALLOW_THREADS | 67 if (r == PY_LOCK_FAILURE && microseconds != 0) { |
| 68 Py_BEGIN_ALLOW_THREADS |
| 69 r = PyThread_acquire_lock_timed(lock, microseconds, 1); |
| 70 Py_END_ALLOW_THREADS |
| 71 } |
| 68 | 72 |
| 69 if (r == PY_LOCK_INTR) { | 73 if (r == PY_LOCK_INTR) { |
| 70 /* Run signal handlers if we were interrupted. Propagate | 74 /* Run signal handlers if we were interrupted. Propagate |
| 71 * exceptions from signal handlers, such as KeyboardInterrupt, by | 75 * exceptions from signal handlers, such as KeyboardInterrupt, by |
| 72 * passing up PY_LOCK_INTR. */ | 76 * passing up PY_LOCK_INTR. */ |
| 73 if (Py_MakePendingCalls() < 0) { | 77 if (Py_MakePendingCalls() < 0) { |
| 74 return PY_LOCK_INTR; | 78 return PY_LOCK_INTR; |
| 75 } | 79 } |
| 76 | 80 |
| 77 /* If we're using a timeout, recompute the timeout after processing | 81 /* If we're using a timeout, recompute the timeout after processing |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 return NULL; | 132 return NULL; |
| 129 } | 133 } |
| 130 microseconds = (PY_TIMEOUT_T) timeout; | 134 microseconds = (PY_TIMEOUT_T) timeout; |
| 131 } | 135 } |
| 132 | 136 |
| 133 r = acquire_timed(self->lock_lock, microseconds); | 137 r = acquire_timed(self->lock_lock, microseconds); |
| 134 if (r == PY_LOCK_INTR) { | 138 if (r == PY_LOCK_INTR) { |
| 135 return NULL; | 139 return NULL; |
| 136 } | 140 } |
| 137 | 141 |
| 142 if (r == PY_LOCK_ACQUIRED) |
| 143 self->locked = 1; |
| 138 return PyBool_FromLong(r == PY_LOCK_ACQUIRED); | 144 return PyBool_FromLong(r == PY_LOCK_ACQUIRED); |
| 139 } | 145 } |
| 140 | 146 |
| 141 PyDoc_STRVAR(acquire_doc, | 147 PyDoc_STRVAR(acquire_doc, |
| 142 "acquire([wait]) -> None or bool\n\ | 148 "acquire([wait]) -> None or bool\n\ |
| 143 (acquire_lock() is an obsolete synonym)\n\ | 149 (acquire_lock() is an obsolete synonym)\n\ |
| 144 \n\ | 150 \n\ |
| 145 Lock the lock. Without argument, this blocks if the lock is already\n\ | 151 Lock the lock. Without argument, this blocks if the lock is already\n\ |
| 146 locked (even by the same thread), waiting for another thread to release\n\ | 152 locked (even by the same thread), waiting for another thread to release\n\ |
| 147 the lock, and return None once the lock is acquired.\n\ | 153 the lock, and return None once the lock is acquired.\n\ |
| 148 With an argument, this will only block if the argument is true,\n\ | 154 With an argument, this will only block if the argument is true,\n\ |
| 149 and the return value reflects whether the lock is acquired.\n\ | 155 and the return value reflects whether the lock is acquired.\n\ |
| 150 The blocking operation is interruptible."); | 156 The blocking operation is interruptible."); |
| 151 | 157 |
| 152 static PyObject * | 158 static PyObject * |
| 153 lock_PyThread_release_lock(lockobject *self) | 159 lock_PyThread_release_lock(lockobject *self) |
| 154 { | 160 { |
| 155 /* Sanity check: the lock must be locked */ | 161 /* Sanity check: the lock must be locked */ |
| 156 if (PyThread_acquire_lock(self->lock_lock, 0)) { | 162 if (!self->locked) { |
| 157 PyThread_release_lock(self->lock_lock); | |
| 158 PyErr_SetString(ThreadError, "release unlocked lock"); | 163 PyErr_SetString(ThreadError, "release unlocked lock"); |
| 159 return NULL; | 164 return NULL; |
| 160 } | 165 } |
| 161 | 166 |
| 162 PyThread_release_lock(self->lock_lock); | 167 PyThread_release_lock(self->lock_lock); |
| 168 self->locked = 0; |
| 163 Py_INCREF(Py_None); | 169 Py_INCREF(Py_None); |
| 164 return Py_None; | 170 return Py_None; |
| 165 } | 171 } |
| 166 | 172 |
| 167 PyDoc_STRVAR(release_doc, | 173 PyDoc_STRVAR(release_doc, |
| 168 "release()\n\ | 174 "release()\n\ |
| 169 (release_lock() is an obsolete synonym)\n\ | 175 (release_lock() is an obsolete synonym)\n\ |
| 170 \n\ | 176 \n\ |
| 171 Release the lock, allowing another thread that is blocked waiting for\n\ | 177 Release the lock, allowing another thread that is blocked waiting for\n\ |
| 172 the lock to acquire the lock. The lock must be in the locked state,\n\ | 178 the lock to acquire the lock. The lock must be in the locked state,\n\ |
| 173 but it needn't be locked by the same thread that unlocks it."); | 179 but it needn't be locked by the same thread that unlocks it."); |
| 174 | 180 |
| 175 static PyObject * | 181 static PyObject * |
| 176 lock_locked_lock(lockobject *self) | 182 lock_locked_lock(lockobject *self) |
| 177 { | 183 { |
| 178 if (PyThread_acquire_lock(self->lock_lock, 0)) { | 184 return PyBool_FromLong((long)self->locked); |
| 179 PyThread_release_lock(self->lock_lock); | |
| 180 return PyBool_FromLong(0L); | |
| 181 } | |
| 182 return PyBool_FromLong(1L); | |
| 183 } | 185 } |
| 184 | 186 |
| 185 PyDoc_STRVAR(locked_doc, | 187 PyDoc_STRVAR(locked_doc, |
| 186 "locked() -> bool\n\ | 188 "locked() -> bool\n\ |
| 187 (locked_lock() is an obsolete synonym)\n\ | 189 (locked_lock() is an obsolete synonym)\n\ |
| 188 \n\ | 190 \n\ |
| 189 Return whether the lock is in the locked state."); | 191 Return whether the lock is in the locked state."); |
| 190 | 192 |
| 191 PyDoc_STRVAR(lock_release_save_doc, | 193 PyDoc_STRVAR(lock_release_save_doc, |
| 192 "_release_save() -> state\n\ | 194 "_release_save() -> state\n\ |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 if (self->rlock_count > 0 && tid == self->rlock_owner) { | 342 if (self->rlock_count > 0 && tid == self->rlock_owner) { |
| 341 unsigned long count = self->rlock_count + 1; | 343 unsigned long count = self->rlock_count + 1; |
| 342 if (count <= self->rlock_count) { | 344 if (count <= self->rlock_count) { |
| 343 PyErr_SetString(PyExc_OverflowError, | 345 PyErr_SetString(PyExc_OverflowError, |
| 344 "Internal lock count overflowed"); | 346 "Internal lock count overflowed"); |
| 345 return NULL; | 347 return NULL; |
| 346 } | 348 } |
| 347 self->rlock_count = count; | 349 self->rlock_count = count; |
| 348 Py_RETURN_TRUE; | 350 Py_RETURN_TRUE; |
| 349 } | 351 } |
| 350 | 352 r = acquire_timed(self->rlock_lock, microseconds); |
| 351 if (self->rlock_count > 0 || | |
| 352 !PyThread_acquire_lock(self->rlock_lock, 0)) { | |
| 353 if (microseconds == 0) { | |
| 354 Py_RETURN_FALSE; | |
| 355 } | |
| 356 r = acquire_timed(self->rlock_lock, microseconds); | |
| 357 } | |
| 358 if (r == PY_LOCK_ACQUIRED) { | 353 if (r == PY_LOCK_ACQUIRED) { |
| 359 assert(self->rlock_count == 0); | 354 assert(self->rlock_count == 0); |
| 360 self->rlock_owner = tid; | 355 self->rlock_owner = tid; |
| 361 self->rlock_count = 1; | 356 self->rlock_count = 1; |
| 362 } | 357 } |
| 363 else if (r == PY_LOCK_INTR) { | 358 else if (r == PY_LOCK_INTR) { |
| 364 return NULL; | 359 return NULL; |
| 365 } | 360 } |
| 366 | 361 |
| 367 return PyBool_FromLong(r == PY_LOCK_ACQUIRED); | 362 return PyBool_FromLong(r == PY_LOCK_ACQUIRED); |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 545 }; | 540 }; |
| 546 | 541 |
| 547 static lockobject * | 542 static lockobject * |
| 548 newlockobject(void) | 543 newlockobject(void) |
| 549 { | 544 { |
| 550 lockobject *self; | 545 lockobject *self; |
| 551 self = PyObject_New(lockobject, &Locktype); | 546 self = PyObject_New(lockobject, &Locktype); |
| 552 if (self == NULL) | 547 if (self == NULL) |
| 553 return NULL; | 548 return NULL; |
| 554 self->lock_lock = PyThread_allocate_lock(); | 549 self->lock_lock = PyThread_allocate_lock(); |
| 550 self->locked = 0; |
| 555 self->in_weakreflist = NULL; | 551 self->in_weakreflist = NULL; |
| 556 if (self->lock_lock == NULL) { | 552 if (self->lock_lock == NULL) { |
| 557 Py_DECREF(self); | 553 Py_DECREF(self); |
| 558 PyErr_SetString(ThreadError, "can't allocate lock"); | 554 PyErr_SetString(ThreadError, "can't allocate lock"); |
| 559 return NULL; | 555 return NULL; |
| 560 } | 556 } |
| 561 return self; | 557 return self; |
| 562 } | 558 } |
| 563 | 559 |
| 564 static PyObject * | 560 static PyObject * |
| 565 lock_acquire_condition(lockobject *self, PyObject *args, PyObject *kwds) | 561 lock_acquire_condition(lockobject *self, PyObject *args, PyObject *kwds) |
| 566 { | 562 { |
| 567 double timeout; | 563 PyObject *timeout_obj; |
| 568 PyObject *outer_lock; | 564 PyObject *outer_lock; |
| 569 PyObject *outer_arg; | 565 PyObject *outer_arg; |
| 566 double timeout; |
| 567 unsigned long count; |
| 568 long owner; |
| 570 PY_TIMEOUT_T microseconds; | 569 PY_TIMEOUT_T microseconds; |
| 571 PyLockStatus r; | 570 PyLockStatus r; |
| 572 | 571 |
| 573 if (!PyArg_ParseTuple(args, "dOO:_acquire_condition", &timeout, &outer_lock,
&outer_arg)) | 572 /* if we can't even parse the arguments, then we cannot re-acquire the outer
lock. But that |
| 574 return NULL; | 573 * is the same if passing wrong arguments to a _aquire_restore method. |
| 575 | 574 */ |
| 576 if (timeout < 0 && timeout != -1) { | 575 if (!PyArg_ParseTuple(args, "OOO:_acquire_condition", &timeout_obj, &outer_l
ock, &outer_arg)) |
| 577 PyErr_SetString(PyExc_ValueError, "timeout value must be " | 576 return NULL; |
| 578 "strictly positive"); | 577 if (Py_TYPE(outer_lock) == &RLocktype) |
| 579 return NULL; | 578 if (!PyArg_ParseTuple(outer_arg, "kl", &count, &owner)) |
| 580 } | 579 return NULL; |
| 581 if (timeout == -1) | 580 |
| 581 /* None is infinite, otherwise a float is the timeout in seconds, negative v
alues |
| 582 * are clipped to zero |
| 583 */ |
| 584 if (timeout_obj == Py_None) { |
| 582 microseconds = -1; | 585 microseconds = -1; |
| 583 else { | 586 } else { |
| 584 timeout *= 1e6; | 587 timeout = PyFloat_AsDouble(timeout_obj); |
| 585 if (timeout >= (double) PY_TIMEOUT_MAX) { | 588 if (timeout == -1.0 && PyErr_Occurred()) |
| 586 PyErr_SetString(PyExc_OverflowError, | 589 goto ERR; |
| 587 "timeout value is too large"); | 590 if (timeout > 0.0) { |
| 588 return NULL; | 591 timeout *= 1e6; |
| 589 } | 592 if (timeout >= (double) PY_TIMEOUT_MAX) { |
| 590 microseconds = (PY_TIMEOUT_T) timeout; | 593 PyErr_SetString(PyExc_OverflowError, |
| 591 } | 594 "timeout value is too large"); |
| 592 | 595 goto ERR; |
| 596 } |
| 597 microseconds = (PY_TIMEOUT_T) timeout; |
| 598 } else |
| 599 microseconds = 0; |
| 600 } |
| 601 |
| 602 r = PY_LOCK_ACQUIRED; |
| 603 goto ACQUIRE; |
| 604 ERR: |
| 605 r = PY_LOCK_INTR; /* just acquire the outer lock and exit with error */ |
| 606 ACQUIRE: |
| 593 /* acquire the condition lock _and_ the outer lock before reacquiring the GI
L */ | 607 /* acquire the condition lock _and_ the outer lock before reacquiring the GI
L */ |
| 594 Py_BEGIN_ALLOW_THREADS | 608 Py_BEGIN_ALLOW_THREADS |
| 595 r = PyThread_acquire_lock_timed(self->lock_lock, microseconds, 1); | 609 if (r == PY_LOCK_ACQUIRED) |
| 610 r = PyThread_acquire_lock_timed(self->lock_lock, microseconds, 1); |
| 596 /* acquire the outer lock if we know it */ | 611 /* acquire the outer lock if we know it */ |
| 597 if (Py_TYPE(outer_lock) == &Locktype) { | 612 if (Py_TYPE(outer_lock) == &Locktype) { |
| 598 PyThread_acquire_lock_timed(((lockobject*)outer_lock)->lock_lock, -1, 0)
; | 613 PyThread_acquire_lock_timed(((lockobject*)outer_lock)->lock_lock, -1, 0)
; |
| 599 } else if(Py_TYPE(outer_lock) == &RLocktype) { | 614 } else if(Py_TYPE(outer_lock) == &RLocktype) { |
| 600 rlockobject *rlock = (rlockobject*)outer_lock; | 615 rlockobject *rlock = (rlockobject*)outer_lock; |
| 601 PyThread_acquire_lock_timed(rlock->rlock_lock, -1, 0); | 616 PyThread_acquire_lock_timed(rlock->rlock_lock, -1, 0); |
| 602 } | 617 } |
| 603 Py_END_ALLOW_THREADS | 618 Py_END_ALLOW_THREADS |
| 604 /* and restore the state of the RLock */ | 619 /* and restore the state of the locks */ |
| 605 if (Py_TYPE(outer_lock) == &RLocktype) { | 620 if (Py_TYPE(outer_lock) == &Locktype) { |
| 621 ((lockobject*)outer_lock)->locked = 1; |
| 622 } else if (Py_TYPE(outer_lock) == &RLocktype) { |
| 606 rlockobject *rlock = (rlockobject*)outer_lock; | 623 rlockobject *rlock = (rlockobject*)outer_lock; |
| 607 PyArg_ParseTuple(outer_arg, "kl", &rlock->rlock_count, &rlock->rlock_own
er); | 624 rlock->rlock_count = count; |
| 625 rlock->rlock_owner = owner; |
| 608 } | 626 } |
| 609 | 627 |
| 610 if (r == PY_LOCK_INTR) { | 628 if (r == PY_LOCK_INTR) { |
| 611 return NULL; | 629 return NULL; |
| 612 } | 630 } |
| 613 | 631 |
| 614 return PyBool_FromLong(r == PY_LOCK_ACQUIRED); | 632 return PyBool_FromLong(r == PY_LOCK_ACQUIRED); |
| 615 } | 633 } |
| 616 | 634 |
| 617 /* Thread-local objects */ | 635 /* Thread-local objects */ |
| (...skipping 772 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1390 nb_threads = 0; | 1408 nb_threads = 0; |
| 1391 | 1409 |
| 1392 str_dict = PyUnicode_InternFromString("__dict__"); | 1410 str_dict = PyUnicode_InternFromString("__dict__"); |
| 1393 if (str_dict == NULL) | 1411 if (str_dict == NULL) |
| 1394 return NULL; | 1412 return NULL; |
| 1395 | 1413 |
| 1396 /* Initialize the C thread library */ | 1414 /* Initialize the C thread library */ |
| 1397 PyThread_init_thread(); | 1415 PyThread_init_thread(); |
| 1398 return m; | 1416 return m; |
| 1399 } | 1417 } |
| LEFT | RIGHT |