[Stackless-checkins] CVS: slpdev/src/2.3/dev/Stackless/core cframeobject.c, 1.69, 1.70 slp_transfer.c, 1.21, 1.22 stackless_impl.h, 1.87, 1.88 stackless_structs.h, 1.62, 1.63 stackless_tstate.h, 1.50, 1.51 stackless_util.c, 1.18, 1.19 stacklesseval.c, 1.147, 1.148
Christian Tismer
tismer at centera.de
Mon May 24 03:01:23 CEST 2004
Update of /home/cvs/slpdev/src/2.3/dev/Stackless/core
In directory centera.de:/tmp/cvs-serv31331/core
Modified Files:
cframeobject.c slp_transfer.c stackless_impl.h
stackless_structs.h stackless_tstate.h stackless_util.c
stacklesseval.c
Log Message:
This is Stackless 3.1 alpha.
Stackless is supporting Real Threads!
There are a few glitches: The unit tests don't pass all, yet.
Revive_main has been dropped in favor of a global
dead-lock check. Maybe this needs a bit more work.
There is a global interthread lock. I'm not sure whether it is really needed.
Anyway, this thing works nicely with threads. I'm very happy to release
this new version, after a full week of day and night hacking.
Btw.: channels are not working compatibly, right now. Their policy
to prefer receivers to be unlocked is not set at the moment.
I will set the default back, ASAP and provide a computed attribute
to control this with the next check-in.
Index: cframeobject.c
===================================================================
RCS file: /home/cvs/slpdev/src/2.3/dev/Stackless/core/cframeobject.c,v
retrieving revision 1.69
retrieving revision 1.70
diff -C2 -d -r1.69 -r1.70
*** cframeobject.c 3 May 2004 16:53:39 -0000 1.69
--- cframeobject.c 24 May 2004 01:01:20 -0000 1.70
***************
*** 1,5 ****
/******************************************************
! The CFrame and friends
******************************************************/
--- 1,5 ----
/******************************************************
! The CFrame
******************************************************/
***************
*** 10,14 ****
* A CFrame does not appear in tracebacks, but it does
* play a role in frame chains.
- * At the moment, it can only appear as a toplevel frame of a tasklet.
*
* For simplicity, it mimicks the fields which slp_transfer needs
--- 10,13 ----
***************
*** 21,31 ****
* how to handle them.
*
! * In order to avoid incompatibilities with standard modules
! * like traceback, which might reach a cframe through
! * the extract_stack function, there is a couple of
! * computed attributes provided.
! *
! * XXX this is no longer true, baseframes don't show up in frame
! * chains any longer. Future target: use thunks, instead.
*/
--- 20,26 ----
* how to handle them.
*
! * XXX in a later, thunk-based implementation, CFrames should
! * vanish and be replaced by special thunks, which don't mess
! * with the frame chain.
*/
***************
*** 36,102 ****
#include "pickling/prickelpit.h"
- /* access macro to the members which are floating "behind" the object */
-
- #define PyBaseFrame_GET_MEMBERS(frame) \
- ((PyObject **)(((char *)frame) + (frame)->ob_type->tp_basicsize))
static void
! baseframe_dealloc(PyBaseFrameObject *c)
{
! int i;
! PyObject ** f_params = PyBaseFrame_GET_MEMBERS(c);
!
! PyObject_GC_UnTrack(c);
! Py_XDECREF(c->f_back);
! for (i=0; i < c->ob_size; ++i) {
! Py_XDECREF(f_params[i]);
! }
! PyObject_GC_Del(c);
}
static int
! baseframe_traverse(PyBaseFrameObject *c, visitproc visit, void *arg)
{
! int i, err;
! PyObject ** f_params = PyBaseFrame_GET_MEMBERS(c);
#define VISIT(o) if (o) {if ((err = visit((PyObject *)(o), arg))) return err;}
! VISIT(c->f_back);
! for (i=0; i < c->ob_size; ++i) {
! VISIT(f_params[i]);
! }
return 0;
}
! /* clearing a baseframe while the objects still exists */
static void
! baseframe_clear(PyBaseFrameObject *c)
{
! int i;
! PyObject ** f_params = PyBaseFrame_GET_MEMBERS(c);
!
! for (i=0; i < c->ob_size; ++i) {
! PyObject *hold = f_params[i];
! if (hold != NULL) {
! f_params[i] = NULL;
! Py_DECREF(hold);
! }
}
! /* note that the object is still alive, and ready for normal destruction without side effects */
}
! PyBaseFrameObject *
! slp_baseframe_new(PyFrame_ExecFunc *exec, unsigned int linked, unsigned int extra)
{
PyThreadState *ts = PyThreadState_GET();
! PyBaseFrameObject *c;
PyFrameObject *back;
- int i;
! c = PyObject_GC_NewVar(PyBaseFrameObject, &PyBaseFrame_Type, extra);
! if (c == NULL)
return NULL;
--- 31,89 ----
#include "pickling/prickelpit.h"
static void
! cframe_dealloc(PyCFrameObject *cf)
{
! PyObject_GC_UnTrack(cf);
! Py_XDECREF(cf->f_back);
! Py_XDECREF(cf->ob1);
! Py_XDECREF(cf->ob2);
! Py_XDECREF(cf->ob3);
! PyObject_GC_Del(cf);
}
static int
! cframe_traverse(PyCFrameObject *cf, visitproc visit, void *arg)
{
! int err;
#define VISIT(o) if (o) {if ((err = visit((PyObject *)(o), arg))) return err;}
! VISIT(cf->f_back);
! VISIT(cf->ob1);
! VISIT(cf->ob2);
! VISIT(cf->ob3);
! #undef VISIT
return 0;
}
! /* clearing a cframe while the object still exists */
static void
! cframe_clear(PyCFrameObject *cf)
{
! #define ZAP(x) \
! if (x != NULL) { \
! PyObject *_hold = (PyObject *) x; \
! x = NULL; \
! Py_XDECREF(_hold); \
}
! ZAP(cf->f_back);
! ZAP(cf->ob1);
! ZAP(cf->ob2);
! ZAP(cf->ob3);
! #undef ZAP
}
! PyCFrameObject *
! slp_cframe_new(PyFrame_ExecFunc *exec, unsigned int linked)
{
PyThreadState *ts = PyThreadState_GET();
! PyCFrameObject *cf;
PyFrameObject *back;
! cf = PyObject_GC_NewVar(PyCFrameObject, &PyCFrame_Type, 0);
! if (cf == NULL)
return NULL;
***************
*** 104,142 ****
if (!linked)
back = NULL;
-
Py_XINCREF(back);
! c->f_back = back;
! for (i=0; i < c->ob_size; ++i) {
! PyObject ** f_params = PyBaseFrame_GET_MEMBERS(c);
! f_params[i] = NULL;
! }
! c->f_execute = exec;
! _PyObject_GC_TRACK(c);
! return c;
}
! /* pickling support for baseframes and simple derived objects */
- #define baseframetuplefmt "iSO"
static PyObject *
! baseframe_reduce(PyBaseFrameObject *f)
{
PyObject *res = NULL, *exec_name = NULL;
PyObject *params = NULL;
! int valid = 1, extra;
! if ((exec_name = slp_find_execname((PyFrameObject *) f, &valid)) == NULL)
return NULL;
! extra = f->ob_size;
! params = slp_into_tuple_with_nulls(PyBaseFrame_GET_MEMBERS(f), extra);
if (params == NULL) goto err_exit;
! res = Py_BuildValue ("(O(" baseframetuplefmt "))",
! f->ob_type,
valid,
exec_name,
! params);
err_exit:
--- 91,129 ----
if (!linked)
back = NULL;
Py_XINCREF(back);
! cf->f_execute = exec;
! cf->f_back = back;
! cf->ob1 = cf->ob2 = cf->ob3 = NULL;
! cf->i = cf->n = 0;
! _PyObject_GC_TRACK(cf);
! return cf;
}
! /* pickling support for cframes */
!
! #define cframetuplefmt "iSOll"
! #define cframetuplenewfmt "iSO!ll:cframe"
static PyObject *
! cframe_reduce(PyCFrameObject *cf)
{
PyObject *res = NULL, *exec_name = NULL;
PyObject *params = NULL;
! int valid = 1;
! if ((exec_name = slp_find_execname((PyFrameObject *) cf, &valid)) == NULL)
return NULL;
! params = slp_into_tuple_with_nulls(&cf->ob1, 3);
if (params == NULL) goto err_exit;
! res = Py_BuildValue ("(O()(" cframetuplefmt "))",
! cf->ob_type,
valid,
exec_name,
! params,
! cf->i,
! cf->n);
err_exit:
***************
*** 146,220 ****
}
! static PyMethodDef baseframe_methods[] = {
! {"__reduce__", (PyCFunction)baseframe_reduce, METH_NOARGS, NULL},
! {NULL, NULL}
! };
! #define baseframetuplenewfmt "iSO!:baseframe"
static PyObject *
! baseframe_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
! PyBaseFrameObject *f;
int valid;
PyObject *exec_name = NULL;
PyFrame_ExecFunc *good_func, *bad_func;
PyObject *params;
! int extra;
!
! if (kwds != NULL) {
! PyErr_SetString(PyExc_ValueError,
! "Keyword parameters not supported"
! "for baseframe unpickling");
! return NULL;
! }
! if (!PyArg_ParseTuple (args, baseframetuplenewfmt,
&valid,
&exec_name,
! &PyTuple_Type, ¶ms))
return NULL;
! if (slp_find_execfuncs(type, exec_name, &good_func, &bad_func))
return NULL;
! extra = PyTuple_GET_SIZE(params)-1;
! f = slp_baseframe_new(valid ? good_func : bad_func, 0, extra);
! /* mark as from unpickling */
Py_INCREF(Py_None);
! f->f_back = (PyFrameObject *) Py_None;
! f->ob_type = type;
! slp_from_tuple_with_nulls(PyBaseFrame_GET_MEMBERS(f), params);
! return (PyObject *) f;
}
static PyObject * run_cframe(PyFrameObject *f, PyObject *retval)
{
PyThreadState *ts = PyThreadState_GET();
! PyCFrameObject *c = (PyCFrameObject*) f;
ts->frame = f;
! if (retval == NULL)
goto exit_run_cframe;
- if (c->callable == NULL) {
- /* we were left by a soft call */
- }
- else {
- Py_DECREF(retval);
- STACKLESS_PROPOSE_ALL();
- retval = PyObject_Call(c->callable, c->args, c->kwds);
- STACKLESS_ASSERT();
! if (STACKLESS_UNWINDING(retval)) {
! Py_DECREF(c->callable);
! c->callable = NULL;
! return retval;
}
}
/* pop frame */
exit_run_cframe:
! ts->frame = c->bf.f_back;
! Py_DECREF(f);
return retval;
}
--- 133,225 ----
}
! static PyObject *
! cframe_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
! {
! static char *kwlist[] = {NULL};
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, ":cframe", kwlist))
+ return NULL;
+ return (PyObject *) slp_cframe_new(NULL, 0);
+ }
! /* note that args is a tuple, although we use METH_O */
static PyObject *
! cframe_setstate(PyObject *self, PyObject *args)
{
! PyCFrameObject *cf = (PyCFrameObject *) self;
int valid;
PyObject *exec_name = NULL;
PyFrame_ExecFunc *good_func, *bad_func;
PyObject *params;
! int i, n;
! if (!PyArg_ParseTuple (args, cframetuplenewfmt,
&valid,
&exec_name,
! &PyTuple_Type, ¶ms,
! &i,
! &n))
return NULL;
! if (slp_find_execfuncs(cf->ob_type, exec_name, &good_func, &bad_func))
return NULL;
! if (PyTuple_GET_SIZE(params)-1 != 3)
! VALUE_ERROR("bad argument for cframe unpickling", NULL);
!
! /* mark this frame as coming from unpickling */
Py_INCREF(Py_None);
! cf->f_back = (PyFrameObject *) Py_None;
! cf->f_execute = valid ? good_func : bad_func;
! slp_from_tuple_with_nulls(&cf->ob1, params);
! cf->i = i;
! cf->n = n;
! Py_INCREF(cf);
! return (PyObject *) cf;
}
+ static PyMethodDef cframe_methods[] = {
+ {"__reduce__", (PyCFunction)cframe_reduce, METH_NOARGS, NULL},
+ {"__reduce_ex__", (PyCFunction)cframe_reduce, METH_VARARGS, NULL},
+ {"__setstate__", (PyCFunction)cframe_setstate, METH_O, NULL},
+ {NULL, NULL}
+ };
+
+
static PyObject * run_cframe(PyFrameObject *f, 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;
}
***************
*** 223,317 ****
PyCFrameObject *
! slp_cframe_new(PyObject *func, PyObject *args, PyObject *kwds, unsigned int linked)
{
! PyCFrameObject *c;
if (func == NULL || !PyCallable_Check(func))
! return TYPE_ERROR("cframe function must be a callable", NULL);
! c = (PyCFrameObject *)slp_baseframe_new(run_cframe, linked, 3);
! if (c == NULL)
return NULL;
- c->bf.ob_type = &PyCFrame_Type;
-
Py_INCREF(func);
! c->callable = func;
Py_INCREF(args);
! c->args = args;
Py_XINCREF(kwds);
! c->kwds = kwds;
! return c;
}
- static PyMemberDef baseframe_memberlist[] = {
- {"f_back", T_OBJECT, offsetof(PyCFrameObject, bf.f_back), RO},
- {"_exec_adr", T_INT, offsetof(PyCFrameObject, bf.f_execute), RO,
- "The address of the execute function of this frame.\n"
- "use f._exec_map[adr] to find its pickling name."},
- {NULL} /* Sentinel */
- };
-
static PyMemberDef cframe_memberlist[] = {
! {"f_back", T_OBJECT, offsetof(PyCFrameObject, bf.f_back), RO},
! {"callable", T_OBJECT, offsetof(PyCFrameObject, callable), RO},
! {"args", T_OBJECT, offsetof(PyCFrameObject, args), RO},
! {"kwds", T_OBJECT, offsetof(PyCFrameObject, kwds), RO},
! {"_exec_adr", T_INT, offsetof(PyCFrameObject, bf.f_execute), RO,
! "The address of the execute function of this frame.\n"
! "use f._exec_map[adr] to find its pickling name."},
{NULL} /* Sentinel */
};
-
- PyTypeObject PyBaseFrame_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "stackless.baseframe",
- sizeof(PyBaseFrameObject),
- sizeof(PyObject *),
- (destructor)baseframe_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- PyObject_GenericSetAttr, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
- 0, /* tp_doc */
- (traverseproc)baseframe_traverse, /* tp_traverse */
- (inquiry) baseframe_clear, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- baseframe_methods, /* tp_methods */
- baseframe_memberlist, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- baseframe_new, /* tp_new */
- _PyObject_Del, /* tp_free */
- };
-
-
PyTypeObject PyCFrame_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"stackless.cframe",
! sizeof(PyBaseFrameObject),
! sizeof(PyObject *),
! (destructor)baseframe_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
--- 228,266 ----
PyCFrameObject *
! slp_cframe_newfunc(PyObject *func, PyObject *args, PyObject *kwds, unsigned int linked)
{
! PyCFrameObject *cf;
if (func == NULL || !PyCallable_Check(func))
! TYPE_ERROR("cframe function must be a callable", NULL);
! cf = slp_cframe_new(run_cframe, linked);
! if (cf == NULL)
return NULL;
Py_INCREF(func);
! cf->ob1 = func;
Py_INCREF(args);
! cf->ob2 = args;
Py_XINCREF(kwds);
! cf->ob3 = kwds;
! return cf;
}
static PyMemberDef cframe_memberlist[] = {
! {"f_back", T_OBJECT, offsetof(PyCFrameObject, f_back), RO},
! {"ob1", T_OBJECT, offsetof(PyCFrameObject, ob1), RO},
! {"ob2", T_OBJECT, offsetof(PyCFrameObject, ob2), RO},
! {"ob3", T_OBJECT, offsetof(PyCFrameObject, ob3), RO},
! {"i", T_LONG, offsetof(PyCFrameObject, i), RO},
! {"n", T_LONG, offsetof(PyCFrameObject, n), RO},
{NULL} /* Sentinel */
};
PyTypeObject PyCFrame_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"stackless.cframe",
! sizeof(PyCFrameObject),
! 0,
! (destructor)cframe_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
***************
*** 328,343 ****
PyObject_GenericSetAttr, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
0, /* tp_doc */
! (traverseproc)baseframe_traverse, /* tp_traverse */
! (inquiry) baseframe_clear, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
! 0, /* tp_methods */
cframe_memberlist, /* tp_members */
0, /* tp_getset */
! &PyBaseFrame_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
--- 277,292 ----
PyObject_GenericSetAttr, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
0, /* tp_doc */
! (traverseproc)cframe_traverse, /* tp_traverse */
! (inquiry) cframe_clear, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
! cframe_methods, /* tp_methods */
cframe_memberlist, /* tp_members */
0, /* tp_getset */
! 0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
***************
*** 346,350 ****
0, /* tp_init */
0, /* tp_alloc */
! baseframe_new, /* tp_new */
_PyObject_Del, /* tp_free */
};
--- 295,299 ----
0, /* tp_init */
0, /* tp_alloc */
! cframe_new, /* tp_new */
_PyObject_Del, /* tp_free */
};
***************
*** 353,357 ****
{
/* register the cframe exec func */
! return slp_register_execute(&PyCFrame_Type, "run_frame",
run_cframe, REF_INVALID_EXEC(run_cframe));
}
--- 302,306 ----
{
/* register the cframe exec func */
! return slp_register_execute(&PyCFrame_Type, "run_cframe",
run_cframe, REF_INVALID_EXEC(run_cframe));
}
Index: slp_transfer.c
===================================================================
RCS file: /home/cvs/slpdev/src/2.3/dev/Stackless/core/slp_transfer.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -C2 -d -r1.21 -r1.22
*** slp_transfer.c 29 Apr 2004 18:13:42 -0000 1.21
--- slp_transfer.c 24 May 2004 01:01:20 -0000 1.22
***************
*** 35,44 ****
stsizeb = (_cst->startaddr - stackref) * sizeof(int*); \
if (_cst == NULL) return 0; \
! stsizediff = stsizeb - (_cst->ob_size * sizeof(int*));
#define SLP_RESTORE_STATE() \
if (_cst != NULL) { \
slp_cstack_restore(_cst); \
- _cst->tstate->st.nesting_level = _cst->nesting_level; \
}
--- 35,43 ----
stsizeb = (_cst->startaddr - stackref) * sizeof(int*); \
if (_cst == NULL) return 0; \
! stsizediff = stsizeb - (_cst->ob_size * sizeof(int*));
#define SLP_RESTORE_STATE() \
if (_cst != NULL) { \
slp_cstack_restore(_cst); \
}
***************
*** 82,86 ****
if ((int*) &ts > ts->st.cstack_base)
return climb_stack_and_transfer(cstprev, cst, prev);
! if (cst == NULL)
cst = ts->st.initial_stub;
if (cst != NULL) {
--- 81,85 ----
if ((int*) &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) {
Index: stackless_impl.h
===================================================================
RCS file: /home/cvs/slpdev/src/2.3/dev/Stackless/core/stackless_impl.h,v
retrieving revision 1.87
retrieving revision 1.88
diff -C2 -d -r1.87 -r1.88
*** stackless_impl.h 13 May 2004 02:00:26 -0000 1.87
--- stackless_impl.h 24 May 2004 01:01:20 -0000 1.88
***************
*** 34,51 ****
/********************************************************************
*
- * This section defines/references stuff from cframeobject.c
- *
- ********************************************************************/
-
- PyAPI_DATA(PyTypeObject) PyCFrame_Type;
- PyAPI_DATA(PyTypeObject) PyBaseFrame_Type;
-
- #define PyBaseFrame_Check(op) PyObject_TypeCheck(op, &PyBaseFrame_Type)
- #define PyBaseFrame_CheckExact(op) ((op)->ob_type == &PyBaseFrame_Type)
- #define PyCFrame_Check(op) PyObject_TypeCheck(op, &PyCFrame_Type)
- #define PyCFrame_CheckExact(op) ((op)->ob_type == &PyCFrame_Type)
-
- /********************************************************************
- *
* This section defines/references stuff from stacklesseval.c
*
--- 34,37 ----
***************
*** 56,59 ****
--- 42,46 ----
PyAPI_DATA(int) slp_enable_softswitch;
PyAPI_DATA(int) slp_try_stackless;
+ PyAPI_DATA(PyCStackObject *) slp_cstack_chain;
PyAPI_FUNC(PyCStackObject *) slp_cstack_new(PyCStackObject **cst,
***************
*** 80,84 ****
PyAPI_FUNC(void) PyStacklessEval_Fini(void);
! PyAPI_FUNC(void) PyStackless_kill_tasks_with_stacks(void);
/* the special version of eval_frame */
--- 67,71 ----
PyAPI_FUNC(void) PyStacklessEval_Fini(void);
! PyAPI_FUNC(void) PyStackless_kill_tasks_with_stacks(int allthreads);
/* the special version of eval_frame */
***************
*** 91,96 ****
/* the frame dispatcher for toplevel tasklets */
! PyAPI_FUNC(PyObject *) slp_frame_dispatch_top(PyFrameObject *f,
! PyObject *retval);
/* the now exported eval_frame */
--- 78,82 ----
/* the frame dispatcher for toplevel tasklets */
! PyAPI_FUNC(PyObject *) slp_frame_dispatch_top(PyObject *retval);
/* the now exported eval_frame */
***************
*** 98,101 ****
--- 84,90 ----
PyObject *retval);
+ /* eval_frame with stack overflow, triggered there with a macro */
+ PyAPI_FUNC(PyObject *) slp_eval_frame_newstack(f, retval);
+
/* the new eval_frame loop with or without value or resuming an iterator */
PyAPI_FUNC(PyObject *) PyEval_EvalFrame_value(struct _frame *f,
***************
*** 331,340 ****
PyAPI_FUNC(void) slp_channel_insert(PyChannelObject *channel,
PyTaskletObject *task, int dir);
! PyAPI_FUNC(PyTaskletObject) * slp_channel_remove(PyChannelObject *channel,
int dir);
! PyAPI_FUNC(PyTaskletObject) * slp_channel_remove_specific(
PyChannelObject *channel,
int dir, PyTaskletObject *task);
! PyAPI_FUNC(PyTaskletObject) * slp_channel_remove_slow(PyTaskletObject *task);
/* tasklet/scheduling operations */
--- 320,337 ----
PyAPI_FUNC(void) slp_channel_insert(PyChannelObject *channel,
PyTaskletObject *task, int dir);
! PyAPI_FUNC(PyTaskletObject *) slp_channel_remove(PyChannelObject *channel,
int dir);
! PyAPI_FUNC(PyTaskletObject *) slp_channel_remove_specific(
PyChannelObject *channel,
int dir, PyTaskletObject *task);
! PyAPI_FUNC(PyTaskletObject *) slp_channel_remove_slow(PyTaskletObject *task);
!
! /* recording the main thread state */
!
! PyAPI_DATA(PyThreadState *) slp_initial_tstate;
!
! /* protecting soft-switched tasklets in other threads */
!
! PyAPI_FUNC(int) slp_ensure_linkage(PyTaskletObject *task);
/* tasklet/scheduling operations */
***************
*** 387,393 ****
/* tasklet startup */
! PyAPI_FUNC(PyObject *) slp_run_tasklet(PyFrameObject *f);
! PyAPI_FUNC(PyObject *) slp_resume_tasklet(PyFrameObject *f);
! PyAPI_FUNC(int) initialize_main_and_current(PyFrameObject *f);
/* handy abbrevations */
--- 384,388 ----
/* tasklet startup */
! PyAPI_FUNC(PyObject *) slp_run_tasklet(void);
/* handy abbrevations */
***************
*** 409,423 ****
#endif
! #define TYPE_ERROR(str, ret) (slp_type_error(str), ret)
! #define RUNTIME_ERROR(str, ret) (slp_runtime_error(str), ret)
! #define VALUE_ERROR(str, ret) (slp_value_error(str), ret)
! PyAPI_FUNC(PyBaseFrameObject *) slp_baseframe_new(PyFrame_ExecFunc *exec,
! unsigned int linked,
! unsigned int extra);
! PyAPI_FUNC(PyCFrameObject *) slp_cframe_new(PyObject *func,
! PyObject *args,
! PyObject *kwds,
unsigned int linked);
PyAPI_FUNC(PyFrameObject *) slp_get_frame(PyTaskletObject *task);
--- 404,417 ----
#endif
! #define TYPE_ERROR(str, ret) return (slp_type_error(str), ret)
! #define RUNTIME_ERROR(str, ret) return (slp_runtime_error(str), ret)
! #define VALUE_ERROR(str, ret) return (slp_value_error(str), ret)
! PyAPI_FUNC(PyCFrameObject *) slp_cframe_new(PyFrame_ExecFunc *exec,
unsigned int linked);
+ PyAPI_FUNC(PyCFrameObject *) slp_cframe_newfunc(PyObject *func,
+ PyObject *args,
+ PyObject *kwds,
+ unsigned int linked);
PyAPI_FUNC(PyFrameObject *) slp_get_frame(PyTaskletObject *task);
***************
*** 429,433 ****
PyAPI_FUNC(int) slp_resurrect_and_kill(PyObject *self,
void(*killer)(PyObject *));
- PyAPI_FUNC(int) slp_revive_main(void);
/* stackless pickling support */
--- 423,426 ----
Index: stackless_structs.h
===================================================================
RCS file: /home/cvs/slpdev/src/2.3/dev/Stackless/core/stackless_structs.h,v
retrieving revision 1.62
retrieving revision 1.63
diff -C2 -d -r1.62 -r1.63
*** stackless_structs.h 12 May 2004 15:33:56 -0000 1.62
--- stackless_structs.h 24 May 2004 01:01:20 -0000 1.63
***************
*** 76,83 ****
struct _cframe *cframe;
} f;
- /*
- PyObject *channel;
- */
- PyFrameObject *topframe;
PyObject *tempval;
/* bits stuff */
--- 76,79 ----
***************
*** 159,165 ****
! /*** important stuctures: baseframe, cframe ***/
! typedef struct _baseframe {
PyObject_VAR_HEAD
struct _frame *f_back; /* previous frame, or NULL */
--- 155,161 ----
! /*** important stuctures: cframe ***/
! typedef struct _cframe {
PyObject_VAR_HEAD
struct _frame *f_back; /* previous frame, or NULL */
***************
*** 172,185 ****
*/
! } PyBaseFrameObject;
!
!
! /* "derived" cframe */
! typedef struct _cframe {
! PyBaseFrameObject bf;
! PyObject *callable;
! PyObject *args;
! PyObject *kwds;
} PyCFrameObject;
--- 168,177 ----
*/
! /* these can be used as the CFrame likes to */
! PyObject *ob1;
! PyObject *ob2;
! PyObject *ob3;
! long i, n;
} PyCFrameObject;
***************
*** 198,204 ****
/*** associated type objects ***/
- PyAPI_DATA(PyTypeObject) PyBaseFrame_Type;
PyAPI_DATA(PyTypeObject) PyCFrame_Type;
PyAPI_DATA(PyTypeObject) PyCStack_Type;
PyAPI_DATA(PyTypeObject) PyBomb_Type;
--- 190,198 ----
/*** associated type objects ***/
PyAPI_DATA(PyTypeObject) PyCFrame_Type;
+ #define PyCFrame_Check(op) ((op)->ob_type == &PyCFrame_Type)
+
PyAPI_DATA(PyTypeObject) PyCStack_Type;
+ #define PyCStack_Check(op) ((op)->ob_type == &PyCStack_Type)
PyAPI_DATA(PyTypeObject) PyBomb_Type;
Index: stackless_tstate.h
===================================================================
RCS file: /home/cvs/slpdev/src/2.3/dev/Stackless/core/stackless_tstate.h,v
retrieving revision 1.50
retrieving revision 1.51
diff -C2 -d -r1.50 -r1.51
*** stackless_tstate.h 12 May 2004 15:33:56 -0000 1.50
--- stackless_tstate.h 24 May 2004 01:01:20 -0000 1.51
***************
*** 12,19 ****
long serial_last_jump;
#endif
! /* the list of all stacks of this thread */
! struct _cstack *cstack_chain;
! /* the base address for hijacking stacks */
int *cstack_base;
/* main tasklet */
struct _tasklet *main;
--- 12,19 ----
long serial_last_jump;
#endif
! /* the base address for hijacking stacks. XXX deprecating */
int *cstack_base;
+ /* stack overflow check and init flag */
+ int *cstack_root;
/* main tasklet */
struct _tasklet *main;
***************
*** 28,48 ****
/* trap recursive scheduling via callbacks */
int schedlock;
!
/* number of nested interpreters (1.0/2.0 merge) */
int nesting_level;
- /* common return frame for all tasklets (3.0) */
- /* XXX this is about to be removed, since we always
- have cframes on top now */
- struct _frame *tasklet_runner;
} PyStacklessState;
/* these macros go into pystate.c */
! #define STACKLESS_PYSTATE_NEW \
tstate->st.initial_stub = NULL; \
tstate->st.serial = 0; \
tstate->st.serial_last_jump = 0; \
- tstate->st.cstack_chain = NULL; \
tstate->st.cstack_base = NULL; \
tstate->st.ticker = 0; \
tstate->st.interval = 0; \
--- 28,50 ----
/* trap recursive scheduling via callbacks */
int schedlock;
! #ifdef WITH_THREAD
! struct {
! PyObject *self_lock;
! PyObject *unlock_lock;
! int is_locked;
! } thread;
! #endif
/* number of nested interpreters (1.0/2.0 merge) */
int nesting_level;
} PyStacklessState;
/* these macros go into pystate.c */
! #define __STACKLESS_PYSTATE_NEW \
tstate->st.initial_stub = NULL; \
tstate->st.serial = 0; \
tstate->st.serial_last_jump = 0; \
tstate->st.cstack_base = NULL; \
+ tstate->st.cstack_root = NULL; \
tstate->st.ticker = 0; \
tstate->st.interval = 0; \
***************
*** 52,57 ****
tstate->st.current = NULL; \
tstate->st.runcount = 0; \
! tstate->st.nesting_level = 0; \
! tstate->st.tasklet_runner = NULL;
/* note that the scheduler knows how to zap. It checks if it is in charge
--- 54,58 ----
tstate->st.current = NULL; \
tstate->st.runcount = 0; \
! tstate->st.nesting_level = 0;
/* note that the scheduler knows how to zap. It checks if it is in charge
***************
*** 64,69 ****
void slp_kill_tasks_with_stacks(struct _ts *tstate);
! #define STACKLESS_PYSTATE_ZAP \
slp_kill_tasks_with_stacks(tstate); \
! ZAP(tstate->st.initial_stub); \
! ZAP(tstate->st.tasklet_runner);
--- 65,93 ----
void slp_kill_tasks_with_stacks(struct _ts *tstate);
! #define __STACKLESS_PYSTATE_ZAP \
slp_kill_tasks_with_stacks(tstate); \
! ZAP(tstate->st.initial_stub);
!
! #ifdef WITH_THREAD
!
! #define STACKLESS_PYSTATE_NEW \
! __STACKLESS_PYSTATE_NEW \
! tstate->st.thread.self_lock = NULL; \
! tstate->st.thread.unlock_lock = NULL; \
! tstate->st.thread.is_locked = 0;
!
!
! #define STACKLESS_PYSTATE_ZAP \
! __STACKLESS_PYSTATE_ZAP \
! ZAP(tstate->st.thread.self_lock); \
! ZAP(tstate->st.thread.unlock_lock);
!
! #else
!
! #define STACKLESS_PYSTATE_NEW __STACKLESS_PYSTATE_NEW
! #define STACKLESS_PYSTATE_ZAP __STACKLESS_PYSTATE_ZAP
!
! #undef __STACKLESS_PYSTATE_NEW
! #undef __STACKLESS_PYSTATE_ZAP
!
! #endif
Index: stackless_util.c
===================================================================
RCS file: /home/cvs/slpdev/src/2.3/dev/Stackless/core/stackless_util.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -C2 -d -r1.18 -r1.19
*** stackless_util.c 12 May 2004 15:33:56 -0000 1.18
--- stackless_util.c 24 May 2004 01:01:20 -0000 1.19
***************
*** 41,49 ****
slp_get_frame(PyTaskletObject *task)
{
! PyThreadState *ts;
- if (task->topframe == NULL || task->cstate == NULL)
- return NULL;
- ts = task->cstate->tstate;
return ts->st.current == task ? ts->frame : task->f.frame;
}
--- 41,46 ----
slp_get_frame(PyTaskletObject *task)
{
! PyThreadState *ts = PyThreadState_GET();
return ts->st.current == task ? ts->frame : task->f.frame;
}
Index: stacklesseval.c
===================================================================
RCS file: /home/cvs/slpdev/src/2.3/dev/Stackless/core/stacklesseval.c,v
retrieving revision 1.147
retrieving revision 1.148
diff -C2 -d -r1.147 -r1.148
*** stacklesseval.c 12 May 2004 15:33:56 -0000 1.147
--- stacklesseval.c 24 May 2004 01:01:20 -0000 1.148
***************
*** 33,36 ****
--- 33,40 ----
int slp_try_stackless = 0;
+ /* the list of all stacks of all threads */
+ struct _cstack *slp_cstack_chain = NULL;
+
+
/******************************************************
***************
*** 39,48 ****
******************************************************/
- /* adjust slots to typical size for your system */
-
- #define CSTACK_SLOTS 1024
- #define CSTACK_MAXCACHE 100
- #define CSTACK_GOODGAP 4096
-
static PyCStackObject *cstack_cache[CSTACK_SLOTS] = { NULL };
static int cstack_cachecount = 0;
--- 43,46 ----
***************
*** 69,74 ****
PyThreadState *ts = PyThreadState_GET();
! ts->st.cstack_chain = cst;
! SLP_CHAIN_REMOVE(PyCStackObject, &ts->st.cstack_chain, cst, next,
prev);
if (cst->ob_size >= CSTACK_SLOTS) {
--- 67,72 ----
PyThreadState *ts = PyThreadState_GET();
! slp_cstack_chain = cst;
! SLP_CHAIN_REMOVE(PyCStackObject, &slp_cstack_chain, cst, next,
prev);
if (cst->ob_size >= CSTACK_SLOTS) {
***************
*** 92,99 ****
int size = stackbase - stackref;
! if (size < 0) {
! PyErr_SetString(PyExc_RuntimeError, "negative stack size");
! return NULL;
! }
if (*cst && (*cst)->ob_size == size && (*cst)->ob_refcnt == 1) {
/* reuse it */
--- 90,95 ----
int size = stackbase - stackref;
! if (size < 0)
! RUNTIME_ERROR("negative stack size", NULL);
if (*cst && (*cst)->ob_size == size && (*cst)->ob_refcnt == 1) {
/* reuse it */
***************
*** 123,127 ****
(*cst)->startaddr = stackbase;
(*cst)->next = (*cst)->prev = NULL;
! SLP_CHAIN_INSERT(PyCStackObject, &ts->st.cstack_chain, *cst, next, prev);
(*cst)->serial = ts->st.serial;
(*cst)->task = task;
--- 119,123 ----
(*cst)->startaddr = stackbase;
(*cst)->next = (*cst)->prev = NULL;
! SLP_CHAIN_INSERT(PyCStackObject, &slp_cstack_chain, *cst, next, prev);
(*cst)->serial = ts->st.serial;
(*cst)->task = task;
***************
*** 144,147 ****
--- 140,144 ----
slp_cstack_restore(PyCStackObject *cst)
{
+ cst->tstate->st.nesting_level = cst->nesting_level;
/* mark task as no longer responsible for cstack instance */
cst->task = NULL;
***************
*** 215,228 ****
0, /* tp_methods */
cstack_members, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- 0, /* tp_new */
- 0, /* tp_free */
};
--- 212,215 ----
***************
*** 237,241 ****
ts->st.initial_stub = NULL;
}
! ++ts->st.serial;
if (slp_transfer(&ts->st.initial_stub, NULL, NULL)) return -1;
ts->st.initial_stub->serial = ts->st.serial;
--- 224,228 ----
ts->st.initial_stub = NULL;
}
! ts->st.serial_last_jump = ++ts->st.serial;
if (slp_transfer(&ts->st.initial_stub, NULL, NULL)) return -1;
ts->st.initial_stub->serial = ts->st.serial;
***************
*** 246,249 ****
--- 233,237 ----
* To insure that, it was necessary to re-create the
* initial stub for *every* run of a new main.
+ * This will vanish with greenlet-like stack management.
*/
***************
*** 291,317 ****
* Reason: (observed with wxPython):
* A toplevel frame is run as a tasklet. When its frame
! * is deallocated (in slp_tasklet_end), a Python object
* with a __del__ method is destroyed. This __del__
! * will run as a toplevel frame, with fback == NULL!
*/
stackref = STACK_REFPLUS + (int*) &f;
! if (ts->st.cstack_base == NULL)
! ts->st.cstack_base = stackref-CSTACK_GOODGAP;
! if (stackref > ts->st.cstack_base)
! return climb_stack_and_eval_frame(f);
ts->frame = f;
if (make_initial_stub())
return NULL;
! f = ts->frame;
! if (f == NULL)
! return NULL;
! if (f->f_back == NULL || f->f_back == ts->st.tasklet_runner) {
! /* this is really a new tasklet or main */
! /* I hope very much to get rid of this hack, soon */
! return slp_run_tasklet(f);
! }
! return slp_resume_tasklet(f);
}
Py_INCREF(Py_None);
--- 279,297 ----
* Reason: (observed with wxPython):
* A toplevel frame is run as a tasklet. When its frame
! * is deallocated (in tasklet_end), a Python object
* with a __del__ method is destroyed. This __del__
! * will run as a toplevel frame, with f_back == NULL!
*/
stackref = STACK_REFPLUS + (int*) &f;
! if (ts->st.cstack_base == NULL)
! ts->st.cstack_base = stackref-CSTACK_GOODGAP;
! if (stackref > ts->st.cstack_base)
! return climb_stack_and_eval_frame(f);
ts->frame = f;
if (make_initial_stub())
return NULL;
! return slp_run_tasklet();
}
Py_INCREF(Py_None);
***************
*** 319,357 ****
}
! void slp_kill_tasks_with_stacks(struct _ts *tstate)
{
- PyThreadState *ts = PyThreadState_GET();
- PyObject *exception, *value, *tb;
int count = 0;
- if (ts != tstate) {
- /* too bad, can't handle this, give up */
- return;
- }
- PyErr_Fetch(&exception, &value, &tb);
while (1) {
! PyCStackObject *csfirst = ts->st.cstack_chain, *cs = csfirst;
PyTaskletObject *t;
! if (cs == NULL)
break;
! while (cs->task == NULL && cs->next != csfirst) {
! cs = cs->next;
! ++count; /* for debugging */
! }
count = 0;
- if (cs->task == NULL)
- return;
t = cs->task;
! cs->task = NULL;
PyTasklet_Kill(t);
PyErr_Clear();
}
- PyErr_Restore(exception, value, tb);
}
! void PyStackless_kill_tasks_with_stacks(void)
{
! slp_kill_tasks_with_stacks(PyThreadState_GET());
}
--- 299,345 ----
}
! void slp_kill_tasks_with_stacks(PyThreadState *ts)
{
int count = 0;
while (1) {
! PyCStackObject *csfirst = slp_cstack_chain, *cs;
PyTaskletObject *t;
! if (csfirst == NULL)
break;
! for (cs = csfirst; ; cs = cs->next) {
! if (count && cs == csfirst) {
! /* nothing found */
! return;
! }
! ++count;
! if (cs->task == NULL)
! continue;
! if (ts != NULL && cs->tstate != ts)
! continue;
! break;
! }
count = 0;
t = cs->task;
! Py_INCREF(t);
!
PyTasklet_Kill(t);
PyErr_Clear();
+
+ if (t->f.frame == 0) {
+ /* ensure a valid tstate */
+ t->cstate->tstate = slp_initial_tstate;
+ }
+ Py_DECREF(t);
}
}
! void PyStackless_kill_tasks_with_stacks(int allthreads)
{
! PyThreadState *ts = PyThreadState_Get();
! PyInterpreterState *interp = ts->interp;
!
! slp_kill_tasks_with_stacks(allthreads ? NULL : ts);
}
***************
*** 363,366 ****
--- 351,408 ----
+ /* cstack spilling for recursive calls */
+
+ static PyObject *
+ eval_frame_callback(PyFrameObject *f, PyObject *retval)
+ {
+ PyThreadState *ts = PyThreadState_GET();
+ PyTaskletObject *cur = ts->st.current;
+ PyCStackObject *cst = cur->cstate;
+
+ ts->frame = f->f_back;
+ Py_DECREF(f);
+ retval = PyEval_EvalFrame(ts->frame, retval);
+ TASKLET_SETVAL_OWN(cur, retval);
+ /* jump back */
+ slp_transfer_return(cst);
+ /* never come here */
+ return NULL;
+ }
+
+ PyObject *
+ slp_eval_frame_newstack(PyFrameObject *f, PyObject *retval)
+ {
+ PyThreadState *ts = PyThreadState_GET();
+ PyTaskletObject *cur = ts->st.current;
+ PyCFrameObject *cf = NULL;
+ PyCStackObject *cst;
+
+ if (ts->st.cstack_root == NULL) {
+ /* this is a toplevel call */
+ ts->st.cstack_root = STACK_REFPLUS + (int*) &f;
+ retval = PyEval_EvalFrame(f, retval);
+ return retval;
+ }
+
+ ts->frame = f;
+ cf = slp_cframe_new(eval_frame_callback, 1);
+ if (cf == NULL)
+ return NULL;
+ ts->frame = (PyFrameObject *) cf;
+ cst = cur->cstate;
+ cur->cstate = NULL;
+ Py_XDECREF(retval);
+ if (slp_transfer(&cur->cstate, NULL, cur))
+ goto finally; /* fatal */
+ Py_XDECREF(cur->cstate);
+ retval = cur->tempval;
+ Py_INCREF(retval);
+ if (PyBomb_Check(retval))
+ retval = slp_bomb_explode(cur);
+ finally:
+ cur->cstate = cst;
+ return retval;
+ }
+
/******************************************************
***************
*** 390,400 ****
*/
- typedef struct _gen_callback_frame {
- PyBaseFrameObject bf;
- genobject *gen;
- } gen_callback_frame;
- #define GEN_CALLBACK_FRAME_SIZE ((sizeof(gen_callback_frame) - \
- sizeof(PyBaseFrameObject))/sizeof(PyObject*))
-
static PyObject* gen_iternext_callback(PyFrameObject *f, PyObject *retval);
--- 432,435 ----
***************
*** 419,424 ****
if (f->f_back == NULL &&
(f->f_back = (PyFrameObject *)
! slp_baseframe_new(gen_iternext_callback, 0,
! GEN_CALLBACK_FRAME_SIZE)) == NULL)
return NULL;
/* Generators always return to their most recent caller, not
--- 454,458 ----
if (f->f_back == NULL &&
(f->f_back = (PyFrameObject *)
! slp_cframe_new(gen_iternext_callback, 0)) == NULL)
return NULL;
/* Generators always return to their most recent caller, not
***************
*** 439,443 ****
Py_INCREF(gen);
! ((gen_callback_frame *) f->f_back)->gen = gen;
Py_INCREF(f);
ts->frame = f;
--- 473,477 ----
Py_INCREF(gen);
! ((PyCFrameObject *) f->f_back)->ob1 = (PyObject *) gen;
Py_INCREF(f);
ts->frame = f;
***************
*** 451,456 ****
{
PyThreadState *ts = PyThreadState_GET();
! gen_callback_frame *gcf = (gen_callback_frame*) f;
! genobject *gen = gcf->gen;
gen->gi_running = 0;
--- 485,490 ----
{
PyThreadState *ts = PyThreadState_GET();
! PyCFrameObject *cf = (PyCFrameObject *) f;
! genobject *gen = (genobject *) cf->ob1;
gen->gi_running = 0;
***************
*** 478,482 ****
}
}
! gcf->gen = NULL;
Py_DECREF(gen);
return retval;
--- 512,516 ----
}
}
! cf->ob1 = NULL;
Py_DECREF(gen);
return retval;
***************
*** 571,579 ****
PyObject *
! slp_frame_dispatch_top(PyFrameObject *f, PyObject *retval)
{
PyThreadState *ts = PyThreadState_GET();
! if (f==NULL) return NULL;
while (1) {
--- 605,614 ----
PyObject *
! slp_frame_dispatch_top(PyObject *retval)
{
PyThreadState *ts = PyThreadState_GET();
+ PyFrameObject *f = ts->frame;
! if (f==NULL) return retval;
while (1) {
***************
*** 586,590 ****
break;
}
! return retval;
}
--- 621,625 ----
break;
}
! return retval;
}
_______________________________________________
Stackless-checkins mailing list
Stackless-checkins at stackless.com
http://www.stackless.com/mailman/listinfo/stackless-checkins
More information about the Stackless-checkins
mailing list