Skip to content
This repository was archived by the owner on Feb 13, 2025. It is now read-only.

Commit 54ba7b1

Browse files
kristjanvalurAnselm Kruis
and
Anselm Kruis
authored
Stackless issue #278: implement switching using the Stackman submodule
Stackless now uses Stackman https://github.com/stackless-dev/stackman for stack switching / hard tasklet switching. The legacy stack switching code is still available. See 'readme.txt' for details. The Stackman code is in a git submodule located below Stackless/stackman. You can control the usage of Stackman with the configure options "--with-stackman" and "--without-stackman". On Windows you can use the MSBuild property "stackmanDir". (To set a property add '"/p:name=value"' to the build.bat command line.) Co-authored-by: Anselm Kruis <[email protected]>
1 parent 9b442f6 commit 54ba7b1

12 files changed

+265
-57
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "Stackless/platf/stackman"]
2+
path = Stackless/stackman
3+
url = https://github.com/stackless-dev/stackman.git

Makefile.pre.in

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ CFLAGS_ALIASING=@CFLAGS_ALIASING@
119119

120120
# Special C flags for slp_transfer.c
121121
SLPFLAGS= @SLPFLAGS@
122+
SLP_STACKMAN_LIB= @SLP_STACKMAN_LIB@
123+
SLP_STACKMAN_OBJS= @SLP_STACKMAN_OBJS@
122124

123125
# Machine-dependent subdirectories
124126
MACHDEP= @MACHDEP@
@@ -329,6 +331,7 @@ PYTHON_OBJS= \
329331
Stackless/module/taskletobject.o \
330332
Stackless/pickling/prickelpit.o \
331333
Stackless/pickling/safe_pickle.o \
334+
$(SLP_STACKMAN_OBJS) \
332335
Python/codecs.o \
333336
Python/compile.o \
334337
Python/coreconfig.o \
@@ -707,6 +710,17 @@ $(srcdir)/Include/cpython/slp_exttype.h: $(srcdir)/Objects/typeobject.c
707710
$(PYTHON_FOR_REGEN) $(srcdir)/Stackless/Tools/extract_slp_info.py && \
708711
mv $(srcdir)/Include/cpython/slp_exttype.h.new $(srcdir)/Include/cpython/slp_exttype.h
709712

713+
$(SLP_STACKMAN_OBJS): $(SLP_STACKMAN_LIB)
714+
cp $(SLP_STACKMAN_LIB) Stackless/platf/libstackman.a
715+
cd Stackless/platf && $(AR) x libstackman.a && rm libstackman.a
716+
717+
Stackless/platf/slp_transfer.o: $(srcdir)/Stackless/platf/slp_transfer.c
718+
$(CC) -c $(PY_CORE_CFLAGS) $(SLPFLAGS) -o $@ $(srcdir)/Stackless/platf/slp_transfer.c
719+
720+
.PHONY: teststackless
721+
teststackless: @DEF_MAKE_RULE@ platform
722+
$(TESTPYTHON) -E $(srcdir)/Stackless/unittests/runAll.py
723+
710724
############################################################################
711725
# Importlib
712726

@@ -960,9 +974,6 @@ regen-typeslots:
960974
$(srcdir)/Objects/typeslots.inc.new
961975
$(UPDATE_FILE) $(srcdir)/Objects/typeslots.inc $(srcdir)/Objects/typeslots.inc.new
962976

963-
Stackless/platf/slp_transfer.o: $(srcdir)/Stackless/platf/slp_transfer.c
964-
$(CC) -c $(PY_CORE_CFLAGS) $(SLPFLAGS) -o $@ $(srcdir)/Stackless/platf/slp_transfer.c
965-
966977
############################################################################
967978
# Header files
968979

@@ -1121,7 +1132,7 @@ TESTPYTHON= $(RUNSHARED) ./$(BUILDPYTHON) $(TESTPYTHONOPTS)
11211132
TESTRUNNER= $(TESTPYTHON) $(srcdir)/Tools/scripts/run_tests.py
11221133
TESTTIMEOUT= 1200
11231134

1124-
.PHONY: test testall testuniversal buildbottest pythoninfo teststackless
1135+
.PHONY: test testall testuniversal buildbottest pythoninfo
11251136

11261137
# Run a basic set of regression tests.
11271138
# This excludes some tests that are particularly resource-intensive.
@@ -1142,9 +1153,6 @@ testall: @DEF_MAKE_RULE@ platform
11421153
-$(TESTRUNNER) -u all $(TESTOPTS)
11431154
$(TESTRUNNER) -u all $(TESTOPTS)
11441155

1145-
teststackless: @DEF_MAKE_RULE@ platform
1146-
$(TESTPYTHON) -E $(srcdir)/Stackless/unittests/runAll.py
1147-
11481156
# Run the test suite for both architectures in a Universal build on OSX.
11491157
# Must be run on an Intel box.
11501158
testuniversal: @DEF_MAKE_RULE@ platform
@@ -1762,7 +1770,7 @@ docclean:
17621770
-rm -rf Doc/tools/sphinx Doc/tools/pygments Doc/tools/docutils
17631771

17641772
clean: pycremoval
1765-
find . -name '*.[oa]' -exec rm -f {} ';'
1773+
find . -path '*Stackless/stackman/*.a' -prune -o -name '*.[oa]' -exec rm -f {} ';'
17661774
find . -name '*.s[ol]' -exec rm -f {} ';'
17671775
find . -name '*.so.[0-9]*.[0-9]*' -exec rm -f {} ';'
17681776
find build -name 'fficonfig.h' -exec rm -f {} ';' || true

PCbuild/python.props

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@
7171

7272
<!-- Full path of the resulting python.exe binary -->
7373
<PythonExe Condition="'$(PythonExe)' == ''">$(BuildPath)python$(PyDebugExt).exe</PythonExe>
74+
75+
<!-- Stackless stackman directory. Set this property to 'no', to build without Stackman -->
76+
<stackmanDir Condition="'$(stackmanDir)' == ''">$(PySourcePath)Stackless\stackman\</stackmanDir>
77+
<stackmanDir Condition="'$(stackmanDir)' != 'no' And !HasTrailingSlash($(stackmanDir))">$(stackmanDir)\</stackmanDir>
78+
<stackmanLib Condition="'$(stackmanDir)' != 'no'">stackman.lib;</stackmanLib>
7479
</PropertyGroup>
7580

7681
<PropertyGroup Condition="'$(Platform)'=='ARM'" Label="ArmConfiguration">

PCbuild/pythoncore.vcxproj

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,15 @@
8888
<AdditionalIncludeDirectories Condition="$(IncludeExternals)">$(zlibDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
8989
<PreprocessorDefinitions>_USRDLL;Py_BUILD_CORE;Py_ENABLE_SHARED;MS_DLL_ID="$(SysWinVer)";%(PreprocessorDefinitions)</PreprocessorDefinitions>
9090
<PreprocessorDefinitions Condition="$(IncludeExternals)">_Py_HAVE_ZLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
91+
<PreprocessorDefinitions Condition="'$(stackmanDir)' == 'no'">SLP_NO_STACKMAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
9192
</ClCompile>
9293
<Link>
93-
<AdditionalDependencies>version.lib;shlwapi.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
94+
<AdditionalDependencies>version.lib;shlwapi.lib;ws2_32.lib;$(stackmanLib)%(AdditionalDependencies)</AdditionalDependencies>
95+
<AdditionalLibraryDirectories Condition="'$(stackmanLib)'!='' And '$(Platform)'=='x64'">$(stackmanDir)lib\win_x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
96+
<AdditionalLibraryDirectories Condition="'$(stackmanLib)'!='' And '$(Platform)'=='Win32'">$(stackmanDir)lib\win_x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
97+
<AdditionalLibraryDirectories Condition="'$(stackmanLib)'!='' And '$(Platform)'=='ARM'">$(stackmanDir)lib\win_arm;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
98+
<AdditionalLibraryDirectories Condition="'$(stackmanLib)'!='' And '$(Platform)'=='ARM64'">$(stackmanDir)lib\win_arm64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
99+
<ImageHasSafeExceptionHandlers Condition="'$(stackmanLib)'!='' And '$(Platform)'=='Win32'">false</ImageHasSafeExceptionHandlers>
94100
</Link>
95101
</ItemDefinitionGroup>
96102
<ItemGroup>
@@ -452,7 +458,9 @@
452458
<ClCompile Include="..\Python\thread.c" />
453459
<ClCompile Include="..\Python\traceback.c" />
454460
<ClCompile Include="..\Stackless\core\cframeobject.c" />
455-
<ClCompile Include="..\Stackless\platf\slp_transfer.c" />
461+
<ClCompile Include="..\Stackless\platf\slp_transfer.c">
462+
<AdditionalIncludeDirectories Condition="'$(stackmanDir)'!='no'">$(stackmanDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
463+
</ClCompile>
456464
<ClCompile Include="..\Stackless\core\stacklesseval.c" />
457465
<ClCompile Include="..\Stackless\core\stackless_util.c" />
458466
<ClCompile Include="..\Stackless\module\channelobject.c" />
@@ -484,23 +492,12 @@
484492
</ItemGroup>
485493
<ItemGroup>
486494
<CustomBuild Include="..\Stackless\platf\switch_x64_masm.asm">
487-
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
488-
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='PGInstrument|Win32'">true</ExcludedFromBuild>
489-
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='PGUpdate|Win32'">true</ExcludedFromBuild>
490-
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
495+
<ExcludedFromBuild Condition="'$(Platform)'!='x64'">true</ExcludedFromBuild>
496+
<ExcludedFromBuild Condition="'$(Platform)'=='x64' And '$(stackmanDir)'!='no'">true</ExcludedFromBuild>
491497
<FileType>Document</FileType>
492-
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">ml64 /nologo /c /Zi /Fo "$(IntDir)%(Filename) .obj" "%(FullPath)"</Command>
493-
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Running ml64</Message>
494-
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)%(Filename) .obj;%(Outputs)</Outputs>
495-
<Command Condition="'$(Configuration)|$(Platform)'=='PGInstrument|x64'">ml64 /nologo /c /Zi /Fo "$(IntDir)%(Filename) .obj" "%(FullPath)"</Command>
496-
<Message Condition="'$(Configuration)|$(Platform)'=='PGInstrument|x64'">Running ml64</Message>
497-
<Outputs Condition="'$(Configuration)|$(Platform)'=='PGInstrument|x64'">$(IntDir)%(Filename) .obj;%(Outputs)</Outputs>
498-
<Command Condition="'$(Configuration)|$(Platform)'=='PGUpdate|x64'">ml64 /nologo /c /Zi /Fo "$(IntDir)%(Filename) .obj" "%(FullPath)"</Command>
499-
<Message Condition="'$(Configuration)|$(Platform)'=='PGUpdate|x64'">Running ml64</Message>
500-
<Outputs Condition="'$(Configuration)|$(Platform)'=='PGUpdate|x64'">$(IntDir)%(Filename) .obj;%(Outputs)</Outputs>
501-
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">ml64 /nologo /c /Zi /Fo "$(IntDir)%(Filename) .obj" "%(FullPath)"</Command>
502-
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Running ml64</Message>
503-
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)%(Filename) .obj;%(Outputs)</Outputs>
498+
<Command Condition="'$(Platform)'=='x64'">ml64 /nologo /c /Zi /Fo "$(IntDir)%(Filename) .obj" "%(FullPath)"</Command>
499+
<Message Condition="'$(Platform)'=='x64'">Running ml64</Message>
500+
<Outputs Condition="'$(Platform)'=='x64'">$(IntDir)%(Filename) .obj;%(Outputs)</Outputs>
504501
</CustomBuild>
505502
<None Include="..\Stackless\readme.txt" />
506503
</ItemGroup>

Stackless/Tools/create_source_archive.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ if [ $# != 3 ] ; then
1414
exit 1
1515
fi
1616

17-
: ${excludes:=.gitignore .git* .hg* .bzrignore .mention-bot .travis.yml .readthedocs.yml .azure-pipelines}
17+
: ${excludes:=.gitignore .git* .mention-bot .travis.yml .readthedocs.yml .azure-pipelines Stackless/stackman/.git* }
1818

1919
git_python_dir="$1" ; shift
2020
if [ "x$1" = "x-v" ] ; then
@@ -42,6 +42,7 @@ mkdir "$tmpdir"
4242
cd "$git_python_dir"
4343
git archive --format=tar --prefix="${srcdir}/" "$tag" | \
4444
( cd "${tmpdir}" && tar xf - )
45+
git submodule foreach --recursive "git archive --format=tar --prefix=${srcdir}/\$path/ HEAD | ( cd \"${tmpdir}\" && tar xf - )"
4546
cd "${tmpdir}"
4647
( cd "${srcdir}" && set +f && rm -rf $excludes )
4748

Stackless/changelog.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ What's New in Stackless 3.X.X?
99

1010
*Release date: 20XX-XX-XX*
1111

12+
- https://github.com/stackless-dev/stackless/issues/278
13+
Stackless now uses Stackman https://github.com/stackless-dev/stackman for
14+
stack switching / hard tasklet switching. The legacy stack switching code
15+
is still available. See 'readme.txt' for details.
16+
1217
- https://github.com/stackless-dev/stackless/issues/254
1318
The Stackless version is now "3.8".
1419

Stackless/platf/slp_transfer.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@
3939
*/
4040
#define SLP_EVAL /* enable code generation in the included header */
4141

42+
#ifndef SLP_NO_STACKMAN /* defined by configure --without-stackman */
43+
/* First, see if stackman an implementation without external
44+
* assembler, use that if possible
45+
*/
46+
#define STACKMAN_OPTIONAL
47+
#include "stackman/stackman.h"
48+
#endif /* #ifndef SLP_NO_STACKMAN */
49+
#if defined(STACKMAN_PLATFORM) && !defined(STACKMAN_EXTERNAL_ASM)
50+
#include "switch_stackman.h"
51+
#else /* use traditional stackless switching */
4252
#if defined(MS_WIN32) && !defined(MS_WIN64) && defined(_M_IX86)
4353
#include "switch_x86_msvc.h" /* MS Visual Studio on X86 */
4454
#elif defined(MS_WIN64) && defined(_M_X64)
@@ -74,6 +84,7 @@ Please provide an implementation of the switch_XXX.h
7484
or disable the STACKLESS flag.
7585
**********
7686
#endif
87+
#endif /* use traditional stackless switching */
7788

7889
/* default definitions if not defined in above files */
7990

Stackless/platf/switch_stackman.h

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* this is the internal transfer function, using
3+
* the stackman platform library.
4+
* We create a wrapper callback that employs the existing
5+
* stack macros.
6+
* At some later point in time, the callback could be
7+
* written directly.
8+
*
9+
*/
10+
11+
#define SLP_STACK_REFPLUS 1
12+
13+
#ifdef SLP_EVAL
14+
#define SLP_STACK_MAGIC 0
15+
16+
17+
/* need a special function arount SLP_SAVE_STATE() because
18+
* the macro has a built-in return of 0 or -1. Must catch
19+
* that.
20+
*/
21+
static int slp_stackman_cb_save(void *sp, intptr_t *pdiff)
22+
{
23+
intptr_t diff;
24+
/* first argument must be a pointer to a "stack word", not a void* */
25+
SLP_SAVE_STATE(((intptr_t *)sp), diff);
26+
*pdiff = diff;
27+
return 1;
28+
}
29+
30+
static void *slp_stackman_cb(void *_ctxt, int opcode, void *sp)
31+
{
32+
int *error = (int*)_ctxt;
33+
intptr_t stsizediff;
34+
if (opcode == STACKMAN_OP_SAVE)
35+
{
36+
int ret = slp_stackman_cb_save(sp, &stsizediff);
37+
if (ret == 1) {
38+
/* regular switch */
39+
return (void*)((char*)sp + stsizediff);
40+
}
41+
if (ret == -1)
42+
{
43+
*error = -1;
44+
}
45+
/* error or save only, no change in sp */
46+
return sp;
47+
}
48+
else
49+
{
50+
if (*error != -1)
51+
SLP_RESTORE_STATE();
52+
return sp;
53+
}
54+
}
55+
56+
static int
57+
slp_switch(void)
58+
{
59+
/* this can be on the stack, because if there isn't a switch
60+
* then it is intact. (error or save only) */
61+
int error = 0;
62+
stackman_switch(&slp_stackman_cb, &error);
63+
return error;
64+
}
65+
66+
#include "stackman/stackman_impl.h"
67+
#endif

Stackless/readme.txt

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,26 @@ It is the ultimate truth. Read it at https://github.com/stackless-dev/stackless
2727
Building Stackless
2828
------------------
2929

30-
Just follow the build instructions for regular Python. If you define
31-
the C-preprocessor symbol STACKLESS_OFF, you get a Python interpreter
32-
without Stackless. It should behave exactly like the corresponding
33-
version of regular Python. Any difference constitutes a bug.
34-
(Windows 64bit only: if you define STACKLESS_OFF, you also need
35-
to clear the content of the file Stackless\platf\switch_x64_masm.asm:
36-
c:\> echo END > Stackless\platf\switch_x64_masm.asm )
30+
Just follow the build instructions for regular C-Python.
31+
32+
To more easily support new platforms and CPU architectures, Stackless Python
33+
now commonly uses Stackman (https://github.com/stackless-dev/stackman)
34+
for stack switching / hard switching between tasklets. Stackman is a
35+
lightweight library for stack manipulation. The Stackless source archive
36+
already contains a copy of Stackman, which is normally used automatically.
37+
However, the legacy Stackless switching code can still be used without
38+
restrictions. To do this, Stackless must be configured with
39+
`configure --without-stackman` or built under Windows with
40+
`build.bat "/p:stackmanDir=no"`.
41+
42+
It is also possible to use your own version of Stackman instead of the copy
43+
bundled with Stackless. To do this configure Stackless with
44+
`configure --with-stackman=/path/to/your/stackman` or built under Windows
45+
with `build.bat "/p:stackmanDir=X:\path\to\your\stackman"`.
46+
47+
If you define the C-preprocessor symbol STACKLESS_OFF in Include/stackless.h,
48+
you get a Python interpreter without Stackless. It should behave exactly like
49+
the corresponding version of regular Python. Any difference constitutes a bug.
3750

3851
Contributing
3952
------------

Stackless/stackman

Submodule stackman added at c572d4d

0 commit comments

Comments
 (0)