[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