[Stackless-checkins] CVS: slpdev/src/2.3/dev/Stackless/core slp_transfer.c, 1.26, 1.27 stackless_impl.h, 1.94, 1.95 stacklesseval.c, 1.155, 1.156
Christian Tismer
tismer at centera.de
Thu Jun 3 20:02:15 CEST 2004
Update of /home/cvs/slpdev/src/2.3/dev/Stackless/core
In directory centera.de:/tmp/cvs-serv17074/Stackless/core
Modified Files:
slp_transfer.c stackless_impl.h stacklesseval.c
Log Message:
hmm, all undone.
Seems to need just -O0
Index: slp_transfer.c
===================================================================
RCS file: /home/cvs/slpdev/src/2.3/dev/Stackless/core/slp_transfer.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -C2 -d -r1.26 -r1.27
*** slp_transfer.c 3 Jun 2004 17:34:21 -0000 1.26
--- slp_transfer.c 3 Jun 2004 18:02:11 -0000 1.27
***************
*** 46,352 ****
#include "platf/slp_platformselect.h"
- /* these functions must be here, too, to prevend inlining */
-
- /******************************************************
-
- The C Stack
-
- ******************************************************/
-
- static PyCStackObject *cstack_cache[CSTACK_SLOTS] = { NULL };
- static int cstack_cachecount = 0;
-
- /* this function will get called by PyStacklessEval_Fini */
- void slp_cstack_cacheclear(void)
- {
- int i;
- PyCStackObject *stack;
-
- for (i=0; i < CSTACK_SLOTS; i++) {
- while (cstack_cache[i] != NULL) {
- stack = cstack_cache[i];
- cstack_cache[i] = (PyCStackObject *) stack->startaddr;
- PyMem_Free(stack);
- }
- }
- cstack_cachecount = 0;
- }
-
- static void
- cstack_dealloc(PyCStackObject *cst)
- {
- slp_cstack_chain = cst;
- SLP_CHAIN_REMOVE(PyCStackObject, &slp_cstack_chain, cst, next,
- prev);
- if (cst->ob_size >= CSTACK_SLOTS) {
- PyMem_Free(cst);
- }
- else {
- if (cstack_cachecount >= CSTACK_MAXCACHE)
- slp_cstack_cacheclear();
- cst->startaddr = (int *) cstack_cache[cst->ob_size];
- cstack_cache[cst->ob_size] = cst;
- ++cstack_cachecount;
- }
- }
-
-
- /* slp_cstack_save/restore moved to slp_transfer */
-
- static char cstack_doc[] =
- "A CStack object serves to save the stack slice which is involved\n\
- during a recursive Python call. It will also be used for pickling\n\
- of program state. This structure is highly platform dependant.\n\
- Note: For inspection, str() can dump it as a string.\
- ";
-
- #if SIZEOF_VOIDP == SIZEOF_INT
- #define T_ADDR T_UINT
- #else
- #define T_ADDR T_ULONG
- #endif
-
-
- static PyMemberDef cstack_members[] = {
- {"size", T_INT, offsetof(PyCStackObject, ob_size), READONLY},
- {"next", T_OBJECT, offsetof(PyCStackObject, next), READONLY},
- {"prev", T_OBJECT, offsetof(PyCStackObject, prev), READONLY},
- {"task", T_OBJECT, offsetof(PyCStackObject, task), READONLY},
- {"startaddr", T_ADDR, offsetof(PyCStackObject, startaddr), READONLY},
- {0}
- };
-
- /* simple string interface for inspection */
-
- static PyObject *
- cstack_str(PyObject *o)
- {
- PyCStackObject *cst = (PyCStackObject*)o;
- return PyString_FromStringAndSize((char*)&cst->stack,
- cst->ob_size*sizeof(cst->stack[0]));
- }
-
- PyTypeObject PyCStack_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "stackless.cstack",
- sizeof(PyCStackObject),
- sizeof(PyObject *),
- (destructor)cstack_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 */
- (reprfunc)cstack_str, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- PyObject_GenericSetAttr, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- cstack_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- cstack_members, /* tp_members */
- };
-
- /*
- * slp_eval_frame moved to slp_transfer.c
- * to avoid optimization in gcc 3.3.2
- */
-
- 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);
- }
- }
-
- PyCStackObject *
- slp_cstack_new(PyCStackObject **cst, int *stackref, PyTaskletObject *task)
- {
- PyThreadState *ts = PyThreadState_GET();
- int *stackbase = ts->st.cstack_base;
- 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 */
- (*cst)->task = task;
- return *cst;
- }
-
- if (*cst != NULL) {
- if ((*cst)->task == task)
- (*cst)->task = NULL;
- Py_DECREF(*cst);
- }
- if (size < CSTACK_SLOTS && ((*cst) = cstack_cache[size])) {
- /* take stack from cache */
- cstack_cache[size] = (PyCStackObject *) (*cst)->startaddr;
- --cstack_cachecount;
- }
- else {
- /* PyObject_NewVar is inlined */
- *cst = (PyCStackObject *)
- PyObject_MALLOC(sizeof(PyCStackObject) +
- (size-1) * sizeof(int*));
- if (*cst == NULL) return NULL;
- }
- (void) PyObject_INIT_VAR(*cst, &PyCStack_Type, size);
-
- (*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;
- (*cst)->tstate = ts;
- (*cst)->nesting_level = ts->st.nesting_level;
- return *cst;
- }
-
- int
- slp_cstack_save(PyCStackObject *cstprev)
- {
- int stsizeb = (cstprev)->ob_size * sizeof(int*);
-
- memcpy((cstprev)->stack, (cstprev)->startaddr -
- (cstprev)->ob_size, stsizeb);
- return stsizeb;
- }
-
- void
- 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;
- memcpy(cst->startaddr - cst->ob_size, &cst->stack,
- (cst->ob_size) * sizeof(int*));
- }
-
- static int
- make_initial_stub(void)
- {
- PyThreadState *ts = PyThreadState_GET();
-
- if (ts->st.initial_stub != NULL) {
- Py_DECREF(ts->st.initial_stub);
- 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;
- /*
- * from here, we always arrive with a compatible cstack
- * that also can be used by main, if it is running
- * in soft-switching mode.
- * 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.
- */
-
- return 0;
- }
-
- static PyObject *
- climb_stack_and_eval_frame(PyFrameObject *f)
- {
- /*
- * a similar case to climb_stack_and_transfer,
- * but here we need to incorporate a gap in the
- * stack into main and keep this gap on the stack.
- * This way, initial_stub is always valid to be
- * used to return to the main c stack.
- */
- PyThreadState *ts = PyThreadState_GET();
- int probe;
- int needed = &probe - ts->st.cstack_base;
- /* in rare cases, the need might have vanished due to the recursion */
- int * goobledigoobs;
-
- if (needed > 0) {
- goobledigoobs = alloca(needed * sizeof(int));
- if (goobledigoobs == NULL)
- return NULL;
- }
- return slp_eval_frame(f);
- }
-
- PyObject *
- slp_eval_frame(PyFrameObject *f)
- {
- PyThreadState *ts = PyThreadState_GET();
- PyFrameObject *fprev = f->f_back;
- int * stackref;
-
- if (fprev == NULL && ts->st.main == NULL) {
- /* this is the initial frame, so mark the stack base */
-
- /*
- * careful, this caused me a major headache.
- * it is *not* sufficient to just check for fprev == NULL.
- * 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);
- return slp_frame_dispatch(f, fprev, Py_None);
- }
-
static int
climb_stack_and_transfer(PyCStackObject **cstprev, PyCStackObject *cst,
--- 46,49 ----
Index: stackless_impl.h
===================================================================
RCS file: /home/cvs/slpdev/src/2.3/dev/Stackless/core/stackless_impl.h,v
retrieving revision 1.94
retrieving revision 1.95
diff -C2 -d -r1.94 -r1.95
*** stackless_impl.h 3 Jun 2004 17:34:21 -0000 1.94
--- stackless_impl.h 3 Jun 2004 18:02:11 -0000 1.95
***************
*** 43,47 ****
PyAPI_FUNC(int) slp_cstack_save(PyCStackObject *cstprev);
PyAPI_FUNC(void) slp_cstack_restore(PyCStackObject *cst);
- PyAPI_FUNC(void) slp_cstack_cacheclear(void);
PyAPI_FUNC(int) slp_transfer(PyCStackObject **cstprev, PyCStackObject *cst,
--- 43,46 ----
Index: stacklesseval.c
===================================================================
RCS file: /home/cvs/slpdev/src/2.3/dev/Stackless/core/stacklesseval.c,v
retrieving revision 1.155
retrieving revision 1.156
diff -C2 -d -r1.155 -r1.156
*** stacklesseval.c 3 Jun 2004 17:34:21 -0000 1.155
--- stacklesseval.c 3 Jun 2004 18:02:12 -0000 1.156
***************
*** 37,40 ****
--- 37,337 ----
+ /******************************************************
+
+ The C Stack
+
+ ******************************************************/
+
+ static PyCStackObject *cstack_cache[CSTACK_SLOTS] = { NULL };
+ static int cstack_cachecount = 0;
+
+ /* this function will get called by PyStacklessEval_Fini */
+ static void slp_cstack_cacheclear(void)
+ {
+ int i;
+ PyCStackObject *stack;
+
+ for (i=0; i < CSTACK_SLOTS; i++) {
+ while (cstack_cache[i] != NULL) {
+ stack = cstack_cache[i];
+ cstack_cache[i] = (PyCStackObject *) stack->startaddr;
+ PyMem_Free(stack);
+ }
+ }
+ cstack_cachecount = 0;
+ }
+
+ static void
+ cstack_dealloc(PyCStackObject *cst)
+ {
+ slp_cstack_chain = cst;
+ SLP_CHAIN_REMOVE(PyCStackObject, &slp_cstack_chain, cst, next,
+ prev);
+ if (cst->ob_size >= CSTACK_SLOTS) {
+ PyMem_Free(cst);
+ }
+ else {
+ if (cstack_cachecount >= CSTACK_MAXCACHE)
+ slp_cstack_cacheclear();
+ cst->startaddr = (int *) cstack_cache[cst->ob_size];
+ cstack_cache[cst->ob_size] = cst;
+ ++cstack_cachecount;
+ }
+ }
+
+
+ PyCStackObject *
+ slp_cstack_new(PyCStackObject **cst, int *stackref, PyTaskletObject *task)
+ {
+ PyThreadState *ts = PyThreadState_GET();
+ int *stackbase = ts->st.cstack_base;
+ 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 */
+ (*cst)->task = task;
+ return *cst;
+ }
+
+ if (*cst != NULL) {
+ if ((*cst)->task == task)
+ (*cst)->task = NULL;
+ Py_DECREF(*cst);
+ }
+ if (size < CSTACK_SLOTS && ((*cst) = cstack_cache[size])) {
+ /* take stack from cache */
+ cstack_cache[size] = (PyCStackObject *) (*cst)->startaddr;
+ --cstack_cachecount;
+ }
+ else {
+ /* PyObject_NewVar is inlined */
+ *cst = (PyCStackObject *)
+ PyObject_MALLOC(sizeof(PyCStackObject) +
+ (size-1) * sizeof(int*));
+ if (*cst == NULL) return NULL;
+ }
+ (void) PyObject_INIT_VAR(*cst, &PyCStack_Type, size);
+
+ (*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;
+ (*cst)->tstate = ts;
+ (*cst)->nesting_level = ts->st.nesting_level;
+ return *cst;
+ }
+
+ int
+ slp_cstack_save(PyCStackObject *cstprev)
+ {
+ int stsizeb = (cstprev)->ob_size * sizeof(int*);
+
+ memcpy((cstprev)->stack, (cstprev)->startaddr -
+ (cstprev)->ob_size, stsizeb);
+ return stsizeb;
+ }
+
+ void
+ 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;
+ memcpy(cst->startaddr - cst->ob_size, &cst->stack,
+ (cst->ob_size) * sizeof(int*));
+ }
+
+
+ static char cstack_doc[] =
+ "A CStack object serves to save the stack slice which is involved\n\
+ during a recursive Python call. It will also be used for pickling\n\
+ of program state. This structure is highly platform dependant.\n\
+ Note: For inspection, str() can dump it as a string.\
+ ";
+
+ #if SIZEOF_VOIDP == SIZEOF_INT
+ #define T_ADDR T_UINT
+ #else
+ #define T_ADDR T_ULONG
+ #endif
+
+
+ static PyMemberDef cstack_members[] = {
+ {"size", T_INT, offsetof(PyCStackObject, ob_size), READONLY},
+ {"next", T_OBJECT, offsetof(PyCStackObject, next), READONLY},
+ {"prev", T_OBJECT, offsetof(PyCStackObject, prev), READONLY},
+ {"task", T_OBJECT, offsetof(PyCStackObject, task), READONLY},
+ {"startaddr", T_ADDR, offsetof(PyCStackObject, startaddr), READONLY},
+ {0}
+ };
+
+ /* simple string interface for inspection */
+
+ static PyObject *
+ cstack_str(PyObject *o)
+ {
+ PyCStackObject *cst = (PyCStackObject*)o;
+ return PyString_FromStringAndSize((char*)&cst->stack,
+ cst->ob_size*sizeof(cst->stack[0]));
+ }
+
+ PyTypeObject PyCStack_Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "stackless.cstack",
+ sizeof(PyCStackObject),
+ sizeof(PyObject *),
+ (destructor)cstack_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 */
+ (reprfunc)cstack_str, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ PyObject_GenericSetAttr, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ cstack_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ cstack_members, /* tp_members */
+ };
+
+
+ static int
+ make_initial_stub(void)
+ {
+ PyThreadState *ts = PyThreadState_GET();
+
+ if (ts->st.initial_stub != NULL) {
+ Py_DECREF(ts->st.initial_stub);
+ 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;
+ /*
+ * from here, we always arrive with a compatible cstack
+ * that also can be used by main, if it is running
+ * in soft-switching mode.
+ * 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.
+ */
+
+ return 0;
+ }
+
+ static PyObject *
+ climb_stack_and_eval_frame(PyFrameObject *f)
+ {
+ /*
+ * a similar case to climb_stack_and_transfer,
+ * but here we need to incorporate a gap in the
+ * stack into main and keep this gap on the stack.
+ * This way, initial_stub is always valid to be
+ * used to return to the main c stack.
+ */
+ PyThreadState *ts = PyThreadState_GET();
+ int probe;
+ int needed = &probe - ts->st.cstack_base;
+ /* in rare cases, the need might have vanished due to the recursion */
+ int * goobledigoobs;
+
+ if (needed > 0) {
+ goobledigoobs = alloca(needed * sizeof(int));
+ if (goobledigoobs == NULL)
+ return NULL;
+ }
+ return slp_eval_frame(f);
+ }
+
+
+ PyObject *
+ slp_eval_frame(PyFrameObject *f)
+ {
+ PyThreadState *ts = PyThreadState_GET();
+ PyFrameObject *fprev = f->f_back;
+ int * stackref;
+
+ if (fprev == NULL && ts->st.main == NULL) {
+ /* this is the initial frame, so mark the stack base */
+
+ /*
+ * careful, this caused me a major headache.
+ * it is *not* sufficient to just check for fprev == NULL.
+ * 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);
+ return slp_frame_dispatch(f, fprev, Py_None);
+ }
+
+ 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)
{
_______________________________________________
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