예제 #1
0
파일: channelobject.c 프로젝트: d11/rts
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;
}
예제 #2
0
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);
}
예제 #3
0
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);
}
예제 #4
0
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);
}
예제 #5
0
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;
	}
}