static PyObject * channel_send_sequence(PyChannelObject *self, PyObject *v) { STACKLESS_GETARG(); PyThreadState *ts = PyThreadState_GET(); /*unused: PyChannel_HeapType *t = (PyChannel_HeapType *) self->ob_type;*/ PyObject *it; PyCFrameObject *f; if (!stackless) return _channel_send_sequence(self, v); it = PyObject_GetIter(v); if (it == NULL) return NULL; f = slp_cframe_new(channel_seq_callback, 1); if (f == NULL) goto error; f->ob1 = it; Py_INCREF(self); f->ob2 = (PyObject *) self; f->i = 0; f->n = 0; ts->frame = (PyFrameObject *) f; Py_INCREF(Py_None); return STACKLESS_PACK(Py_None); error: Py_DECREF(it); return NULL; }
static PyObject * restore_exception(PyFrameObject *f, int exc, PyObject *retval) { PyThreadState *ts = PyThreadState_GET(); PyCFrameObject *cf = (PyCFrameObject *) f; f = cf->f_back; ts->exc_type = cf->ob1; ts->exc_value = cf->ob2; ts->exc_traceback = cf->ob3; cf->ob1 = cf->ob2 = cf->ob3 = NULL; Py_DECREF(cf); ts->frame = f; return STACKLESS_PACK(retval); }
static PyObject * restore_tracing(PyFrameObject *f, int exc, PyObject *retval) { PyThreadState *ts = PyThreadState_GET(); PyCFrameObject *cf = (PyCFrameObject *) f; f = cf->f_back; ts->c_tracefunc = cf->any1; ts->c_profilefunc = cf->any2; ts->c_traceobj = cf->ob1; ts->c_profileobj = cf->ob2; ts->tracing = cf->i; ts->use_tracing = cf->n; /* the objects *have* extra references here */ Py_DECREF(cf); ts->frame = f; return STACKLESS_PACK(retval); }
static PyObject * test_cframe_nr(PyObject *self, PyObject *args, PyObject *kwds) { static char *argnames[] = {"switches", NULL}; PyThreadState *ts = PyThreadState_GET(); PyCFrameObject *cf; long switches; if (!PyArg_ParseTupleAndKeywords(args, kwds, "l:test_cframe_nr", argnames, &switches)) return NULL; cf = slp_cframe_new(test_cframe_nr_loop, 1); if (cf == NULL) return NULL; cf->n = switches; ts->frame = (PyFrameObject *) cf; Py_INCREF(Py_None); return STACKLESS_PACK(Py_None); }
PyObject * slp_schedule_task(PyTaskletObject *prev, PyTaskletObject *next, int stackless) { PyThreadState *ts = PyThreadState_GET(); PyCStackObject **cstprev; PyObject *retval; int (*transfer)(PyCStackObject **, PyCStackObject *, PyTaskletObject *); if (next == NULL) { return schedule_task_block(prev, stackless); } #ifdef WITH_THREAD /* note that next->cstate is undefined if it is ourself */ if (next->cstate != NULL && next->cstate->tstate != ts) { return schedule_task_unblock(prev, next, stackless); } #endif 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); } if (prev == next) { retval = prev->tempval; Py_INCREF(retval); if (PyBomb_Check(retval)) retval = slp_bomb_explode(prev); return retval; } NOTIFY_SCHEDULE(prev, next, NULL); ts->st.ticker = ts->st.interval; prev->recursion_depth = ts->recursion_depth; prev->f.frame = ts->frame; if (!stackless || ts->st.nesting_level != 0) goto hard_switching; /* start of soft switching code */ if (prev->cstate != ts->st.initial_stub) { Py_DECREF(prev->cstate); prev->cstate = ts->st.initial_stub; Py_INCREF(prev->cstate); } if (ts != slp_initial_tstate) { /* ensure to get all tasklets into the other thread's chain */ if (slp_ensure_linkage(prev) || slp_ensure_linkage(next)) return NULL; } /* handle exception */ if (ts->exc_type == Py_None) { Py_XDECREF(ts->exc_type); ts->exc_type = NULL; } if (ts->exc_type != NULL) { /* build a shadow frame */ PyCFrameObject *f = slp_cframe_new(restore_exception, 1); if (f == NULL) return NULL; f->ob1 = ts->exc_type; f->ob2 = ts->exc_value; f->ob3 = ts->exc_traceback; prev->f.frame = (PyFrameObject *) f; ts->exc_type = ts->exc_value = ts->exc_traceback = NULL; } if (ts->use_tracing || ts->tracing) { /* build a shadow frame */ PyCFrameObject *f = slp_cframe_new(restore_tracing, 1); if (f == NULL) return NULL; f->any1 = ts->c_tracefunc; f->any2 = ts->c_profilefunc; ts->c_tracefunc = ts->c_profilefunc = NULL; f->ob1 = ts->c_traceobj; f->ob2 = ts->c_profileobj; /* trace/profile does not add references */ Py_XINCREF(f->ob1); Py_XINCREF(f->ob2); ts->c_traceobj = ts->c_profileobj = NULL; f->i = ts->tracing; f->n = ts->use_tracing; ts->tracing = ts->use_tracing = 0; prev->f.frame = (PyFrameObject *) f; } ts->frame = next->f.frame; next->f.frame = NULL; ts->recursion_depth = next->recursion_depth; ts->st.current = next; retval = next->tempval; assert(next->cstate != NULL); if (next->cstate->nesting_level != 0) { /* create a helper frame to restore the target stack */ ts->frame = (PyFrameObject *) slp_cframe_new(jump_soft_to_hard, 1); if (ts->frame == NULL) { ts->frame = prev->f.frame; return NULL; } /* note that we don't explode the bomb now and don't incref! */ return STACKLESS_PACK(retval); } Py_INCREF(retval); if (PyBomb_Check(retval)) retval = slp_bomb_explode(next); return STACKLESS_PACK(retval); hard_switching: /* since we change the stack we must assure that the protocol was met */ STACKLESS_ASSERT(); /* note: nesting_level is handled in cstack_new */ cstprev = &prev->cstate; ts->st.current = next; if (ts->exc_type == Py_None) { Py_XDECREF(ts->exc_type); ts->exc_type = NULL; } ts->recursion_depth = next->recursion_depth; ts->frame = next->f.frame; next->f.frame = NULL; ++ts->st.nesting_level; if (ts->exc_type != NULL || ts->use_tracing || ts->tracing) transfer = transfer_with_exc; else transfer = slp_transfer; if (transfer(cstprev, next->cstate, prev) == 0) { --ts->st.nesting_level; retval = prev->tempval; Py_INCREF(retval); if (PyBomb_Check(retval)) retval = slp_bomb_explode(prev); return retval; } else { --ts->st.nesting_level; kill_wrap_bad_guy(prev, next); return NULL; } }