[Stackless] Ported stackless to AMD64
Hye-Shik Chang
perky at i18n.org
Fri Apr 2 13:00:23 CEST 2004
Hi there.
I ported the stackless context switcher to amd64 and it seems to
work:
% ./python -S
Python 2.3.3 Stackless 3.0 040224 (#1, Apr 2 2004, 10:46:12)
[GCC 3.3.3 [FreeBSD] 20031106] on freebsd5
>>> import os;os.uname()
('FreeBSD', 'sledge.freebsd.org', '5.2-CURRENT', 'FreeBSD 5.2-CURRENT #206: Thu Apr 1 10:00:41 PST 2004 kensmith at sledge.freebsd.org:/h/src/sys/amd64/compile/SLEDGE', 'amd64')
% ./python Stackless/test/tasktest.py|tail -2
back
main done.
% ./python Stackless/test/chantest.py|tail -2
dinky got: 42
dinky says bye
But, I didn't test it any other OSes other than FreeBSD.
The patch is attached. And you may notice that I changed too much
than other portings. Unfortunately amd64's register doesn't fit in
int type. So, I changed variable types that I found as address
keepers to SLP_REG_TYPE and defined it on both of Stackless/stackless.h
and Stackless/stackless_impl.h. But I think the duplicating isn't
so neat so please fix it to conform the Stackless style. :)
Thanks,
Hye-Shik
-------------- next part --------------
diff -ruN stackless/Include/pystate.h stackless.amd64/Include/pystate.h
--- stackless/Include/pystate.h Fri Apr 2 09:52:51 2004
+++ stackless.amd64/Include/pystate.h Fri Apr 2 09:36:02 2004
@@ -5,6 +5,7 @@
#ifndef Py_PYSTATE_H
#define Py_PYSTATE_H
#ifdef STACKLESS
+#include "stackless.h"
#include "stackless_tstate.h"
#endif
#ifdef __cplusplus
diff -ruN stackless/Stackless/cstackobject.h stackless.amd64/Stackless/cstackobject.h
--- stackless/Stackless/cstackobject.h Fri Apr 2 09:52:51 2004
+++ stackless.amd64/Stackless/cstackobject.h Fri Apr 2 09:42:58 2004
@@ -1,5 +1,5 @@
#define CSTACK_NEW_HEAD(func) \
- PyCStackObject * func (PyCStackObject **cst, int *stackref, PyTaskletObject *task)
+ PyCStackObject * func (PyCStackObject **cst, SLP_REG_TYPE *stackref, PyTaskletObject *task)
#define CSTACK_SAVE_HEAD(func) \
int func (PyCStackObject *cstprev)
diff -ruN stackless/Stackless/prickelpit.c stackless.amd64/Stackless/prickelpit.c
--- stackless/Stackless/prickelpit.c Fri Apr 2 09:52:51 2004
+++ stackless.amd64/Stackless/prickelpit.c Fri Apr 2 09:48:02 2004
@@ -205,8 +205,8 @@
if (exec_name == NULL) {
char msg[500];
PyErr_Clear();
- sprintf(msg, "frame exec function at %08x is not registered!",
- (unsigned int)(void *)f->f_execute);
+ sprintf(msg, "frame exec function at %08lx is not registered!",
+ (unsigned SLP_REG_TYPE)(void *)f->f_execute);
PyErr_SetString(PyExc_ValueError, msg);
valid = 0;
}
diff -ruN stackless/Stackless/slp_platformselect.h stackless.amd64/Stackless/slp_platformselect.h
--- stackless/Stackless/slp_platformselect.h Fri Apr 2 09:52:51 2004
+++ stackless.amd64/Stackless/slp_platformselect.h Fri Apr 2 08:58:05 2004
@@ -6,6 +6,8 @@
#include "switch_x86_msvc.h" /* MS Visual Studio on X86 */
#elif defined(__GNUC__) && defined(__i386__)
#include "switch_x86_unix.h" /* gcc on X86 */
+#elif defined(__GNUC__) && defined(__amd64__)
+#include "switch_amd64_unix.h" /* gcc on amd64 */
#elif defined(__GNUC__) && defined(__PPC__) && defined(__linux__)
#include "switch_ppc_unix.h" /* gcc on PowerPC */
#elif defined(__GNUC__) && defined(__ppc__) && defined(__APPLE__)
diff -ruN stackless/Stackless/slp_transfer.c stackless.amd64/Stackless/slp_transfer.c
--- stackless/Stackless/slp_transfer.c Fri Apr 2 09:52:51 2004
+++ stackless.amd64/Stackless/slp_transfer.c Fri Apr 2 09:47:02 2004
@@ -27,16 +27,16 @@
static PyTaskletObject *_prev;
#define SLP_SAVE_STATE(stackref, stsizediff) \
- int stsizeb; \
- stackref += STACK_MAGIC; \
+ SLP_REG_TYPE stsizeb; \
+ stackref += STACK_MAGIC; \
if (_cstprev != NULL) { \
if (CSTACK_TYPE->new(_cstprev, stackref, _prev) == NULL) return -1; \
stsizeb = CSTACK_CAST(*_cstprev)->save(*_cstprev); \
} \
else \
- stsizeb = (_cst->startaddr - stackref) * sizeof(int*); \
+ stsizeb = (_cst->startaddr - stackref) * sizeof(SLP_REG_TYPE*); \
if (_cst == NULL) return 0; \
- stsizediff = stsizeb - (_cst->ob_size * sizeof(int*));
+ stsizediff = stsizeb - (_cst->ob_size * sizeof(SLP_REG_TYPE*));
#define SLP_RESTORE_STATE() \
if (_cst != NULL) { \
@@ -58,12 +58,12 @@
* needed stack size becomes *negative* :-))
*/
PyThreadState *ts = PyThreadState_GET();
- int probe;
- int needed = &probe - ts->st.cstack_base;
+ SLP_REG_TYPE probe;
+ SLP_REG_TYPE needed = &probe - ts->st.cstack_base;
/* in rare cases, the need might have vanished due to the recursion */
- int * goobledigoobs;
+ SLP_REG_TYPE * goobledigoobs;
if (needed > 0) {
- goobledigoobs = alloca(needed * sizeof(int));
+ goobledigoobs = alloca(needed * sizeof(SLP_REG_TYPE));
if (goobledigoobs == NULL)
return -1;
}
@@ -74,7 +74,7 @@
slp_transfer(PyCStackObject **cstprev, PyCStackObject *cst, PyTaskletObject *prev)
{
PyThreadState *ts = PyThreadState_GET();
- if ((int*) &ts > ts->st.cstack_base)
+ if ((SLP_REG_TYPE*) &ts > ts->st.cstack_base)
return climb_stack_and_transfer(cstprev, cst, prev);
if (cst == NULL)
cst = ts->st.initial_stub;
diff -ruN stackless/Stackless/stackless.h stackless.amd64/Stackless/stackless.h
--- stackless/Stackless/stackless.h Fri Apr 2 09:52:51 2004
+++ stackless.amd64/Stackless/stackless.h Fri Apr 2 09:37:29 2004
@@ -39,6 +39,8 @@
/* MS Visual Studio on X86 */
#elif defined(__GNUC__) && defined(__i386__)
/* gcc on X86 */
+#elif defined(__GNUC__) && defined(__amd64__)
+ /* gcc on AMD64 */
#elif defined(__GNUC__) && defined(__PPC__) && defined(__linux__)
/* gcc on PowerPC */
#elif defined(__GNUC__) && defined(__ppc__) && defined(__APPLE__)
@@ -52,6 +54,14 @@
#else
/* no supported platform */
#undef STACKLESS
+#endif
+
+#ifndef SLP_REG_TYPE
+#ifdef __amd64__
+#define SLP_REG_TYPE long
+#else
+#define SLP_REG_TYPE int
+#endif
#endif
#ifdef __cplusplus
diff -ruN stackless/Stackless/stackless_impl.h stackless.amd64/Stackless/stackless_impl.h
--- stackless/Stackless/stackless_impl.h Fri Apr 2 09:52:51 2004
+++ stackless.amd64/Stackless/stackless_impl.h Fri Apr 2 09:37:42 2004
@@ -25,6 +25,13 @@
#define PyAPI_FUNC(thing) extern DL_IMPORT(thing)
#endif
+#ifndef SLP_REG_TYPE
+#ifdef __amd64__
+#define SLP_REG_TYPE long
+#else
+#define SLP_REG_TYPE int
+#endif
+#endif
#include "structmember.h"
#include "compile.h"
diff -ruN stackless/Stackless/stackless_structs.h stackless.amd64/Stackless/stackless_structs.h
--- stackless/Stackless/stackless_structs.h Fri Apr 2 09:52:51 2004
+++ stackless.amd64/Stackless/stackless_structs.h Fri Apr 2 09:39:51 2004
@@ -103,7 +103,7 @@
struct _tasklet *task;
int nesting_level;
PyThreadState *tstate;
- int *startaddr;
+ SLP_REG_TYPE *startaddr;
int *stack[1];
} PyCStackObject;
diff -ruN stackless/Stackless/stackless_tstate.h stackless.amd64/Stackless/stackless_tstate.h
--- stackless/Stackless/stackless_tstate.h Fri Apr 2 09:52:51 2004
+++ stackless.amd64/Stackless/stackless_tstate.h Fri Apr 2 09:38:12 2004
@@ -21,7 +21,7 @@
/* the list of all stacks of this thread */
struct _cstack *cstack_chain;
/* the base address for hijacking stacks */
- int *cstack_base;
+ SLP_REG_TYPE *cstack_base;
/* flags of the running tasklet */
struct _tasklet_flags flags;
/* main tasklet */
diff -ruN stackless/Stackless/stacklesseval.c stackless.amd64/Stackless/stacklesseval.c
--- stackless/Stackless/stacklesseval.c Fri Apr 2 09:52:51 2004
+++ stackless.amd64/Stackless/stacklesseval.c Fri Apr 2 09:45:09 2004
@@ -67,7 +67,7 @@
else {
if (cstack_cachecount >= CSTACK_MAXCACHE)
slp_cstack_cacheclear();
- cst->startaddr = (int *) cstack_cache[cst->ob_size];
+ cst->startaddr = (SLP_REG_TYPE *) cstack_cache[cst->ob_size];
cstack_cache[cst->ob_size] = cst;
++cstack_cachecount;
}
@@ -75,11 +75,11 @@
static PyCStackObject *
-cstack_new(PyCStackObject **cst, int *stackref, PyTaskletObject *task)
+cstack_new(PyCStackObject **cst, SLP_REG_TYPE *stackref, PyTaskletObject *task)
{
PyThreadState *ts = PyThreadState_GET();
- int *stackbase = ts->st.cstack_base;
- int size = stackbase - stackref;
+ SLP_REG_TYPE *stackbase = ts->st.cstack_base;
+ SLP_REG_TYPE size = stackbase - stackref;
if (size < 0) {
PyErr_SetString(PyExc_RuntimeError, "negative stack size");
return NULL;
@@ -102,7 +102,7 @@
else {
/* PyObject_NewVar is inlined */
*cst = (PyCStackObject *)
- PyObject_MALLOC(sizeof(PyCStackObject) + (size-1) * sizeof(int*));
+ PyObject_MALLOC(sizeof(PyCStackObject) + (size-1) * sizeof(SLP_REG_TYPE*));
if (*cst == NULL) return NULL;
}
(void) PyObject_INIT_VAR(*cst, &PyCStack_Type, size);
@@ -253,12 +253,12 @@
* used to return to the main c stack.
*/
PyThreadState *ts = PyThreadState_GET();
- int probe;
- int needed = &probe - ts->st.cstack_base;
+ SLP_REG_TYPE probe;
+ SLP_REG_TYPE needed = &probe - ts->st.cstack_base;
/* in rare cases, the need might have vanished due to the recursion */
- int * goobledigoobs;
+ SLP_REG_TYPE * goobledigoobs;
if (needed > 0) {
- goobledigoobs = alloca(needed * sizeof(int));
+ goobledigoobs = alloca(needed * sizeof(SLP_REG_TYPE));
if (goobledigoobs == NULL)
return NULL;
}
@@ -271,7 +271,7 @@
{
PyThreadState *ts = PyThreadState_GET();
PyFrameObject *fprev = f->f_back;
- int * stackref;
+ SLP_REG_TYPE * stackref;
PyObject *result;
if (fprev == NULL && ts->st.main == NULL) {
@@ -287,7 +287,7 @@
will run as a toplevel frame, with fback == NULL!
*/
- stackref = STACK_REFPLUS + (int*) &f;
+ stackref = STACK_REFPLUS + (SLP_REG_TYPE*) &f;
if (ts->st.cstack_base == NULL)
ts->st.cstack_base = stackref-CSTACK_GOODGAP; /* XXX */
if (stackref > ts->st.cstack_base)
diff -ruN stackless/Stackless/switch_amd64_unix.h stackless.amd64/Stackless/switch_amd64_unix.h
--- stackless/Stackless/switch_amd64_unix.h Thu Jan 1 00:00:00 1970
+++ stackless.amd64/Stackless/switch_amd64_unix.h Fri Apr 2 10:35:24 2004
@@ -0,0 +1,66 @@
+/*
+ * this is the internal transfer function.
+ *
+ * HISTORY
+ * 01-Apr-04 Hye-Shik Chang <perky at FreeBSD.org>
+ * Ported from i386 to amd64.
+ * 24-Nov-02 Christian Tismer <tismer at tismer.com>
+ * needed to add another magic constant to insure
+ * that f in slp_eval_frame(PyFrameObject *f)
+ * STACK_REFPLUS will probably be 1 in most cases.
+ * gets included into the saved stack area.
+ * 17-Sep-02 Christian Tismer <tismer at tismer.com>
+ * after virtualizing stack save/restore, the
+ * stack size shrunk a bit. Needed to introduce
+ * an adjustment STACK_MAGIC per platform.
+ * 15-Sep-02 Gerd Woetzel <gerd.woetzel at GMD.DE>
+ * slightly changed framework for spark
+ * 31-Avr-02 Armin Rigo <arigo at ulb.ac.be>
+ * Added ebx, esi and edi register-saves.
+ * 01-Mar-02 Samual M. Rushing <rushing at ironport.com>
+ * Ported from i386.
+ */
+
+#define STACK_REFPLUS 1
+
+#ifdef SLP_EVAL
+
+/* #define STACK_MAGIC 3 */
+/* the above works fine with gcc 2.96, but 2.95.3 wants this */
+#define STACK_MAGIC 0
+
+#define REGS_TO_SAVE "rdx", "rbx", "r12", "r13", "r14", "r15"
+
+
+static int
+slp_switch(void)
+{
+ register long *stackref, stsizediff;
+ __asm__ volatile ("" : : : REGS_TO_SAVE);
+ __asm__ ("movq %%rsp, %0" : "=g" (stackref));
+ {
+ SLP_SAVE_STATE(stackref, stsizediff);
+ __asm__ volatile (
+ "addq %0, %%rsp\n"
+ "addq %0, %%rbp\n"
+ :
+ : "r" (stsizediff)
+ );
+ SLP_RESTORE_STATE();
+ return 0;
+ }
+ __asm__ volatile ("" : : : REGS_TO_SAVE);
+}
+
+#endif
+
+/*
+ * further self-processing support
+ */
+
+/*
+ * if you want to add self-inspection tools, place them
+ * here. See the x86_msvc for the necessary defines.
+ * These features are highly experimental und not
+ * essential yet.
+ */
-------------- next part --------------
_______________________________________________
Stackless mailing list
Stackless at stackless.com
http://www.stackless.com/mailman/listinfo/stackless
More information about the Stackless
mailing list