Esempio n. 1
0
static int g_switchstack(void)
{
	/* perform a stack switch according to some global variables
	   that must be set before:
	   - ts_current: current greenlet (holds a reference)
	   - ts_target: greenlet to switch to
	   - ts_passaround_args: NULL if PyErr_Occurred(),
	             else a tuple of args sent to ts_target (holds a reference)
	   - ts_passaround_kwargs: same as ts_passaround_args
	*/
	int err = slp_switch();
	if (err < 0)
	{
		/* error */
	}
	else 
	{
		greenlet* target = ts_target;
		greenlet* origin = ts_current;
		
		ts_current = target;

	}
	return err;
}
Esempio n. 2
0
STATIC_NOINLINE
void *_stacklet_switchstack(void *(*save_state)(void*, void*),
                            void *(*restore_state)(void*, void*),
                            void *extra)
{
    return slp_switch(save_state, restore_state, extra);
}
Esempio n. 3
0
static int g_switchstack(void)
{
	/* perform a stack switch according to some global variables
	   that must be set before:
	   - ts_current: current greenlet (holds a reference)
	   - ts_target: greenlet to switch to
	   - ts_passaround_args: NULL if PyErr_Occurred(),
	             else a tuple of args sent to ts_target (holds a reference)
	   - ts_passaround_kwargs: same as ts_passaround_args
	*/
	int err;
	{   /* save state */
		PyGreenlet* current = ts_current;
		PyThreadState* tstate = PyThreadState_GET();
		current->recursion_depth = tstate->recursion_depth;
		current->top_frame = tstate->frame;
		current->exc_type = tstate->exc_type;
		current->exc_value = tstate->exc_value;
		current->exc_traceback = tstate->exc_traceback;
	}
	err = slp_switch();
	if (err < 0) {   /* error */
		PyGreenlet* current = ts_current;
		current->top_frame = NULL;
		current->exc_type = NULL;
		current->exc_value = NULL;
		current->exc_traceback = NULL;
	}
	else {
		PyObject* args = ts_passaround_args;
		PyObject* kwargs = ts_passaround_kwargs;
		PyGreenlet* target = ts_target;
		PyGreenlet* origin = ts_current;
		PyThreadState* tstate = PyThreadState_GET();
		tstate->recursion_depth = target->recursion_depth;
		tstate->frame = target->top_frame;
		target->top_frame = NULL;
		tstate->exc_type = target->exc_type;
		target->exc_type = NULL;
		tstate->exc_value = target->exc_value;
		target->exc_value = NULL;
		tstate->exc_traceback = target->exc_traceback;
		target->exc_traceback = NULL;

		ts_current = target;
		Py_INCREF(target);
		Py_DECREF(origin);
		ts_passaround_args = args;
		ts_passaround_kwargs = kwargs;
	}
	return err;
}
Esempio n. 4
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. 5
0
static int g_switchstack(void)
{
	/* Perform a stack switch according to some global variables
	   that must be set before:
	   - ts_current: current greenlet (holds a reference)
	   - ts_target: greenlet to switch to (weak reference)
	   - ts_passaround_args: NULL if PyErr_Occurred(),
	       else a tuple of args sent to ts_target (holds a reference)
	   - ts_passaround_kwargs: switch kwargs (holds a reference)
	   On return results are passed via global variables as well:
	   - ts_origin: originating greenlet (holds a reference)
	   - ts_current: current greenlet (holds a reference)
	   - ts_passaround_args: NULL if PyErr_Occurred(),
	       else a tuple of args sent to ts_current (holds a reference)
	   - ts_passaround_kwargs: switch kwargs (holds a reference)
	   It is very important that stack switch is 'atomic', i.e. no
	   calls into other Python code allowed (except very few that
	   are safe), because global variables are very fragile.
	*/
	int err;
	{   /* save state */
		PyGreenlet* current = ts_current;
		PyThreadState* tstate = PyThreadState_GET();
		current->recursion_depth = tstate->recursion_depth;
		current->top_frame = tstate->frame;
		current->exc_type = tstate->exc_type;
		current->exc_value = tstate->exc_value;
		current->exc_traceback = tstate->exc_traceback;
	}
	err = slp_switch();
	if (err < 0) {   /* error */
		PyGreenlet* current = ts_current;
		current->top_frame = NULL;
		current->exc_type = NULL;
		current->exc_value = NULL;
		current->exc_traceback = NULL;

		assert(ts_origin == NULL);
		ts_target = NULL;
	}
	else {
		PyGreenlet* target = ts_target;
		PyGreenlet* origin = ts_current;
		PyThreadState* tstate = PyThreadState_GET();
		tstate->recursion_depth = target->recursion_depth;
		tstate->frame = target->top_frame;
		target->top_frame = NULL;
		tstate->exc_type = target->exc_type;
		target->exc_type = NULL;
		tstate->exc_value = target->exc_value;
		target->exc_value = NULL;
		tstate->exc_traceback = target->exc_traceback;
		target->exc_traceback = NULL;

		assert(ts_origin == NULL);
		Py_INCREF(target);
		ts_current = target;
		ts_origin = origin;
		ts_target = NULL;
	}
	return err;
}