Esempio n. 1
0
static PyObject *
wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds)
{
	STACKLESS_GETARG();
	wrapperfunc wrapper = wp->descr->d_base->wrapper;
	PyObject *self = wp->self;
	PyObject *ret;

	if (wp->descr->d_base->flags & PyWrapperFlag_KEYWORDS) {
		wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper;
		STACKLESS_PROMOTE_WRAPPER(wp);
		ret = (*wk)(self, args, wp->descr->d_wrapped, kwds);
		STACKLESS_ASSERT();
		return ret;
	}

	if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_Size(kwds) != 0)) {
		PyErr_Format(PyExc_TypeError,
			     "wrapper %s doesn't take keyword arguments",
			     wp->descr->d_base->name);
		return NULL;
	}
	STACKLESS_PROMOTE_WRAPPER(wp);
	ret = (*wrapper)(self, args, wp->descr->d_wrapped);
	STACKLESS_ASSERT();
	return ret;
}
Esempio n. 2
0
static TASKLET_KILL_HEAD(impl_tasklet_kill)
{
    STACKLESS_GETARG();
    PyObject *noargs;
    PyObject *ret;

    /*
     * silently do nothing if the tasklet is dead.
     * simple raising would kill ourself in this case.
     */
    if (slp_get_frame(task) == NULL)
        Py_RETURN_NONE;

    /* we might be called after exceptions are gone */
    if (PyExc_TaskletExit == NULL) {
        PyExc_TaskletExit = PyString_FromString("zombie");
        if (PyExc_TaskletExit == NULL)
            return NULL; /* give up */
    }
    noargs = PyTuple_New(0);
    STACKLESS_PROMOTE_ALL();
    ret = impl_tasklet_raise_exception(task, PyExc_TaskletExit,
                                       noargs);
    STACKLESS_ASSERT();
    Py_DECREF(noargs);
    return ret;
}
Esempio n. 3
0
static PyObject *
channel_send_exception(PyObject *myself, PyObject *args)
{
	STACKLESS_GETARG();
	PyObject *retval = NULL;
	PyObject *klass = PySequence_GetItem(args, 0);

	if (klass == NULL)
		VALUE_ERROR("channel.send_exception(e, v...)", NULL);
	args = PySequence_GetSlice(args, 1, PySequence_Size(args));
	if (!args) {
		goto err_exit;
	}
	STACKLESS_PROMOTE_ALL();
	retval = impl_channel_send_exception((PyChannelObject*)myself,
						klass, args);
	STACKLESS_ASSERT();
	if (retval == NULL || STACKLESS_UNWINDING(retval)) {
		goto err_exit;
	}
	Py_INCREF(Py_None);
	retval = Py_None;
err_exit:
	Py_DECREF(klass);
	Py_XDECREF(args);
	return retval;
}
PyObject *
PyChannel_Receive(PyChannelObject *self)
{
    PyObject *ret = impl_channel_receive(self);
    STACKLESS_ASSERT();
    assert(!STACKLESS_UNWINDING(self));
    return ret;
}
PyObject *
PyChannel_Receive_nr(PyChannelObject *self)
{
    PyObject *ret;

    STACKLESS_PROPOSE_ALL();
    ret = impl_channel_receive(self);
    STACKLESS_ASSERT();
    return ret;
}
Esempio n. 6
0
PyObject *
PyChannel_Receive_nr(PyChannelObject *self)
{
	PyChannel_HeapType *t = (PyChannel_HeapType *) Py_TYPE(self);
	PyObject *ret;

	slp_try_stackless = 1;
	ret = t->receive(self);
	STACKLESS_ASSERT();
	return ret;
}
Esempio n. 7
0
static PyObject *
run_mod(mod_ty mod, const char *filename, PyObject *globals, PyObject *locals,
	 PyCompilerFlags *flags, PyArena *arena)
{
	STACKLESS_GETARG();
	PyCodeObject *co;
	PyObject *v;
	co = PyAST_Compile(mod, filename, flags, arena);
	if (co == NULL)
		return NULL;
	STACKLESS_PROMOTE_ALL();
	v = PyEval_EvalCode(co, globals, locals);
	STACKLESS_ASSERT();
	Py_DECREF(co);
	return v;
}
Esempio n. 8
0
static PyObject *
classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
		      PyObject *kwds)
{
	STACKLESS_GETARG();
	PyObject *func, *result;

	func = PyCFunction_New(descr->d_method, (PyObject *)descr->d_type);
	if (func == NULL)
		return NULL;

	STACKLESS_PROMOTE_ALL();
	result = PyEval_CallObjectWithKeywords(func, args, kwds);
	STACKLESS_ASSERT();
	Py_DECREF(func);
	return result;
}
Esempio n. 9
0
static PyObject *
wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
{
	STACKLESS_GETARG();
	Py_ssize_t argc;
	PyObject *self, *func, *result;

	/* Make sure that the first argument is acceptable as 'self' */
	assert(PyTuple_Check(args));
	argc = PyTuple_GET_SIZE(args);
	if (argc < 1) {
		PyErr_Format(PyExc_TypeError,
			     "descriptor '%.300s' of '%.100s' "
			     "object needs an argument",
			     descr_name((PyDescrObject *)descr),
			     descr->d_type->tp_name);
		return NULL;
	}
	self = PyTuple_GET_ITEM(args, 0);
	if (!PyObject_IsInstance(self, (PyObject *)(descr->d_type))) {
		PyErr_Format(PyExc_TypeError,
			     "descriptor '%.200s' "
			     "requires a '%.100s' object "
			     "but received a '%.100s'",
			     descr_name((PyDescrObject *)descr),
			     descr->d_type->tp_name,
			     self->ob_type->tp_name);
		return NULL;
	}

	func = PyWrapper_New((PyObject *)descr, self);
	if (func == NULL)
		return NULL;
	args = PyTuple_GetSlice(args, 1, argc);
	if (args == NULL) {
		Py_DECREF(func);
		return NULL;
	}
	STACKLESS_PROMOTE_ALL();
	result = PyEval_CallObjectWithKeywords(func, args, kwds);
	STACKLESS_ASSERT();
	Py_DECREF(args);
	Py_DECREF(func);
	return result;
}
Esempio n. 10
0
static PyObject *
tasklet_raise_exception(PyObject *myself, PyObject *args)
{
    STACKLESS_GETARG();
    PyObject *result = NULL;
    PyObject *klass = PySequence_GetItem(args, 0);

    if (klass == NULL)
        VALUE_ERROR("tasklet.raise_exception(e, v...)", NULL);
    args = PySequence_GetSlice(args, 1, PySequence_Size(args));
    if (!args) goto err_exit;
    STACKLESS_PROMOTE_ALL();
    result = impl_tasklet_raise_exception(
        (PyTaskletObject*)myself, klass, args);
    STACKLESS_ASSERT();
err_exit:
    Py_DECREF(klass);
    Py_XDECREF(args);
    return result;
}
Esempio n. 11
0
int
slp_transfer(PyCStackObject **cstprev, PyCStackObject *cst,
	     PyTaskletObject *prev)
{
	PyThreadState *ts = PyThreadState_GET();

	/* since we change the stack we must assure that the protocol was met */
	STACKLESS_ASSERT();

	if ((intptr_t *) &ts > ts->st.cstack_base)
		return climb_stack_and_transfer(cstprev, cst, prev);
	if (cst == NULL || cst->ob_size == 0)
		cst = ts->st.initial_stub;
	if (cst != NULL) {
		if (cst->tstate != ts) {
			PyErr_SetString(PyExc_SystemError,
				"bad thread state in transfer");
			return -1;
		}
		if (ts->st.cstack_base != cst->startaddr) {
			PyErr_SetString(PyExc_SystemError,
				"bad stack reference in transfer");
			return -1;
		}
		/* record the context of the target stack */
		ts->st.serial_last_jump = cst->serial;
		/*
		 * if stacks are same and refcount==1, it must be the same
		 * task. In this case, we would destroy the target before
		 * switching. Therefore, we simply don't switch, just save.
		 */
		if (cstprev && *cstprev == cst && cst->ob_refcnt == 1)
			cst = NULL;
	}
	_cstprev = cstprev;
	_cst = cst;
	_prev = prev;
	return slp_switch();
}
Esempio n. 12
0
static PyObject *
channel_send_throw(PyObject *myself, PyObject *args)
{
    STACKLESS_GETARG();

    PyObject *typ;
    PyObject *tb = Py_None;
    PyObject *val = Py_None;
    PyObject *retval;
    if (!PyArg_UnpackTuple(args, "send_throw", 1, 3, &typ, &val, &tb))
        return NULL;

    STACKLESS_PROMOTE_ALL();
    retval = impl_channel_send_throw((PyChannelObject*)myself,
        typ, val, tb);
    STACKLESS_ASSERT();
    if (retval == NULL || STACKLESS_UNWINDING(retval)) {
        goto err_exit;
    }
    Py_INCREF(Py_None);
    retval = Py_None;
err_exit:
    return retval;
}
Esempio n. 13
0
static PyObject * run_cframe(PyFrameObject *f, int exc, PyObject *retval)
{
	PyThreadState *ts = PyThreadState_GET();
	PyCFrameObject *cf = (PyCFrameObject*) f;
	PyTaskletObject *task = ts->st.current;
	int done = cf->i;

	ts->frame = f;

	if (retval == NULL || done)
	    goto exit_run_cframe;

	if (cf->ob2 == NULL)
		cf->ob2 = PyTuple_New(0);
	Py_DECREF(retval);
	STACKLESS_PROPOSE_ALL();
	retval = PyObject_Call(cf->ob1, cf->ob2, cf->ob3);
	STACKLESS_ASSERT();
	cf->i = 1; /* mark ourself as done */

	if (STACKLESS_UNWINDING(retval)) {
		/* try to shortcut */
		if (ts->st.current == task && ts->frame != NULL &&
		    ts->frame->f_back == (PyFrameObject *) cf) {
			Py_DECREF(ts->frame->f_back);
			ts->frame->f_back = cf->f_back;
			Py_DECREF(cf); /* the exec reference */
		}
		return retval;
	}
	/* pop frame */
exit_run_cframe:
	ts->frame = cf->f_back;
	Py_DECREF(cf);
	return retval;
}
Esempio n. 14
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;
	}
}