static char * gdbpy_readline_wrapper (FILE *sys_stdin, FILE *sys_stdout, char *prompt) { int n; char *p = NULL, *p_start, *p_end, *q; volatile struct gdb_exception except; TRY_CATCH (except, RETURN_MASK_ALL) p = command_line_input (prompt, 0, "python"); /* Detect user interrupt (Ctrl-C). */ if (except.reason == RETURN_QUIT) return NULL; /* Handle errors by raising Python exceptions. */ if (except.reason < 0) { /* The thread state is nulled during gdbpy_readline_wrapper, with the original value saved in the following undocumented variable (see Python's Parser/myreadline.c and Modules/readline.c). */ PyEval_RestoreThread (_PyOS_ReadlineTState); gdbpy_convert_exception (except); PyEval_SaveThread (); return NULL; } /* Detect EOF (Ctrl-D). */ if (p == NULL) { q = PyMem_Malloc (1); if (q != NULL) q[0] = '\0'; return q; } n = strlen (p); /* Copy the line to Python and return. */ q = PyMem_Malloc (n + 2); if (q != NULL) { strncpy (q, p, n); q[n] = '\n'; q[n + 1] = '\0'; } return q; }
static int vmd_input_hook() { if (the_app) { the_app->VMDupdate(1); } PyEval_RestoreThread(event_tstate); PyRun_SimpleString( "try:\n" "\timport Tkinter\n" "\twhile Tkinter.tkinter.dooneevent(Tkinter.tkinter.DONT_WAIT):\n" "\t\tpass\n" "except:\n" "\tpass\n"); PyEval_SaveThread(); return 0; }
void interpreter_lock_impl::lock() { boost::mutex::scoped_lock lock(mutex_); while (NULL != thread_state_) { if (!thread_lock_count_) { break; } condition_.wait(lock); } if (NULL == thread_state_) { throw std::runtime_error("Can not acquire python interpreter lock"); } PyEval_RestoreThread(thread_state_); thread_lock_count_++; }
static PyObject * evaluator_call(PyFFEvaluatorObject *self, PyObject *args) { PyArrayObject *coordinates = NULL; PyObject *gradients = NULL; PyObject *force_constants = NULL; int small_change = 0; gradient_function *gf = NULL; fc_function *fcf = NULL; energy_data energy; if (!PyArg_ParseTuple(args, "O!|OOi", &PyArray_Type, &coordinates, &gradients, &force_constants, &small_change)) return NULL; if (gradients == Py_None) gradients = NULL; if (force_constants == Py_None) force_constants = NULL; if (gradients != NULL && !PyArray_Check(gradients)) { PyObject *fnptr = PyObject_CallMethod(gradients, "accessFunction", NULL); if (fnptr == NULL) return NULL; gf = (gradient_function *)PyCObject_AsVoidPtr(fnptr); } if (force_constants != NULL && !PyArray_Check(force_constants)) { PyObject *fnptr = PyObject_CallMethod(force_constants, "accessFunction", NULL); if (fnptr == NULL) return NULL; fcf = (fc_function *)PyCObject_AsVoidPtr(fnptr); } energy.gradients = gradients; energy.gradient_fn = gf; energy.force_constants = force_constants; energy.fc_fn = fcf; #ifdef WITH_THREAD self->tstate_save = PyEval_SaveThread(); #endif (*self->eval_func)(self, &energy, coordinates, small_change); #ifdef WITH_THREAD PyEval_RestoreThread(self->tstate_save); #endif if (energy.error) return NULL; else return PyFloat_FromDouble(energy.energy); }
bool PythonInterpreter::runScript(const char* code) { PyEval_RestoreThread(state); PyObject* ans = PyRun_String(const_cast<char*>(code), Py_file_input, mainNamespace, mainNamespace); if (ans) { Py_DECREF(ans); state = PyEval_SaveThread(); return true; } else { PyErr_Print(); PyErr_Clear(); state = PyEval_SaveThread(); return false; } }
bool PythonInterpreter::compileScript(const char* code) { PyEval_RestoreThread(state); PyObject* ans = Py_CompileString(const_cast<char*>(code), "<script>", Py_file_input); if (ans) { Py_DECREF(ans); state = PyEval_SaveThread(); return true; } else { PyErr_Print(); PyErr_Clear(); state = PyEval_SaveThread(); return false; } }
bool PythonInterpreter::setVar(const char* name, regina::NPacket* value) { PyEval_RestoreThread(state); boost::python::reference_existing_object:: apply<regina::NPacket*>::type conv; PyObject* pyValue = conv(value); if (pyValue) { PyObject* nameStr = PyString_FromString(name); // New ref. PyDict_SetItem(mainNamespace, nameStr, conv(value)); Py_DECREF(nameStr); } state = PyEval_SaveThread(); return (pyValue != 0); }
PyMinqlx_InitStatus_t PyMinqlx_Finalize(void) { if (!PyMinqlx_IsInitialized()) { DebugPrint("%s was called before being initialized!\n", __func__); return PYM_NOT_INITIALIZED_ERROR; } for (handler_t* h = handlers; h->name; h++) { *h->handler = NULL; } PyEval_RestoreThread(mainstate); Py_Finalize(); initialized = 0; return PYM_SUCCESS; }
void interpreterPrepare(Interpreter *interpreter) { //PyEval_AcquireLock(); //interpreter->threadPythonState = Py_NewInterpreter(); interpreter->threadPythonState = PyThreadState_New(mainPythonThread->interp); PyEval_RestoreThread(interpreter->threadPythonState); interpreter->pdict = PyDict_New(); PyDict_SetItemString(interpreter->pdict, "__builtins__", PyEval_GetBuiltins( )); PyEval_SaveThread(); //PyEval_ReleaseThread(interpreter->threadPythonState); }
static PyObject* CDDA_read_sectors(cdio_CDDAObject* self, PyObject *args) { int16_t *raw_sector; int i; int current_sectors_position = 0; int sectors_read; int sectors_to_read; pcm_FrameList *sectors; PyThreadState *thread_state = NULL; if (!PyArg_ParseTuple(args, "i", §ors_to_read)) return NULL; sectors = (pcm_FrameList*)PyObject_CallMethod(self->pcm_module, "__blank__", NULL); if (sectors == NULL) return NULL; if (read_callback == NULL) { thread_state = PyEval_SaveThread(); } sectors->frames = sectors_to_read * (44100 / 75); sectors->channels = 2; sectors->bits_per_sample = 16; sectors->samples_length = (sectors->frames * sectors->channels); sectors->samples = realloc(sectors->samples, sectors->samples_length * sizeof(int)); for (sectors_read = 0; sectors_read < sectors_to_read; sectors_read++) { raw_sector = cdio_paranoia_read_limited(self->paranoia, &read_sector_callback, 10); for (i = 0; i < (SECTOR_LENGTH / 2); i++) { sectors->samples[current_sectors_position++] = raw_sector[i]; } } if (read_callback == NULL) { PyEval_RestoreThread(thread_state); } return (PyObject*)sectors; }
void Effect::run() { // switch to the main thread state and acquire the GIL PyEval_RestoreThread(_mainThreadState); // Initialize a new thread state _interpreterThreadState = Py_NewInterpreter(); // import the buildtin Hyperion module PyObject * module = PyImport_ImportModule("hyperion"); // add a capsule containing 'this' to the module to be able to retrieve the effect from the callback function PyObject_SetAttrString(module, "__effectObj", PyCapsule_New(this, nullptr, nullptr)); // add ledCount variable to the interpreter PyObject_SetAttrString(module, "ledCount", Py_BuildValue("i", _imageProcessor->getLedCount())); // add a args variable to the interpreter PyObject_SetAttrString(module, "args", json2python(_args)); // decref the module Py_XDECREF(module); // Set the end time if applicable if (_timeout > 0) { _endTime = QDateTime::currentMSecsSinceEpoch() + _timeout; } // Run the effect script FILE* file = fopen(_script.c_str(), "r"); if (file != nullptr) { PyRun_SimpleFile(file, _script.c_str()); } else { std::cerr << "EFFECTENGINE ERROR: Unable to open script file " << _script << std::endl; } fclose(file); // Clean up the thread state Py_EndInterpreter(_interpreterThreadState); _interpreterThreadState = nullptr; PyEval_ReleaseLock(); }
PythonModules::~PythonModules() { qDebug() << "Destroying " << this; unloadModules(); PyEval_RestoreThread(pymainstate); cleaningPyObjs(); Py_Finalize(); #if defined(Q_OS_WIN) && !defined(BUILD_PYTHON_3) // this value is only used for the Python 2.7 module delete [] pythonPath; #endif //Q_OS_WIN && !BUILD_PYTHON_3 }
CDummyClientManager::~CDummyClientManager(void) { DeleteDummyClient( 0, m_highestIndex - 1 ); while(1) { int count = dummyClientToDeleteList.size(); if( count == 0 ) { break; } DeleteThreadEndedClient(); Sleep(50); } PyEval_RestoreThread( mainThreadState ); Py_Finalize(); }
static uint16_t data_to_python(void *params, void *priv, uint32_t sendlen, unsigned char *data, uint32_t *putlen) { PyObject *res; ProgressCallback *cb; uint16_t ret = LIBMTP_HANDLER_RETURN_OK; cb = (ProgressCallback *)priv; *putlen = sendlen; PyEval_RestoreThread(cb->state); res = PyObject_CallMethod(cb->extra, "write", "s#", data, (Py_ssize_t)sendlen); if (res == NULL) { ret = LIBMTP_HANDLER_RETURN_ERROR; *putlen = 0; PyErr_Print(); } else Py_DECREF(res); cb->state = PyEval_SaveThread(); return ret; }
void interpreterFree(Interpreter *interpreter) { //PyEval_AcquireThread(interpreter->threadPythonState); //PyEval_RestoreThread(interpreter->threadPythonState); PyEval_RestoreThread(interpreter->threadPythonState); Py_DECREF(interpreter->pdict); //Py_EndInterpreter(interpreter->threadPythonState); PyThreadState_Clear(interpreter->threadPythonState); PyEval_SaveThread(); //PyEval_SaveThread(); //PyEval_ReleaseLock(); }
waits for and dispatches the next incoming message\n\ "); static PyObject * pylcm_handle_timeout (PyLCMObject *lcm_obj, PyObject *arg) { int timeout_millis = PyInt_AsLong(arg); if (timeout_millis == -1 && PyErr_Occurred()) return NULL; if (timeout_millis < 0) { PyErr_SetString (PyExc_ValueError, "invalid timeout"); return NULL; } dbg(DBG_PYTHON, "pylcm_handle_timeout(%p, %d)\n", lcm_obj, timeout_millis); if (lcm_obj->saved_thread_state) { PyErr_SetString (PyExc_RuntimeError, "Simultaneous calls to handle() / handle_timeout() detected"); return NULL; } lcm_obj->saved_thread_state = PyEval_SaveThread(); lcm_obj->exception_raised = 0; dbg(DBG_PYTHON, "calling lcm_handle_timeout(%p, %d)\n", lcm_obj->lcm, timeout_millis); int status = lcm_handle_timeout(lcm_obj->lcm, timeout_millis); // Restore the thread state before returning back to Python. The thread // state may have already been restored by the callback function // pylcm_msg_handler() if (lcm_obj->saved_thread_state) { PyEval_RestoreThread(lcm_obj->saved_thread_state); lcm_obj->saved_thread_state = NULL; } if (lcm_obj->exception_raised) { return NULL; } if (status < 0) { PyErr_SetString (PyExc_IOError, "lcm_handle_timeout() returned -1"); return NULL; } return PyInt_FromLong(status); }
static void py_cli_state_trace_callback(enum tevent_trace_point point, void *private_data) { struct py_cli_state *self = (struct py_cli_state *)private_data; struct py_cli_thread *t = self->thread_state; switch(point) { case TEVENT_TRACE_BEFORE_WAIT: assert(t->py_threadstate == NULL); t->py_threadstate = PyEval_SaveThread(); break; case TEVENT_TRACE_AFTER_WAIT: assert(t->py_threadstate != NULL); PyEval_RestoreThread(t->py_threadstate); t->py_threadstate = NULL; break; default: break; } }
static void ld_callback (u_char * my_thread_state, const struct pcap_pkthdr * h, const u_char * data) { thread_state * ts = (thread_state *)my_thread_state; PyObject * args; PyObject * rv; if (ts->release_thread) PyEval_RestoreThread(ts->ts); #ifndef NO_BYTEARRAYS if (ts->use_bytearray) { args = Py_BuildValue("ONlli", ts->user, PyByteArray_FromStringAndSize((const char *)data, h->caplen), (long)h->ts.tv_sec, (long)h->ts.tv_usec, h->len); } else #endif { args = Py_BuildValue("Os#lli", ts->user, data, h->caplen, (long)h->ts.tv_sec, (long)h->ts.tv_usec, h->len); } rv = PyEval_CallObject(ts->pycallback, args); Py_DECREF(args); if (rv) { Py_DECREF(rv); } else { ts->exception = 1; pcap_breakloop(ts->ppcap); } if (ts->release_thread) ts->ts = PyEval_SaveThread(); }
void MPyEmbed_Fini(void) { int i; if (!PythonAvailable) { return; } MPyEmbed_Exiting = 1; for (i = 0; i < THREADS; i++) { if (VALID(threaddata[i])) { PyThread_acquire_lock(threaddata[i].exitlock, WAIT_LOCK); PyThread_free_lock(threaddata[i].exitlock); } else if (threaddata[i].exitlock != 0) { PyThread_free_lock(threaddata[i].exitlock); } } memset(threaddata, 0, sizeof(threaddata)); PyEval_RestoreThread(mainstate); Py_Finalize(); MPyEmbed_Exiting = 0; }
static void cleanupPy(void *junk) { /* safe because exit hooks are only run once, from a single thread */ static int done; if(done) return; done = 1; PyThreadState *state = PyGILState_GetThisThreadState(); PyEval_RestoreThread(state); if(PyRun_SimpleString("import devsup\n" "devsup._fini(iocMain=True)\n" )) { PyErr_Print(); PyErr_Clear(); } Py_Finalize(); // calls python atexit hooks }
static PyObject* CDDA_read_sector(cdio_CDDAObject* self) { int16_t *raw_sector; int i; int current_sector_position = 0; pcm_FrameList *sector; PyThreadState *thread_state = NULL; sector = (pcm_FrameList*)PyObject_CallMethod(self->pcm_module, "__blank__", NULL); if (sector == NULL) return NULL; if (read_callback == NULL) { thread_state = PyEval_SaveThread(); } sector->frames = 44100 / 75; sector->channels = 2; sector->bits_per_sample = 16; sector->samples_length = (sector->frames * sector->channels); sector->samples = realloc(sector->samples, sector->samples_length * sizeof(int)); raw_sector = cdio_paranoia_read_limited(self->paranoia, &read_sector_callback, 10); for (i = 0; i < (SECTOR_LENGTH / 2); i++) { sector->samples[current_sector_position++] = raw_sector[i]; } if (read_callback == NULL) { PyEval_RestoreThread(thread_state); } return (PyObject*)sector; }
PyGILState_STATE PyGILState_Ensure(void) { int current; PyThreadState *tcur; /* Note that we do not auto-init Python here - apart from potential races with 2 threads auto-initializing, pep-311 spells out other issues. Embedders are expected to have called Py_Initialize() and usually PyEval_InitThreads(). */ assert(autoInterpreterState); /* Py_Initialize() hasn't been called! */ tcur = (PyThreadState *)PyThread_get_key_value(autoTLSkey); if (tcur == NULL) { /* At startup, Python has no concrete GIL. If PyGILState_Ensure() is called from a new thread for the first time, we need the create the GIL. */ PyEval_InitThreads(); /* Create a new thread state for this thread */ tcur = PyThreadState_New(autoInterpreterState); if (tcur == NULL) Py_FatalError("Couldn't create thread-state for new thread"); /* This is our thread state! We'll need to delete it in the matching call to PyGILState_Release(). */ tcur->gilstate_counter = 0; current = 0; /* new thread state is never current */ } else current = PyThreadState_IsCurrent(tcur); if (current == 0) PyEval_RestoreThread(tcur); /* Update our counter in the thread-state - no need for locks: - tcur will remain valid as we hold the GIL. - the counter is safe as we are the only thread "allowed" to modify this value */ ++tcur->gilstate_counter; return current ? PyGILState_LOCKED : PyGILState_UNLOCKED; }
static uint16_t data_from_python(void *params, void *priv, uint32_t wantlen, unsigned char *data, uint32_t *gotlen) { PyObject *res; ProgressCallback *cb; char *buf = NULL; Py_ssize_t len = 0; uint16_t ret = LIBMTP_HANDLER_RETURN_ERROR; *gotlen = 0; cb = (ProgressCallback *)priv; PyEval_RestoreThread(cb->state); res = PyObject_CallMethod(cb->extra, "read", "k", (unsigned long)wantlen); if (res != NULL && PyBytes_AsStringAndSize(res, &buf, &len) != -1 && len <= wantlen) { memcpy(data, buf, len); *gotlen = len; ret = LIBMTP_HANDLER_RETURN_OK; } else PyErr_Print(); Py_XDECREF(res); cb->state = PyEval_SaveThread(); return ret; }
static void test_repeated_init_and_subinterpreters(void) { PyThreadState *mainstate, *substate; #ifdef WITH_THREAD PyGILState_STATE gilstate; #endif int i, j; for (i=0; i<3; i++) { printf("--- Pass %d ---\n", i); _testembed_Py_Initialize(); mainstate = PyThreadState_Get(); #ifdef WITH_THREAD PyEval_InitThreads(); PyEval_ReleaseThread(mainstate); gilstate = PyGILState_Ensure(); #endif print_subinterp(); PyThreadState_Swap(NULL); for (j=0; j<3; j++) { substate = Py_NewInterpreter(); print_subinterp(); Py_EndInterpreter(substate); } PyThreadState_Swap(mainstate); print_subinterp(); #ifdef WITH_THREAD PyGILState_Release(gilstate); #endif PyEval_RestoreThread(mainstate); Py_Finalize(); } }
static int nis_foreach (int instatus, char *inkey, int inkeylen, char *inval, int invallen, struct ypcallback_data *indata) { if (instatus == YP_TRUE) { PyObject *key; PyObject *val; int err; PyEval_RestoreThread(indata->state); if (indata->fix) { if (inkeylen > 0 && inkey[inkeylen-1] == '\0') inkeylen--; if (invallen > 0 && inval[invallen-1] == '\0') invallen--; } key = PyUnicode_DecodeFSDefaultAndSize(inkey, inkeylen); val = PyUnicode_DecodeFSDefaultAndSize(inval, invallen); if (key == NULL || val == NULL) { /* XXX error -- don't know how to handle */ PyErr_Clear(); Py_XDECREF(key); Py_XDECREF(val); indata->state = PyEval_SaveThread(); return 1; } err = PyDict_SetItem(indata->dict, key, val); Py_DECREF(key); Py_DECREF(val); if (err != 0) PyErr_Clear(); indata->state = PyEval_SaveThread(); if (err != 0) return 1; return 0; } return 1; }
static PyObject * tart_event_loop(PyObject *self, PyObject *args) { qDebug() << QThread::currentThreadId() << "_tart.event_loop()"; // code for callback based on // http://docs.python.org/3.2/extending/extending.html#calling-python-functions-from-c PyObject * temp; if(!PyArg_ParseTuple(args, "O:event_loop", &temp)) return NULL; if (!PyCallable_Check(temp)) { PyErr_SetString(PyExc_TypeError, "parameter must be callable"); return NULL; } Py_XINCREF(temp); // Add a reference to new callback event_callback = temp; // Remember new callback // qDebug() << "event_loop: callback is" << event_callback; // exec() may block indefinitely, so we have to release the interpreter // to let other Python threads run until data arrives for us tart_pystate = PyEval_SaveThread(); int rc = Tart::instance()->getThread()->do_exec(); qDebug() << "event_loop: raising SystemExit(" << rc << ")"; PyEval_RestoreThread(tart_pystate); Py_XDECREF(event_callback); // Dispose of callback event_callback = NULL; // Forget callback qDebug() << "event_loop: callback cleared"; PyObject * exit_code = PyLong_FromLong(rc); PyErr_SetObject(PyExc_SystemExit, exit_code); return NULL; }
PyObject * AerospikeQuery_Results(AerospikeQuery * self, PyObject * args, PyObject * kwds) { PyObject * py_policy = NULL; static char * kwlist[] = {"policy", NULL}; if ( PyArg_ParseTupleAndKeywords(args, kwds, "|O:foreach", kwlist, &py_policy) == false ) { return NULL; } as_error err; as_error_init(&err); TRACE(); PyObject * py_results = PyList_New(0); TRACE(); PyThreadState * _save = PyEval_SaveThread(); TRACE(); aerospike_query_foreach(self->client->as, &err, NULL, &self->query, each_result, py_results); TRACE(); PyEval_RestoreThread(_save); TRACE(); if ( err.code != AEROSPIKE_OK ) { PyObject * py_err = NULL; error_to_pyobject(&err, &py_err); PyErr_SetObject(PyExc_Exception, py_err); TRACE(); return NULL; } TRACE(); return py_results; }
/* Decompress nbytes from input into output. * * Returns 1 on success and 0 on failure with a Python exception set. * * */ static int decompress_helper(void * input, size_t nbytes, void * output) { int err, nthreads; PyThreadState *_save = NULL; /* Do the decompression */ // int blosc_decompress_ctx(const void *src, void *dest, size_t destsize, // int numinternalthreads) if( RELEASEGIL ) { _save = PyEval_SaveThread(); nthreads = blosc_get_nthreads(); err = blosc_decompress_ctx(input, output, nbytes, nthreads); PyEval_RestoreThread(_save); _save = NULL; } else { // Run while holding the GIL err = blosc_decompress(input, output, nbytes); } if (err < 0) { blosc_error(err, "while decompressing data"); return 0; } else if (err != (int)nbytes) { PyErr_Format(BloscError, "expected %d bytes of decompressed data, got %d", (int) nbytes, err); return 0; } return 1; }
To subscribe to a channel::\n\ \n\ def msg_handler(channel, data):\n\ # message handling code here. For example:\n\ print(\"received %d byte message on %s\" % (len(data), channel))\n\ \n\ m.subscribe(channel, msg_handler)\n\ \n\ To transmit a raw binary string::\n\ \n\ m.publish(\"CHANNEL_NAME\", data)\n\ \n\ In general, LCM is used with python modules compiled by lcm-gen, each of \n\ which provides the instance method encode() and the static method decode().\n\ Thus, if one had a compiled type named example_t, the following message\n\ handler would decode the message::\n\ \n\ def msg_handler(channel, data):\n\ msg = example_t.decode(data)\n\ \n\ and the following usage would publish a message::\n\ \n\ msg = example_t()\n\ # ... set member variables of msg\n\ m.publish(\"CHANNEL_NAME\", msg.encode())\n\ \n\ @undocumented: __new__, __getattribute__\n\ "); //gives redefinition error in MSVC //PyTypeObject pylcm_type; // all LCM messages subscribed to by all LCM objects pass through this // handler first. static void pylcm_msg_handler (const lcm_recv_buf_t *rbuf, const char *channel, void *userdata) { PyLCMSubscriptionObject *subs_obj = (PyLCMSubscriptionObject*) userdata; dbg(DBG_PYTHON, "%s %p %p\n", __FUNCTION__, subs_obj, subs_obj->lcm_obj); // Restore the thread state before calling back into Python. if (subs_obj->lcm_obj->saved_thread_state) { PyEval_RestoreThread(subs_obj->lcm_obj->saved_thread_state); subs_obj->lcm_obj->saved_thread_state = NULL; } // if an exception has occurred, then abort. if (PyErr_Occurred ()) { return; } #if PY_MAJOR_VERSION >= 3 PyObject *arglist = Py_BuildValue ("sy#", channel, // build from bytes rbuf->data, rbuf->data_size); #else PyObject *arglist = Py_BuildValue ("ss#", channel, // build from string rbuf->data, rbuf->data_size); #endif PyObject *result = PyEval_CallObject (subs_obj->handler, arglist); Py_DECREF (arglist); if (! result) { subs_obj->lcm_obj->exception_raised = 1; } else { Py_DECREF (result); } }
static PyObject *schedule_task_unblock(PyTaskletObject *prev, PyTaskletObject *next, int stackless) { PyThreadState *ts = PyThreadState_GET(); PyThreadState *nts = next->cstate->tstate; PyObject *retval; long thread_id = nts->thread_id; PyObject *unlock_lock; if (ts->st.thread.self_lock == NULL) { if (!(ts->st.thread.self_lock = new_lock())) return NULL; acquire_lock(ts->st.thread.self_lock, 1); if (!(ts->st.thread.unlock_lock = new_lock())) return NULL; if (interthread_lock == NULL) { if (!(interthread_lock = PyThread_allocate_lock())) return NULL; } } /* * make sure nobody else tries a transaction at the same time * on this tasklet's thread state, because two tasklets of the * same thread could be talking to different threads. They must * be serviced in fifo order. */ if (nts->st.thread.unlock_lock == NULL) { if (!(nts->st.thread.unlock_lock = new_lock())) return NULL; } unlock_lock = nts->st.thread.unlock_lock; Py_INCREF(unlock_lock); PyEval_SaveThread(); PR("unblocker waiting for unlocker lock"); acquire_lock(unlock_lock, 1); PR("unblocker HAS unlocker lock"); /* * also make sure that only one single interthread transaction * is performed at any time. */ PR("unblocker waiting for interthread lock"); PyThread_acquire_lock(interthread_lock, 1); PR("unblocker HAS interthread lock"); PyEval_RestoreThread(ts); /* get myself ready */ retval = slp_schedule_task(prev, prev, stackless); /* see whether the other thread still exists and is really blocked */ if (is_thread_alive(thread_id) && nts->st.thread.is_locked) { /* tell the blocker what comes next */ temp.unlock_target = next; temp.other_lock = ts->st.thread.self_lock; /* give it an extra ref, in case I would die early */ Py_INCREF(temp.other_lock); /* unblock it */ release_lock(nts->st.thread.self_lock); /* wait for the transaction to finish */ PyEval_SaveThread(); PR("unblocker waiting for own lock"); acquire_lock(ts->st.thread.self_lock, 1); PR("unblocker HAS own lock"); PyEval_RestoreThread(ts); } else { PR("unlocker: other is NOT LOCKED or dead"); if (next->flags.blocked) { /* unblock from channel */ slp_channel_remove_slow(next); slp_current_insert(next); } else if (next->next == NULL) { /* reactivate floating task */ Py_INCREF(next); slp_current_insert(next); } } PR("unblocker releasing interthread lock"); PyThread_release_lock(interthread_lock); PR("unblocker RELEASED interthread lock"); PR("unblocker releasing unlocker lock"); release_lock(unlock_lock); Py_DECREF(unlock_lock); PR("unblocker RELEASED unlocker lock"); return retval; }