Browse Source

HUE-7860 [core] Integrate non IO blocking Python Webserver
Add greenlet 0.4.12

(cherry picked from commit 683aa84eb74aa6df920a1e3698c6b02835d0484a)

Ying Chen 8 years ago
parent
commit
76ad04632d
49 changed files with 5427 additions and 0 deletions
  1. 15 0
      desktop/core/ext-py/greenlet-0.4.12/.travis.yml
  2. 44 0
      desktop/core/ext-py/greenlet-0.4.12/AUTHORS
  3. 30 0
      desktop/core/ext-py/greenlet-0.4.12/LICENSE
  4. 47 0
      desktop/core/ext-py/greenlet-0.4.12/LICENSE.PSF
  5. 63 0
      desktop/core/ext-py/greenlet-0.4.12/MANIFEST.in
  6. 148 0
      desktop/core/ext-py/greenlet-0.4.12/NEWS
  7. 87 0
      desktop/core/ext-py/greenlet-0.4.12/PKG-INFO
  8. 57 0
      desktop/core/ext-py/greenlet-0.4.12/README.rst
  9. 81 0
      desktop/core/ext-py/greenlet-0.4.12/appveyor.yml
  10. 6 0
      desktop/core/ext-py/greenlet-0.4.12/appveyor/run_pip.py
  11. 88 0
      desktop/core/ext-py/greenlet-0.4.12/appveyor/run_with_env.cmd
  12. 39 0
      desktop/core/ext-py/greenlet-0.4.12/benchmarks/chain.py
  13. 18 0
      desktop/core/ext-py/greenlet-0.4.12/conftest.py
  14. 2 0
      desktop/core/ext-py/greenlet-0.4.12/dev-requirements.txt
  15. 153 0
      desktop/core/ext-py/greenlet-0.4.12/doc/Makefile
  16. 242 0
      desktop/core/ext-py/greenlet-0.4.12/doc/conf.py
  17. 426 0
      desktop/core/ext-py/greenlet-0.4.12/doc/greenlet.txt
  18. 1 0
      desktop/core/ext-py/greenlet-0.4.12/doc/index.txt
  19. 190 0
      desktop/core/ext-py/greenlet-0.4.12/doc/make.bat
  20. 1723 0
      desktop/core/ext-py/greenlet-0.4.12/greenlet.c
  21. 148 0
      desktop/core/ext-py/greenlet-0.4.12/greenlet.h
  22. 19 0
      desktop/core/ext-py/greenlet-0.4.12/make-manylinux
  23. 50 0
      desktop/core/ext-py/greenlet-0.4.12/make-win-release
  24. 60 0
      desktop/core/ext-py/greenlet-0.4.12/my_build_ext.py
  25. 69 0
      desktop/core/ext-py/greenlet-0.4.12/platform/switch_aarch64_gcc.h
  26. 84 0
      desktop/core/ext-py/greenlet-0.4.12/platform/switch_amd64_unix.h
  27. 79 0
      desktop/core/ext-py/greenlet-0.4.12/platform/switch_arm32_gcc.h
  28. 67 0
      desktop/core/ext-py/greenlet-0.4.12/platform/switch_arm32_ios.h
  29. 38 0
      desktop/core/ext-py/greenlet-0.4.12/platform/switch_m68k_gcc.h
  30. 64 0
      desktop/core/ext-py/greenlet-0.4.12/platform/switch_mips_unix.h
  31. 90 0
      desktop/core/ext-py/greenlet-0.4.12/platform/switch_ppc64_linux.h
  32. 87 0
      desktop/core/ext-py/greenlet-0.4.12/platform/switch_ppc_aix.h
  33. 84 0
      desktop/core/ext-py/greenlet-0.4.12/platform/switch_ppc_linux.h
  34. 82 0
      desktop/core/ext-py/greenlet-0.4.12/platform/switch_ppc_macosx.h
  35. 82 0
      desktop/core/ext-py/greenlet-0.4.12/platform/switch_ppc_unix.h
  36. 87 0
      desktop/core/ext-py/greenlet-0.4.12/platform/switch_s390_unix.h
  37. 92 0
      desktop/core/ext-py/greenlet-0.4.12/platform/switch_sparc_sun_gcc.h
  38. 63 0
      desktop/core/ext-py/greenlet-0.4.12/platform/switch_x32_unix.h
  39. 111 0
      desktop/core/ext-py/greenlet-0.4.12/platform/switch_x64_masm.asm
  40. BIN
      desktop/core/ext-py/greenlet-0.4.12/platform/switch_x64_masm.obj
  41. 57 0
      desktop/core/ext-py/greenlet-0.4.12/platform/switch_x64_msvc.h
  42. 88 0
      desktop/core/ext-py/greenlet-0.4.12/platform/switch_x86_msvc.h
  43. 105 0
      desktop/core/ext-py/greenlet-0.4.12/platform/switch_x86_unix.h
  44. 63 0
      desktop/core/ext-py/greenlet-0.4.12/run-tests.py
  45. 2 0
      desktop/core/ext-py/greenlet-0.4.12/setup.cfg
  46. 105 0
      desktop/core/ext-py/greenlet-0.4.12/setup.py
  47. 2 0
      desktop/core/ext-py/greenlet-0.4.12/setup_switch_x64_masm.cmd
  48. 50 0
      desktop/core/ext-py/greenlet-0.4.12/slp_platformselect.h
  49. 39 0
      desktop/core/ext-py/greenlet-0.4.12/tox.ini

+ 15 - 0
desktop/core/ext-py/greenlet-0.4.12/.travis.yml

@@ -0,0 +1,15 @@
+language: python
+sudo: false
+
+python:
+  - 2.6
+  - 2.7
+  - 3.2
+  - 3.3
+  - 3.4
+  - 3.5
+  - 3.6
+
+install: python setup.py build_ext -i
+
+script: python run-tests.py

+ 44 - 0
desktop/core/ext-py/greenlet-0.4.12/AUTHORS

@@ -0,0 +1,44 @@
+Original Authors
+----------------
+* Armin Rigo
+* Christian Tismer
+
+Contributors
+------------
+* Al Stone
+* Alexander Schmidt
+* Alexey Borzenkov
+* Andreas Schwab
+* Armin Ronacher
+* Bin Wang <feisuzhu@163.com>
+* Bob Ippolito
+* ChangBo Guo
+* Christoph Gohlke
+* Denis Bilenko
+* Dirk Mueller
+* Donovan Preston
+* Fantix King
+* Floris Bruynooghe
+* Fredrik Fornwall
+* Gerd Woetzel
+* Giel van Schijndel
+* Gustavo Niemeyer
+* Guy Rozendorn
+* Hye-Shik Chang
+* Jared Kuolt
+* Jason Madden
+* Kyle Ambroff
+* Marc Abramowitz
+* Marc Schlaich
+* Marcin Bachry
+* Matt Madison
+* Michael Ellerman
+* Michael Matz
+* Ralf Schmitt
+* Robie Basak
+* Ronny Pfannschmidt
+* Samual M. Rushing
+* Tony Bowles
+* Tony Breeds
+* Trevor Bowen
+* Ulrich Weigand

+ 30 - 0
desktop/core/ext-py/greenlet-0.4.12/LICENSE

@@ -0,0 +1,30 @@
+The following files are derived from Stackless Python and are subject to the
+same license as Stackless Python:
+
+	slp_platformselect.h
+	files in platform/ directory
+
+See LICENSE.PSF and http://www.stackless.com/ for details.
+
+Unless otherwise noted, the files in greenlet have been released under the
+following MIT license:
+
+Copyright (c) Armin Rigo, Christian Tismer and contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 47 - 0
desktop/core/ext-py/greenlet-0.4.12/LICENSE.PSF

@@ -0,0 +1,47 @@
+PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
+--------------------------------------------
+
+1. This LICENSE AGREEMENT is between the Python Software Foundation
+("PSF"), and the Individual or Organization ("Licensee") accessing and
+otherwise using this software ("Python") in source or binary form and
+its associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, PSF hereby
+grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
+analyze, test, perform and/or display publicly, prepare derivative works,
+distribute, and otherwise use Python alone or in any derivative version,
+provided, however, that PSF's License Agreement and PSF's notice of copyright,
+i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+2011 Python Software Foundation; All Rights Reserved" are retained in Python
+alone or in any derivative version prepared by Licensee.
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates Python or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to Python.
+
+4. PSF is making Python available to Licensee on an "AS IS"
+basis.  PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. Nothing in this License Agreement shall be deemed to create any
+relationship of agency, partnership, or joint venture between PSF and
+Licensee.  This License Agreement does not grant permission to use PSF
+trademarks or trade name in a trademark sense to endorse or promote
+products or services of Licensee, or any third party.
+
+8. By copying, installing or otherwise using Python, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.

+ 63 - 0
desktop/core/ext-py/greenlet-0.4.12/MANIFEST.in

@@ -0,0 +1,63 @@
+include .travis.yml
+include AUTHORS
+include LICENSE
+include LICENSE.PSF
+include MANIFEST.in
+include NEWS
+include README.rst
+include appveyor.yml
+include appveyor/run_pip.py
+include appveyor/run_with_env.cmd
+include benchmarks/chain.py
+include conftest.py
+include dev-requirements.txt
+include doc/Makefile
+include doc/conf.py
+include doc/greenlet.txt
+include doc/index.txt
+include doc/make.bat
+include greenlet.c
+include greenlet.h
+include make-manylinux
+include make-win-release
+include my_build_ext.py
+include platform/switch_aarch64_gcc.h
+include platform/switch_amd64_unix.h
+include platform/switch_arm32_gcc.h
+include platform/switch_arm32_ios.h
+include platform/switch_m68k_gcc.h
+include platform/switch_mips_unix.h
+include platform/switch_ppc64_linux.h
+include platform/switch_ppc_aix.h
+include platform/switch_ppc_linux.h
+include platform/switch_ppc_macosx.h
+include platform/switch_ppc_unix.h
+include platform/switch_s390_unix.h
+include platform/switch_sparc_sun_gcc.h
+include platform/switch_x32_unix.h
+include platform/switch_x64_masm.asm
+include platform/switch_x64_masm.obj
+include platform/switch_x64_msvc.h
+include platform/switch_x86_msvc.h
+include platform/switch_x86_unix.h
+include run-tests.py
+include setup.cfg
+include setup.py
+include setup_switch_x64_masm.cmd
+include slp_platformselect.h
+include tests/__init__.py
+include tests/_test_extension.c
+include tests/_test_extension_cpp.cpp
+include tests/test_cpp.py
+include tests/test_extension_interface.py
+include tests/test_gc.py
+include tests/test_generator.py
+include tests/test_generator_nested.py
+include tests/test_greenlet.py
+include tests/test_leaks.py
+include tests/test_stack_saved.py
+include tests/test_throw.py
+include tests/test_tracing.py
+include tests/test_version.py
+include tests/test_weakref.py
+include tox.ini

+ 148 - 0
desktop/core/ext-py/greenlet-0.4.12/NEWS

@@ -0,0 +1,148 @@
+0.4.12
+======
+- Stop using trashcan api
+
+0.4.11
+======
+- Fixes for aarch64 architecture
+
+0.4.10
+======
+- Added missing files to manifest
+- Added workaround for ppc32 on Linux
+- Start building binary manylinux1 wheels
+
+0.4.9
+=====
+- Fixed Windows builds
+
+0.4.8
+=====
+- Added support for iOS (arm32)
+- Added support for ppc64le
+
+0.4.7
+=====
+- Added a missing workaround for `return 0` on mips
+- Restore compatibility with Python 2.5
+- Fixed stack switching on sparc
+
+0.4.6
+=====
+- Expose `_stack_saved` property on greenlet objects, it may be used to
+  introspect the amount of memory used by a saved stack, but the API is
+  subject to change in the future
+- Added a workaround for `return 0` compiler optimizations on all
+  architectures
+- C API typo fixes
+
+0.4.5
+=====
+- Fixed several bugs in greenlet C API
+- Fixed a bug in multi-threaded applications, which manifested itself
+  with spurious "cannot switch to a different thread" exceptions
+- Fixed some crashes on arm and mips architectures
+
+0.4.4
+=====
+- Fixed PyGreenlet_SetParent signature, thanks to BoonsNaibot
+- Fixed 64-bit Windows builds depending on wrong runtime dll
+
+0.4.3
+=====
+- Better slp_switch performance on SPARC
+- Drop support for Python 2.3
+- Fix trashcan assertions on debug builds of Python
+- Remove deprecated -fno-tree-dominator-opts compiler switch
+- Enable switch code for SunStudio on 32-bit SunOS
+- Support for abc abstract methods in greenlet subclasses
+- Support custom directories for tests
+- Document switch tracing support
+
+0.4.2
+=====
+- Add .travis.yml
+- Fix 'err' may be used uninitialized in this function
+- Check _MSC_VER for msvc specific code
+- Fix slp_switch on SPARC for multi-threaded environments
+- Add support for m68k
+
+0.4.1
+=====
+* fix segfaults when using gcc 4.8 on amd64/x86 unix
+* try to disable certain gcc 4.8 optimizations that make greenlet
+  crash
+* Fix greenlet on aarch64 with gcc 4.8
+* workaround segfault on SunOS/sun4v
+* Add support for Aarch64
+* Add support for x32 psABI on x86_64
+* Changed memory constraints for assembly macro for PPC Linux
+  platforms.
+
+0.4.0
+=====
+* Greenlet has an instance dictionary now, which means it can be
+  used for implementing greenlet local storage, etc. However, this
+  might introduce incompatibility if subclasses have __dict__ in their
+  __slots__. Classes like that will fail, because greenlet already
+  has __dict__ out of the box.
+* Greenlet no longer leaks memory after thread termination, as long as
+  terminated thread has no running greenlets left at the time.
+* Add support for debian sparc and openbsd5-sparc64
+* Add support for ppc64 linux
+* Don't allow greenlets to be copied with copy.copy/deepcopy
+* Fix arm32/thumb support
+* Restore greenlet's parent after kill
+* Add experimental greenlet tracing
+
+0.3.4
+=====
+* Use plain distutils for install command, this fixes installation of
+  the greenlet.h header.
+* Enhanced arm32 support
+* Fix support for Linux/S390 zSeries
+* Workaround compiler bug on RHEL 3 / CentOS 3
+
+0.3.3
+=====
+* Use sphinx to build documentation and publish it on greenlet.rtfd.org
+* Prevent segfaults on openbsd 4/i386
+* Workaround gcc-4.0 not allowing to clobber rbx
+* Enhance test infrastructure
+* Fix possible compilation problems when including greenlet.h in C++ mode
+* Make the greenlet module work on x64 windows
+* Add a test for greenlet C++ exceptions
+* Fix compilation on Solaris with SunStudio
+
+0.3.2
+=====
+* Fix various crashes with recent gcc versions and VC90
+* Try to fix stack save/restore on arm32
+* Store and restore the threadstate on exceptions like pypy/stackless do
+* GreenletExit is now based on BaseException on Python >= 2.5
+* Switch to using PyCapsule for Python 2.7 and 3.1
+* Port for AIX on PowerPC
+* Fix the sparc/solaris header
+* Improved build dependencies patch from flub.
+* Can't pass parent=None to greenlet.greenlet() (fixes #21)
+* Rudimentary gc support (only non-live greenlets are garbage collected though)
+
+0.3.1
+=====
+* Fix reference leak when passing keyword arguments to greenlets (mbachry)
+* Updated documentation.
+
+0.3
+===
+* Python 3 support.
+* New C API to expose Greenlets to C Extensions.
+* greenlet.switch() now accept's keyword arguments.
+* Fix Python crasher caused by switching to new greenlet from another thread.
+* Fix Python 2.6 crash on Windows when built with VS2009. (arigo)
+* arm32 support from stackless (Sylvain Baro)
+* Linux mips support (Thiemo Seufer)
+* MingGW GCC 4.4 support (Giovanni Bajo)
+* Fix for a threading bug (issue 40 in py lib) (arigo and ghazel)
+* Loads more unit tests, some from py lib (3 times as many as Greenlet 0.2)
+* Add documentation from py lib.
+* General code, documentation and repository cleanup (Kyle Ambroff, Jared Kuolt)

+ 87 - 0
desktop/core/ext-py/greenlet-0.4.12/PKG-INFO

@@ -0,0 +1,87 @@
+Metadata-Version: 1.1
+Name: greenlet
+Version: 0.4.12
+Summary: Lightweight in-process concurrent programming
+Home-page: https://github.com/python-greenlet/greenlet
+Author: Alexey Borzenkov
+Author-email: snaury@gmail.com
+License: MIT License
+Description: .. image:: https://secure.travis-ci.org/python-greenlet/greenlet.png
+           :target: http://travis-ci.org/python-greenlet/greenlet
+        
+        The greenlet package is a spin-off of Stackless, a version of CPython
+        that supports micro-threads called "tasklets". Tasklets run
+        pseudo-concurrently (typically in a single or a few OS-level threads)
+        and are synchronized with data exchanges on "channels".
+        
+        A "greenlet", on the other hand, is a still more primitive notion of
+        micro-thread with no implicit scheduling; coroutines, in other
+        words. This is useful when you want to control exactly when your code
+        runs. You can build custom scheduled micro-threads on top of greenlet;
+        however, it seems that greenlets are useful on their own as a way to
+        make advanced control flow structures. For example, we can recreate
+        generators; the difference with Python's own generators is that our
+        generators can call nested functions and the nested functions can
+        yield values too. Additionally, you don't need a "yield" keyword. See
+        the example in tests/test_generator.py.
+        
+        Greenlets are provided as a C extension module for the regular
+        unmodified interpreter.
+        
+        Greenlets are lightweight coroutines for in-process concurrent
+        programming.
+        
+        Who is using Greenlet?
+        ======================
+        
+        There are several libraries that use Greenlet as a more flexible
+        alternative to Python's built in coroutine support:
+        
+         - `Concurrence`_
+         - `Eventlet`_
+         - `Gevent`_
+        
+        .. _Concurrence: http://opensource.hyves.org/concurrence/
+        .. _Eventlet: http://eventlet.net/
+        .. _Gevent: http://www.gevent.org/
+        
+        Getting Greenlet
+        ================
+        
+        The easiest way to get Greenlet is to install it with pip or
+        easy_install::
+        
+          pip install greenlet
+          easy_install greenlet
+        
+        
+        Source code archives and windows installers are available on the
+        python package index at https://pypi.python.org/pypi/greenlet
+        
+        The source code repository is hosted on github:
+        https://github.com/python-greenlet/greenlet
+        
+        Documentation is available on readthedocs.org:
+        https://greenlet.readthedocs.io
+        
+Platform: any
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Natural Language :: English
+Classifier: Programming Language :: C
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.4
+Classifier: Programming Language :: Python :: 2.5
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.0
+Classifier: Programming Language :: Python :: 3.1
+Classifier: Programming Language :: Python :: 3.2
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Operating System :: OS Independent
+Classifier: Topic :: Software Development :: Libraries :: Python Modules

+ 57 - 0
desktop/core/ext-py/greenlet-0.4.12/README.rst

@@ -0,0 +1,57 @@
+.. image:: https://secure.travis-ci.org/python-greenlet/greenlet.png
+   :target: http://travis-ci.org/python-greenlet/greenlet
+
+The greenlet package is a spin-off of Stackless, a version of CPython
+that supports micro-threads called "tasklets". Tasklets run
+pseudo-concurrently (typically in a single or a few OS-level threads)
+and are synchronized with data exchanges on "channels".
+
+A "greenlet", on the other hand, is a still more primitive notion of
+micro-thread with no implicit scheduling; coroutines, in other
+words. This is useful when you want to control exactly when your code
+runs. You can build custom scheduled micro-threads on top of greenlet;
+however, it seems that greenlets are useful on their own as a way to
+make advanced control flow structures. For example, we can recreate
+generators; the difference with Python's own generators is that our
+generators can call nested functions and the nested functions can
+yield values too. Additionally, you don't need a "yield" keyword. See
+the example in tests/test_generator.py.
+
+Greenlets are provided as a C extension module for the regular
+unmodified interpreter.
+
+Greenlets are lightweight coroutines for in-process concurrent
+programming.
+
+Who is using Greenlet?
+======================
+
+There are several libraries that use Greenlet as a more flexible
+alternative to Python's built in coroutine support:
+
+ - `Concurrence`_
+ - `Eventlet`_
+ - `Gevent`_
+
+.. _Concurrence: http://opensource.hyves.org/concurrence/
+.. _Eventlet: http://eventlet.net/
+.. _Gevent: http://www.gevent.org/
+
+Getting Greenlet
+================
+
+The easiest way to get Greenlet is to install it with pip or
+easy_install::
+
+  pip install greenlet
+  easy_install greenlet
+
+
+Source code archives and windows installers are available on the
+python package index at https://pypi.python.org/pypi/greenlet
+
+The source code repository is hosted on github:
+https://github.com/python-greenlet/greenlet
+
+Documentation is available on readthedocs.org:
+https://greenlet.readthedocs.io

+ 81 - 0
desktop/core/ext-py/greenlet-0.4.12/appveyor.yml

@@ -0,0 +1,81 @@
+version: 0.4.12.{build}
+environment:
+  global:
+    # SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the
+    # /E:ON and /V:ON options are not enabled in the batch script intepreter
+    # See: http://stackoverflow.com/a/13751649/163740
+    CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\appveyor\\run_with_env.cmd"
+
+  matrix:
+    # http://www.appveyor.com/docs/installed-software#python
+    - PYTHON_ROOT: "C:\\Python26"
+      PYTHON_ARCH: "32"
+      PYTHON_VERSION: "2.6.x"
+
+    - PYTHON_ROOT: "C:\\Python26-x64"
+      PYTHON_ARCH: "64"
+      PYTHON_VERSION: "2.6.x"
+
+    - PYTHON_ROOT: "C:\\Python27"
+      PYTHON_ARCH: "32"
+      PYTHON_VERSION: "2.7.x"
+
+    - PYTHON_ROOT: "C:\\Python27-x64"
+      PYTHON_ARCH: "64"
+      PYTHON_VERSION: "2.7.x"
+
+    - PYTHON_ROOT: "C:\\Python33"
+      PYTHON_ARCH: "32"
+      PYTHON_VERSION: "3.3.x"
+
+    - PYTHON_ROOT: "C:\\Python33-x64"
+      PYTHON_ARCH: "64"
+      PYTHON_VERSION: "3.3.x"
+
+    - PYTHON_ROOT: "C:\\Python34"
+      PYTHON_ARCH: "32"
+      PYTHON_VERSION: "3.4.x"
+
+    - PYTHON_ROOT: "C:\\Python34-x64"
+      PYTHON_ARCH: "64"
+      PYTHON_VERSION: "3.4.x"
+
+    - PYTHON_ROOT: "C:\\Python35"
+      PYTHON_ARCH: "32"
+      PYTHON_VERSION: "3.5.x"
+
+    - PYTHON_ROOT: "C:\\Python35-x64"
+      PYTHON_ARCH: "64"
+      PYTHON_VERSION: "3.5.x"
+
+    - PYTHON_ROOT: "C:\\Python36"
+      PYTHON_ARCH: "32"
+      PYTHON_VERSION: "3.6.x"
+
+    - PYTHON_ROOT: "C:\\Python36-x64"
+      PYTHON_ARCH: "64"
+      PYTHON_VERSION: "3.6.x"
+
+install:
+  - "SET PATH=%PYTHON_ROOT%;%PYTHON_ROOT%\\Scripts;%PATH%"
+  - "python --version"
+  - "python -c \"import struct; print(struct.calcsize('P') * 8)\""
+
+  # Upgrade pip to the latest version
+  - "python appveyor\\run_pip.py install --disable-pip-version-check --upgrade pip"
+
+  # Install requirements for running tests and building artifacts
+  - "%CMD_IN_ENV% pip install --upgrade -r dev-requirements.txt"
+
+build_script:
+  - "%CMD_IN_ENV% python setup.py build"
+
+test_script:
+  - "%CMD_IN_ENV% python setup.py test"
+
+after_test:
+  - "%CMD_IN_ENV% python setup.py bdist_wheel"
+  - "%CMD_IN_ENV% python setup.py bdist_egg"
+
+artifacts:
+  - path: dist\*

+ 6 - 0
desktop/core/ext-py/greenlet-0.4.12/appveyor/run_pip.py

@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+import sys
+from pip import main
+
+if __name__ == '__main__':
+    sys.exit(main())

+ 88 - 0
desktop/core/ext-py/greenlet-0.4.12/appveyor/run_with_env.cmd

@@ -0,0 +1,88 @@
+:: To build extensions for 64 bit Python 3, we need to configure environment
+:: variables to use the MSVC 2010 C++ compilers from GRMSDKX_EN_DVD.iso of:
+:: MS Windows SDK for Windows 7 and .NET Framework 4 (SDK v7.1)
+::
+:: To build extensions for 64 bit Python 2, we need to configure environment
+:: variables to use the MSVC 2008 C++ compilers from GRMSDKX_EN_DVD.iso of:
+:: MS Windows SDK for Windows 7 and .NET Framework 3.5 (SDK v7.0)
+::
+:: 32 bit builds, and 64-bit builds for 3.5 and beyond, do not require specific
+:: environment configurations.
+::
+:: Note: this script needs to be run with the /E:ON and /V:ON flags for the
+:: cmd interpreter, at least for (SDK v7.0)
+::
+:: More details at:
+:: https://github.com/cython/cython/wiki/64BitCythonExtensionsOnWindows
+:: http://stackoverflow.com/a/13751649/163740
+::
+:: Author: Olivier Grisel
+:: License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/
+::
+:: Notes about batch files for Python people:
+::
+:: Quotes in values are literally part of the values:
+::      SET FOO="bar"
+:: FOO is now five characters long: " b a r "
+:: If you don't want quotes, don't include them on the right-hand side.
+::
+:: The CALL lines at the end of this file look redundant, but if you move them
+:: outside of the IF clauses, they do not run properly in the SET_SDK_64==Y
+:: case, I don't know why.
+@ECHO OFF
+
+SET COMMAND_TO_RUN=%*
+SET WIN_SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows
+SET WIN_WDK=c:\Program Files (x86)\Windows Kits\10\Include\wdf
+
+:: Extract the major and minor versions, and allow for the minor version to be
+:: more than 9.  This requires the version number to have two dots in it.
+SET MAJOR_PYTHON_VERSION=%PYTHON_VERSION:~0,1%
+IF "%PYTHON_VERSION:~3,1%" == "." (
+    SET MINOR_PYTHON_VERSION=%PYTHON_VERSION:~2,1%
+) ELSE (
+    SET MINOR_PYTHON_VERSION=%PYTHON_VERSION:~2,2%
+)
+
+:: Based on the Python version, determine what SDK version to use, and whether
+:: to set the SDK for 64-bit.
+IF %MAJOR_PYTHON_VERSION% == 2 (
+    SET WINDOWS_SDK_VERSION="v7.0"
+    SET SET_SDK_64=Y
+) ELSE (
+    IF %MAJOR_PYTHON_VERSION% == 3 (
+        SET WINDOWS_SDK_VERSION="v7.1"
+        IF %MINOR_PYTHON_VERSION% LEQ 4 (
+            SET SET_SDK_64=Y
+        ) ELSE (
+            SET SET_SDK_64=N
+            IF EXIST "%WIN_WDK%" (
+                :: See: https://connect.microsoft.com/VisualStudio/feedback/details/1610302/
+                REN "%WIN_WDK%" 0wdf
+            )
+        )
+    ) ELSE (
+        ECHO Unsupported Python version: "%MAJOR_PYTHON_VERSION%"
+        EXIT 1
+    )
+)
+
+IF %PYTHON_ARCH% == 64 (
+    IF %SET_SDK_64% == Y (
+        ECHO Configuring Windows SDK %WINDOWS_SDK_VERSION% for Python %MAJOR_PYTHON_VERSION% on a 64 bit architecture
+        SET DISTUTILS_USE_SDK=1
+        SET MSSdk=1
+        "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Setup\WindowsSdkVer.exe" -q -version:%WINDOWS_SDK_VERSION%
+        "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Bin\SetEnv.cmd" /x64 /release
+        ECHO Executing: %COMMAND_TO_RUN%
+        call %COMMAND_TO_RUN% || EXIT 1
+    ) ELSE (
+        ECHO Using default MSVC build environment for 64 bit architecture
+        ECHO Executing: %COMMAND_TO_RUN%
+        call %COMMAND_TO_RUN% || EXIT 1
+    )
+) ELSE (
+    ECHO Using default MSVC build environment for 32 bit architecture
+    ECHO Executing: %COMMAND_TO_RUN%
+    call %COMMAND_TO_RUN% || EXIT 1
+)

+ 39 - 0
desktop/core/ext-py/greenlet-0.4.12/benchmarks/chain.py

@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+
+"""Create a chain of coroutines and pass a value from one end to the other,
+where each coroutine will increment the value before passing it along.
+"""
+
+import optparse
+import time
+
+import greenlet
+
+
+def link(next_greenlet):
+    value = greenlet.getcurrent().parent.switch()
+    next_greenlet.switch(value + 1)
+
+
+def chain(n):
+    start_node = greenlet.getcurrent()
+    for i in xrange(n):
+        g = greenlet.greenlet(link)
+        g.switch(start_node)
+        start_node = g
+    return start_node.switch(0)
+
+if __name__ == '__main__':
+    p = optparse.OptionParser(
+        usage='%prog [-n NUM_COROUTINES]', description=__doc__)
+    p.add_option(
+        '-n', type='int', dest='num_greenlets', default=100000,
+        help='The number of greenlets in the chain.')
+    options, args = p.parse_args()
+
+    if len(args) != 0:
+        p.error('unexpected arguments: %s' % ', '.join(args))
+
+    start_time = time.clock()
+    print 'Result:', chain(options.num_greenlets)
+    print time.clock() - start_time, 'seconds'

+ 18 - 0
desktop/core/ext-py/greenlet-0.4.12/conftest.py

@@ -0,0 +1,18 @@
+# configuration file for py.test
+
+import sys, os
+from distutils.spawn import spawn
+
+
+def pytest_configure(config):
+    os.chdir(os.path.dirname(__file__))
+    cmd = [sys.executable, "setup.py", "-q", "build_ext", "-q", "-i"]
+    spawn(cmd, search_path=0)
+
+    from tests import build_test_extensions
+    build_test_extensions()
+
+
+def pytest_report_header(config):
+    import greenlet
+    return "greenlet %s from %s" % (greenlet.__version__, greenlet.__file__)

+ 2 - 0
desktop/core/ext-py/greenlet-0.4.12/dev-requirements.txt

@@ -0,0 +1,2 @@
+setuptools
+wheel

+ 153 - 0
desktop/core/ext-py/greenlet-0.4.12/doc/Makefile

@@ -0,0 +1,153 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = _build
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html       to make standalone HTML files"
+	@echo "  dirhtml    to make HTML files named index.html in directories"
+	@echo "  singlehtml to make a single large HTML file"
+	@echo "  pickle     to make pickle files"
+	@echo "  json       to make JSON files"
+	@echo "  htmlhelp   to make HTML files and a HTML help project"
+	@echo "  qthelp     to make HTML files and a qthelp project"
+	@echo "  devhelp    to make HTML files and a Devhelp project"
+	@echo "  epub       to make an epub"
+	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
+	@echo "  text       to make text files"
+	@echo "  man        to make manual pages"
+	@echo "  texinfo    to make Texinfo files"
+	@echo "  info       to make Texinfo files and run them through makeinfo"
+	@echo "  gettext    to make PO message catalogs"
+	@echo "  changes    to make an overview of all changed/added/deprecated items"
+	@echo "  linkcheck  to check all external links for integrity"
+	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+	-rm -rf $(BUILDDIR)/*
+
+html:
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+	@echo
+	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+json:
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+	@echo
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
+	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/greenlet.qhcp"
+	@echo "To view the help file:"
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/greenlet.qhc"
+
+devhelp:
+	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+	@echo
+	@echo "Build finished."
+	@echo "To view the help file:"
+	@echo "# mkdir -p $$HOME/.local/share/devhelp/greenlet"
+	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/greenlet"
+	@echo "# devhelp"
+
+epub:
+	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+	@echo
+	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+	@echo "Run \`make' in that directory to run these through (pdf)latex" \
+	      "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo "Running LaTeX files through pdflatex..."
+	$(MAKE) -C $(BUILDDIR)/latex all-pdf
+	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+	@echo
+	@echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+	@echo
+	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo
+	@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+	@echo "Run \`make' in that directory to run these through makeinfo" \
+	      "(use \`make info' here to do that automatically)."
+
+info:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo "Running Texinfo files through makeinfo..."
+	make -C $(BUILDDIR)/texinfo info
+	@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+	$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+	@echo
+	@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+	@echo
+	@echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+	@echo "Testing of doctests in the sources finished, look at the " \
+	      "results in $(BUILDDIR)/doctest/output.txt."

+ 242 - 0
desktop/core/ext-py/greenlet-0.4.12/doc/conf.py

@@ -0,0 +1,242 @@
+# -*- coding: utf-8 -*-
+#
+# greenlet documentation build configuration file, created by
+# sphinx-quickstart on Tue Dec 27 22:58:53 2011.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = []
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = []  # ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.txt'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'greenlet'
+copyright = u'2011, Armin Rigo, Christian Tismer'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '0.4'
+# The full version, including alpha/beta/rc tags.
+release = '0.4.0'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = []  # ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'greenletdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ('index', 'greenlet.tex', u'greenlet Documentation',
+   u'Armin Rigo, Christian Tismer', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    ('index', 'greenlet', u'greenlet Documentation',
+     [u'Armin Rigo, Christian Tismer'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+  ('index', 'greenlet', u'greenlet Documentation',
+   u'Armin Rigo, Christian Tismer', 'greenlet', 'One line description of project.',
+   'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'

+ 426 - 0
desktop/core/ext-py/greenlet-0.4.12/doc/greenlet.txt

@@ -0,0 +1,426 @@
+=====================================================
+greenlet: Lightweight concurrent programming
+=====================================================
+.. toctree::
+   :maxdepth: 2
+
+Motivation
+==========
+
+The "greenlet" package is a spin-off of `Stackless`_, a version of CPython
+that supports micro-threads called "tasklets".  Tasklets run
+pseudo-concurrently (typically in a single or a few OS-level threads) and
+are synchronized with data exchanges on "channels".
+
+A "greenlet", on the other hand, is a still more primitive notion of
+micro-thread with no implicit scheduling; coroutines, in other words.  
+This is useful when you want to
+control exactly when your code runs.  You can build custom scheduled
+micro-threads on top of greenlet; however, it seems that greenlets are
+useful on their own as a way to make advanced control flow structures.  
+For example, we can recreate generators; the difference with Python's own
+generators is that our generators can call nested functions and the nested
+functions can yield values too.  (Additionally, you don't need a "yield"
+keyword.  See the example in ``test/test_generator.py``). 
+
+Greenlets are provided as a C extension module for the regular unmodified
+interpreter.
+
+.. _`Stackless`: http://www.stackless.com
+
+Example
+-------
+
+Let's consider a system controlled by a terminal-like console, where the user
+types commands.  Assume that the input comes character by character.  In such
+a system, there will typically be a loop like the following one::
+
+    def process_commands(*args):
+        while True:
+            line = ''
+            while not line.endswith('\n'):
+                line += read_next_char()
+            if line == 'quit\n':
+                print "are you sure?"
+                if read_next_char() != 'y':
+                    continue    # ignore the command
+            process_command(line)
+
+Now assume that you want to plug this program into a GUI.  Most GUI toolkits
+are event-based.  They will invoke a call-back for each character the user
+presses.  [Replace "GUI" with "XML expat parser" if that rings more bells to
+you ``:-)``]  In this setting, it is difficult to implement the
+read_next_char() function needed by the code above.  We have two incompatible
+functions::
+
+    def event_keydown(key):
+        ?? 
+
+    def read_next_char():
+        ?? should wait for the next event_keydown() call
+
+You might consider doing that with threads.  Greenlets are an alternate
+solution that don't have the related locking and shutdown problems.  You
+start the process_commands() function in its own, separate greenlet, and
+then you exchange the keypresses with it as follows::
+
+    def event_keydown(key):
+             # jump into g_processor, sending it the key
+        g_processor.switch(key)
+
+    def read_next_char():
+            # g_self is g_processor in this simple example
+        g_self = greenlet.getcurrent()
+            # jump to the parent (main) greenlet, waiting for the next key
+        next_char = g_self.parent.switch()
+        return next_char
+
+    g_processor = greenlet(process_commands)
+    g_processor.switch(*args)   # input arguments to process_commands()
+
+    gui.mainloop()
+
+In this example, the execution flow is: when read_next_char() is called, it
+is part of the g_processor greenlet, so when it switches to its parent
+greenlet, it resumes execution in the top-level main loop (the GUI).  When
+the GUI calls event_keydown(), it switches to g_processor, which means that
+the execution jumps back wherever it was suspended in that greenlet -- in
+this case, to the switch() instruction in read_next_char() -- and the ``key``
+argument in event_keydown() is passed as the return value of the switch() in
+read_next_char().
+
+Note that read_next_char() will be suspended and resumed with its call stack
+preserved, so that it will itself return to different positions in
+process_commands() depending on where it was originally called from.  This
+allows the logic of the program to be kept in a nice control-flow way; we
+don't have to completely rewrite process_commands() to turn it into a state
+machine.
+
+
+Usage
+=====
+
+Introduction
+------------
+
+A "greenlet" is a small independent pseudo-thread.  Think about it as a
+small stack of frames; the outermost (bottom) frame is the initial
+function you called, and the innermost frame is the one in which the
+greenlet is currently paused.  You work with greenlets by creating a
+number of such stacks and jumping execution between them.  Jumps are never
+implicit: a greenlet must choose to jump to another greenlet, which will
+cause the former to suspend and the latter to resume where it was
+suspended.  Jumping between greenlets is called "switching".
+
+When you create a greenlet, it gets an initially empty stack; when you
+first switch to it, it starts to run a specified function, which may call
+other functions, switch out of the greenlet, etc.  When eventually the
+outermost function finishes its execution, the greenlet's stack becomes
+empty again and the greenlet is "dead".  Greenlets can also die of an
+uncaught exception.
+
+For example::
+
+    from greenlet import greenlet
+
+    def test1():
+        print 12
+        gr2.switch()
+        print 34
+
+    def test2():
+        print 56
+        gr1.switch()
+        print 78
+
+    gr1 = greenlet(test1)
+    gr2 = greenlet(test2)
+    gr1.switch()
+
+The last line jumps to test1, which prints 12, jumps to test2, prints 56,
+jumps back into test1, prints 34; and then test1 finishes and gr1 dies.  
+At this point, the execution comes back to the original ``gr1.switch()``
+call.  Note that 78 is never printed.
+
+Parents
+-------
+
+Let's see where execution goes when a greenlet dies.  Every greenlet has a
+"parent" greenlet.  The parent greenlet is initially the one in which the
+greenlet was created (this can be changed at any time).  The parent is
+where execution continues when a greenlet dies.  This way, greenlets are
+organized in a tree.  Top-level code that doesn't run in a user-created
+greenlet runs in the implicit "main" greenlet, which is the root of the
+tree.
+
+In the above example, both gr1 and gr2 have the main greenlet as a parent.  
+Whenever one of them dies, the execution comes back to "main".
+
+Uncaught exceptions are propagated into the parent, too.  For example, if
+the above test2() contained a typo, it would generate a NameError that
+would kill gr2, and the exception would go back directly into "main".  
+The traceback would show test2, but not test1.  Remember, switches are not
+calls, but transfer of execution between parallel "stack containers", and
+the "parent" defines which stack logically comes "below" the current one.
+
+Instantiation
+-------------
+
+``greenlet.greenlet`` is the greenlet type, which supports the following
+operations:
+
+``greenlet(run=None, parent=None)``
+    Create a new greenlet object (without running it).  ``run`` is the
+    callable to invoke, and ``parent`` is the parent greenlet, which
+    defaults to the current greenlet.
+
+``greenlet.getcurrent()``
+    Returns the current greenlet (i.e. the one which called this
+    function).
+
+``greenlet.GreenletExit``
+    This special exception does not propagate to the parent greenlet; it
+    can be used to kill a single greenlet.
+
+The ``greenlet`` type can be subclassed, too.  A greenlet runs by calling
+its ``run`` attribute, which is normally set when the greenlet is
+created; but for subclasses it also makes sense to define a ``run`` method
+instead of giving a ``run`` argument to the constructor.
+
+Switching
+---------
+
+Switches between greenlets occur when the method switch() of a greenlet is
+called, in which case execution jumps to the greenlet whose switch() is
+called, or when a greenlet dies, in which case execution jumps to the
+parent greenlet.  During a switch, an object or an exception is "sent" to
+the target greenlet; this can be used as a convenient way to pass
+information between greenlets.  For example::
+
+    def test1(x, y):
+        z = gr2.switch(x+y)
+        print z
+
+    def test2(u):
+        print u
+        gr1.switch(42)
+
+    gr1 = greenlet(test1)
+    gr2 = greenlet(test2)
+    gr1.switch("hello", " world")
+
+This prints "hello world" and 42, with the same order of execution as the
+previous example.  Note that the arguments of test1() and test2() are not
+provided when the greenlet is created, but only the first time someone
+switches to it.
+
+Here are the precise rules for sending objects around:
+
+``g.switch(*args, **kwargs)``
+    Switches execution to the greenlet ``g``, sending it the given
+    arguments.  As a special case, if ``g`` did not start yet, then it
+    will start to run now.
+
+Dying greenlet
+    If a greenlet's ``run()`` finishes, its return value is the object 
+    sent to its parent.  If ``run()`` terminates with an exception, the
+    exception is propagated to its parent (unless it is a
+    ``greenlet.GreenletExit`` exception, in which case the exception
+    object is caught and *returned* to the parent).
+
+Apart from the cases described above, the target greenlet normally
+receives the object as the return value of the call to ``switch()`` in
+which it was previously suspended.  Indeed, although a call to
+``switch()`` does not return immediately, it will still return at some
+point in the future, when some other greenlet switches back.  When this
+occurs, then execution resumes just after the ``switch()`` where it was
+suspended, and the ``switch()`` itself appears to return the object that
+was just sent.  This means that ``x = g.switch(y)`` will send the object
+``y`` to ``g``, and will later put the (unrelated) object that some
+(unrelated) greenlet passes back to us into ``x``.
+
+Note that any attempt to switch to a dead greenlet actually goes to the
+dead greenlet's parent, or its parent's parent, and so on.  (The final
+parent is the "main" greenlet, which is never dead.)
+
+Methods and attributes of greenlets
+-----------------------------------
+
+``g.switch(*args, **kwargs)``
+    Switches execution to the greenlet ``g``.  See above.
+
+``g.run``
+    The callable that ``g`` will run when it starts.  After ``g`` started,
+    this attribute no longer exists.
+
+``g.parent``
+    The parent greenlet.  This is writeable, but it is not allowed to
+    create cycles of parents.
+
+``g.gr_frame``
+    The current top frame, or None.
+
+``g.dead``
+    True if ``g`` is dead (i.e. it finished its execution).
+
+``bool(g)``
+    True if ``g`` is active, False if it is dead or not yet started.
+
+``g.throw([typ, [val, [tb]]])``
+    Switches execution to the greenlet ``g``, but immediately raises the
+    given exception in ``g``.  If no argument is provided, the exception
+    defaults to ``greenlet.GreenletExit``.  The normal exception
+    propagation rules apply, as described above.  Note that calling this
+    method is almost equivalent to the following::
+
+        def raiser():
+            raise typ, val, tb
+        g_raiser = greenlet(raiser, parent=g)
+        g_raiser.switch()
+
+    except that this trick does not work for the
+    ``greenlet.GreenletExit`` exception, which would not propagate
+    from ``g_raiser`` to ``g``.
+
+Greenlets and Python threads
+----------------------------
+
+Greenlets can be combined with Python threads; in this case, each thread
+contains an independent "main" greenlet with a tree of sub-greenlets.  It
+is not possible to mix or switch between greenlets belonging to different
+threads.
+
+Garbage-collecting live greenlets
+---------------------------------
+
+If all the references to a greenlet object go away (including the
+references from the parent attribute of other greenlets), then there is no
+way to ever switch back to this greenlet.  In this case, a GreenletExit
+exception is generated into the greenlet.  This is the only case where a
+greenlet receives the execution asynchronously.  This gives
+``try:finally:`` blocks a chance to clean up resources held by the
+greenlet.  This feature also enables a programming style in which
+greenlets are infinite loops waiting for data and processing it.  Such
+loops are automatically interrupted when the last reference to the
+greenlet goes away.
+
+The greenlet is expected to either die or be resurrected by having a new
+reference to it stored somewhere; just catching and ignoring the
+GreenletExit is likely to lead to an infinite loop.
+
+Greenlets do not participate in garbage collection; cycles involving data
+that is present in a greenlet's frames will not be detected.  Storing
+references to other greenlets cyclically may lead to leaks.
+
+Tracing support
+---------------
+
+Standard Python tracing and profiling doesn't work as expected when used with
+greenlet since stack and frame switching happens on the same Python thread.
+It is difficult to detect greenlet switching reliably with conventional
+methods, so to improve support for debugging, tracing and profiling greenlet
+based code there are new functions in the greenlet module:
+
+``greenlet.gettrace()``
+    Returns a previously set tracing function, or None.
+
+``greenlet.settrace(callback)``
+    Sets a new tracing function and returns a previous tracing function, or
+    None. The callback is called on various events and is expected to have
+    the following signature::
+
+        def callback(event, args):
+            if event == 'switch':
+                origin, target = args
+                # Handle a switch from origin to target.
+                # Note that callback is running in the context of target
+                # greenlet and any exceptions will be passed as if
+                # target.throw() was used instead of a switch.
+                return
+            if event == 'throw':
+                origin, target = args
+                # Handle a throw from origin to target.
+                # Note that callback is running in the context of target
+                # greenlet and any exceptions will replace the original, as
+                # if target.throw() was used with the replacing exception.
+                return
+
+    For compatibility it is very important to unpack args tuple only when
+    event is either ``'switch'`` or ``'throw'`` and not when ``event`` is
+    potentially something else. This way API can be extended to new events
+    similar to ``sys.settrace()``.
+
+C API Reference
+===============
+
+Greenlets can be created and manipulated from extension modules written in C or
+C++, or from applications that embed Python. The ``greenlet.h`` header is
+provided, and exposes the entire API available to pure Python modules.
+
+Types
+-----
++--------------------+-------------------+
+| Type name          | Python name       |
++====================+===================+
+| PyGreenlet         | greenlet.greenlet |
++--------------------+-------------------+
+
+Exceptions
+----------
++---------------------+-----------------------+
+| Type name           | Python name           |
++=====================+=======================+
+| PyExc_GreenletError | greenlet.error        |
++---------------------+-----------------------+
+| PyExc_GreenletExit  | greenlet.GreenletExit |
++---------------------+-----------------------+
+
+Reference
+---------
+
+``PyGreenlet_Import()``
+    A macro that imports the greenlet module and initializes the C API. This
+    must be called once for each extension module that uses the greenlet C API.
+
+``int PyGreenlet_Check(PyObject *p)``
+    Macro that returns true if the argument is a PyGreenlet.
+
+``int PyGreenlet_STARTED(PyGreenlet *g)``
+    Macro that returns true if the greenlet ``g`` has started.
+
+``int PyGreenlet_ACTIVE(PyGreenlet *g)``
+    Macro that returns true if the greenlet ``g`` has started and has not died.
+
+``PyGreenlet *PyGreenlet_GET_PARENT(PyGreenlet *g)``
+    Macro that returns the parent greenlet of ``g``.
+
+``int PyGreenlet_SetParent(PyGreenlet *g, PyGreenlet *nparent)``
+    Set the parent greenlet of ``g``. Returns 0 for success. If -1 is returned,
+    then ``g`` is not a pointer to a PyGreenlet, and an AttributeError will
+    be raised.
+
+``PyGreenlet *PyGreenlet_GetCurrent(void)``
+    Returns the currently active greenlet object.
+
+``PyGreenlet *PyGreenlet_New(PyObject *run, PyObject *parent)``
+    Creates a new greenlet object with the callable ``run`` and parent
+    ``parent``. Both parameters are optional. If ``run`` is NULL, then the
+    greenlet will be created, but will fail if switched in. If ``parent`` is
+    NULL, the parent is automatically set to the current greenlet.
+
+``PyObject *PyGreenlet_Switch(PyGreenlet *g, PyObject *args, PyObject *kwargs)``
+    Switches to the greenlet ``g``. ``args`` and ``kwargs`` are optional and
+    can be NULL. If ``args`` is NULL, an empty tuple is passed to the target
+    greenlet. If kwargs is NULL, no keyword arguments are passed to the target
+    greenlet. If arguments are specified, ``args`` should be a tuple and
+    ``kwargs`` should be a dict.
+
+``PyObject *PyGreenlet_Throw(PyGreenlet *g, PyObject *typ, PyObject *val, PyObject *tb)``
+    Switches to greenlet ``g``, but immediately raise an exception of type
+    ``typ`` with the value ``val``, and optionally, the traceback object
+    ``tb``. ``tb`` can be NULL.
+
+Indices and tables
+==================
+
+* :ref:`search`

+ 1 - 0
desktop/core/ext-py/greenlet-0.4.12/doc/index.txt

@@ -0,0 +1 @@
+.. include:: greenlet.txt

+ 190 - 0
desktop/core/ext-py/greenlet-0.4.12/doc/make.bat

@@ -0,0 +1,190 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+	set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+	set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+	set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+	:help
+	echo.Please use `make ^<target^>` where ^<target^> is one of
+	echo.  html       to make standalone HTML files
+	echo.  dirhtml    to make HTML files named index.html in directories
+	echo.  singlehtml to make a single large HTML file
+	echo.  pickle     to make pickle files
+	echo.  json       to make JSON files
+	echo.  htmlhelp   to make HTML files and a HTML help project
+	echo.  qthelp     to make HTML files and a qthelp project
+	echo.  devhelp    to make HTML files and a Devhelp project
+	echo.  epub       to make an epub
+	echo.  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+	echo.  text       to make text files
+	echo.  man        to make manual pages
+	echo.  texinfo    to make Texinfo files
+	echo.  gettext    to make PO message catalogs
+	echo.  changes    to make an overview over all changed/added/deprecated items
+	echo.  linkcheck  to check all external links for integrity
+	echo.  doctest    to run all doctests embedded in the documentation if enabled
+	goto end
+)
+
+if "%1" == "clean" (
+	for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+	del /q /s %BUILDDIR%\*
+	goto end
+)
+
+if "%1" == "html" (
+	%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+	goto end
+)
+
+if "%1" == "dirhtml" (
+	%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+	goto end
+)
+
+if "%1" == "singlehtml" (
+	%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+	goto end
+)
+
+if "%1" == "pickle" (
+	%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can process the pickle files.
+	goto end
+)
+
+if "%1" == "json" (
+	%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can process the JSON files.
+	goto end
+)
+
+if "%1" == "htmlhelp" (
+	%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+	goto end
+)
+
+if "%1" == "qthelp" (
+	%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+	echo.^> qcollectiongenerator %BUILDDIR%\qthelp\greenlet.qhcp
+	echo.To view the help file:
+	echo.^> assistant -collectionFile %BUILDDIR%\qthelp\greenlet.ghc
+	goto end
+)
+
+if "%1" == "devhelp" (
+	%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished.
+	goto end
+)
+
+if "%1" == "epub" (
+	%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The epub file is in %BUILDDIR%/epub.
+	goto end
+)
+
+if "%1" == "latex" (
+	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+	goto end
+)
+
+if "%1" == "text" (
+	%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The text files are in %BUILDDIR%/text.
+	goto end
+)
+
+if "%1" == "man" (
+	%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The manual pages are in %BUILDDIR%/man.
+	goto end
+)
+
+if "%1" == "texinfo" (
+	%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+	goto end
+)
+
+if "%1" == "gettext" (
+	%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+	goto end
+)
+
+if "%1" == "changes" (
+	%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.The overview file is in %BUILDDIR%/changes.
+	goto end
+)
+
+if "%1" == "linkcheck" (
+	%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+	goto end
+)
+
+if "%1" == "doctest" (
+	%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+	goto end
+)
+
+:end

+ 1723 - 0
desktop/core/ext-py/greenlet-0.4.12/greenlet.c

@@ -0,0 +1,1723 @@
+/* vim:set noet ts=8 sw=8 : */
+
+#define GREENLET_MODULE
+
+#include "greenlet.h"
+#include "structmember.h"
+
+
+/***********************************************************
+
+A PyGreenlet is a range of C stack addresses that must be
+saved and restored in such a way that the full range of the
+stack contains valid data when we switch to it.
+
+Stack layout for a greenlet:
+
+               |     ^^^       |
+               |  older data   |
+               |               |
+  stack_stop . |_______________|
+        .      |               |
+        .      | greenlet data |
+        .      |   in stack    |
+        .    * |_______________| . .  _____________  stack_copy + stack_saved
+        .      |               |     |             |
+        .      |     data      |     |greenlet data|
+        .      |   unrelated   |     |    saved    |
+        .      |      to       |     |   in heap   |
+ stack_start . |     this      | . . |_____________| stack_copy
+               |   greenlet    |
+               |               |
+               |  newer data   |
+               |     vvv       |
+
+
+Note that a greenlet's stack data is typically partly at its correct
+place in the stack, and partly saved away in the heap, but always in
+the above configuration: two blocks, the more recent one in the heap
+and the older one still in the stack (either block may be empty).
+
+Greenlets are chained: each points to the previous greenlet, which is
+the one that owns the data currently in the C stack above my
+stack_stop.  The currently running greenlet is the first element of
+this chain.  The main (initial) greenlet is the last one.  Greenlets
+whose stack is entirely in the heap can be skipped from the chain.
+
+The chain is not related to execution order, but only to the order
+in which bits of C stack happen to belong to greenlets at a particular
+point in time.
+
+The main greenlet doesn't have a stack_stop: it is responsible for the
+complete rest of the C stack, and we don't know where it begins.  We
+use (char*) -1, the largest possible address.
+
+States:
+  stack_stop == NULL && stack_start == NULL:  did not start yet
+  stack_stop != NULL && stack_start == NULL:  already finished
+  stack_stop != NULL && stack_start != NULL:  active
+
+The running greenlet's stack_start is undefined but not NULL.
+
+ ***********************************************************/
+
+/*** global state ***/
+
+/* In the presence of multithreading, this is a bit tricky:
+
+   - ts_current always store a reference to a greenlet, but it is
+     not really the current greenlet after a thread switch occurred.
+
+   - each *running* greenlet uses its run_info field to know which
+     thread it is attached to.  A greenlet can only run in the thread
+     where it was created.  This run_info is a ref to tstate->dict.
+
+   - the thread state dict is used to save and restore ts_current,
+     using the dictionary key 'ts_curkey'.
+*/
+
+/* Python <= 2.5 support */
+#if PY_MAJOR_VERSION < 3
+#ifndef Py_REFCNT
+#  define Py_REFCNT(ob) (((PyObject *) (ob))->ob_refcnt)
+#endif
+#ifndef Py_TYPE
+#  define Py_TYPE(ob)   (((PyObject *) (ob))->ob_type)
+#endif
+#ifndef PyVarObject_HEAD_INIT
+#  define PyVarObject_HEAD_INIT(type, size) \
+	PyObject_HEAD_INIT(type) size,
+#endif
+#endif
+
+#if PY_VERSION_HEX < 0x02060000
+#define PyLong_FromSsize_t PyInt_FromLong
+#endif
+
+#if PY_VERSION_HEX < 0x02050000
+typedef int Py_ssize_t;
+#endif
+
+extern PyTypeObject PyGreenlet_Type;
+
+/* Defines that customize greenlet module behaviour */
+#ifndef GREENLET_USE_GC
+#define GREENLET_USE_GC 1
+#endif
+
+#ifndef GREENLET_USE_TRACING
+#define GREENLET_USE_TRACING 1
+#endif
+
+/* Weak reference to the switching-to greenlet during the slp switch */
+static PyGreenlet* volatile ts_target = NULL;
+/* Strong reference to the switching from greenlet after the switch */
+static PyGreenlet* volatile ts_origin = NULL;
+/* Strong reference to the current greenlet in this thread state */
+static PyGreenlet* volatile ts_current = NULL;
+/* NULL if error, otherwise args tuple to pass around during slp switch */
+static PyObject* volatile ts_passaround_args = NULL;
+static PyObject* volatile ts_passaround_kwargs = NULL;
+
+/***********************************************************/
+/* Thread-aware routines, switching global variables when needed */
+
+#define STATE_OK    (ts_current->run_info == PyThreadState_GET()->dict \
+                     || !green_updatecurrent())
+
+static PyObject* ts_curkey;
+static PyObject* ts_delkey;
+#if GREENLET_USE_TRACING
+static PyObject* ts_tracekey;
+static PyObject* ts_event_switch;
+static PyObject* ts_event_throw;
+#endif
+static PyObject* PyExc_GreenletError;
+static PyObject* PyExc_GreenletExit;
+static PyObject* ts_empty_tuple;
+static PyObject* ts_empty_dict;
+
+#if GREENLET_USE_GC
+#define GREENLET_GC_FLAGS Py_TPFLAGS_HAVE_GC
+#define GREENLET_tp_alloc PyType_GenericAlloc
+#define GREENLET_tp_free PyObject_GC_Del
+#define GREENLET_tp_traverse green_traverse
+#define GREENLET_tp_clear green_clear
+#define GREENLET_tp_is_gc green_is_gc
+#else /* GREENLET_USE_GC */
+#define GREENLET_GC_FLAGS 0
+#define GREENLET_tp_alloc 0
+#define GREENLET_tp_free 0
+#define GREENLET_tp_traverse 0
+#define GREENLET_tp_clear 0
+#define GREENLET_tp_is_gc 0
+#endif /* !GREENLET_USE_GC */
+
+static PyGreenlet* green_create_main(void)
+{
+	PyGreenlet* gmain;
+	PyObject* dict = PyThreadState_GetDict();
+	if (dict == NULL) {
+		if (!PyErr_Occurred())
+			PyErr_NoMemory();
+		return NULL;
+	}
+
+	/* create the main greenlet for this thread */
+	gmain = (PyGreenlet*) PyType_GenericAlloc(&PyGreenlet_Type, 0);
+	if (gmain == NULL)
+		return NULL;
+	gmain->stack_start = (char*) 1;
+	gmain->stack_stop = (char*) -1;
+	gmain->run_info = dict;
+	Py_INCREF(dict);
+	return gmain;
+}
+
+static int green_updatecurrent(void)
+{
+	PyObject *exc, *val, *tb;
+	PyThreadState* tstate;
+	PyGreenlet* current;
+	PyGreenlet* previous;
+	PyObject* deleteme;
+
+green_updatecurrent_restart:
+	/* save current exception */
+	PyErr_Fetch(&exc, &val, &tb);
+
+	/* get ts_current from the active tstate */
+	tstate = PyThreadState_GET();
+	if (tstate->dict && (current =
+	    (PyGreenlet*) PyDict_GetItem(tstate->dict, ts_curkey))) {
+		/* found -- remove it, to avoid keeping a ref */
+		Py_INCREF(current);
+		PyDict_DelItem(tstate->dict, ts_curkey);
+	}
+	else {
+		/* first time we see this tstate */
+		current = green_create_main();
+		if (current == NULL) {
+			Py_XDECREF(exc);
+			Py_XDECREF(val);
+			Py_XDECREF(tb);
+			return -1;
+		}
+	}
+	assert(current->run_info == tstate->dict);
+
+green_updatecurrent_retry:
+	/* update ts_current as soon as possible, in case of nested switches */
+	Py_INCREF(current);
+	previous = ts_current;
+	ts_current = current;
+
+	/* save ts_current as the current greenlet of its own thread */
+	if (PyDict_SetItem(previous->run_info, ts_curkey, (PyObject*) previous)) {
+		Py_DECREF(previous);
+		Py_DECREF(current);
+		Py_XDECREF(exc);
+		Py_XDECREF(val);
+		Py_XDECREF(tb);
+		return -1;
+	}
+	Py_DECREF(previous);
+
+	/* green_dealloc() cannot delete greenlets from other threads, so
+	   it stores them in the thread dict; delete them now. */
+	deleteme = PyDict_GetItem(tstate->dict, ts_delkey);
+	if (deleteme != NULL) {
+		PyList_SetSlice(deleteme, 0, INT_MAX, NULL);
+	}
+
+	if (ts_current != current) {
+		/* some Python code executed above and there was a thread switch,
+		 * so ts_current points to some other thread again. We need to
+		 * delete ts_curkey (it's likely there) and retry. */
+		PyDict_DelItem(tstate->dict, ts_curkey);
+		goto green_updatecurrent_retry;
+	}
+
+	/* release an extra reference */
+	Py_DECREF(current);
+
+	/* restore current exception */
+	PyErr_Restore(exc, val, tb);
+
+	/* thread switch could happen during PyErr_Restore, in that
+	   case there's nothing to do except restart from scratch. */
+	if (ts_current->run_info != tstate->dict)
+		goto green_updatecurrent_restart;
+
+	return 0;
+}
+
+static PyObject* green_statedict(PyGreenlet* g)
+{
+	while (!PyGreenlet_STARTED(g)) {
+		g = g->parent;
+		if (g == NULL) {
+			/* garbage collected greenlet in chain */
+			return NULL;
+		}
+	}
+	return g->run_info;
+}
+
+/***********************************************************/
+
+/* Some functions must not be inlined:
+   * slp_restore_state, when inlined into slp_switch might cause
+     it to restore stack over its own local variables
+   * slp_save_state, when inlined would add its own local
+     variables to the saved stack, wasting space
+   * slp_switch, cannot be inlined for obvious reasons
+   * g_initialstub, when inlined would receive a pointer into its
+     own stack frame, leading to incomplete stack save/restore
+*/
+
+#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+#define GREENLET_NOINLINE_SUPPORTED
+#define GREENLET_NOINLINE(name) __attribute__((noinline)) name
+#elif defined(_MSC_VER) && (_MSC_VER >= 1300)
+#define GREENLET_NOINLINE_SUPPORTED
+#define GREENLET_NOINLINE(name) __declspec(noinline) name
+#endif
+
+#ifdef GREENLET_NOINLINE_SUPPORTED
+/* add forward declarations */
+static void GREENLET_NOINLINE(slp_restore_state)(void);
+static int GREENLET_NOINLINE(slp_save_state)(char*);
+#if !(defined(MS_WIN64) && defined(_M_X64))
+static int GREENLET_NOINLINE(slp_switch)(void);
+#endif
+static int GREENLET_NOINLINE(g_initialstub)(void*);
+#define GREENLET_NOINLINE_INIT() do {} while(0)
+#else
+/* force compiler to call functions via pointers */
+static void (*slp_restore_state)(void);
+static int (*slp_save_state)(char*);
+static int (*slp_switch)(void);
+static int (*g_initialstub)(void*);
+#define GREENLET_NOINLINE(name) cannot_inline_ ## name
+#define GREENLET_NOINLINE_INIT() do { \
+	slp_restore_state = GREENLET_NOINLINE(slp_restore_state); \
+	slp_save_state = GREENLET_NOINLINE(slp_save_state); \
+	slp_switch = GREENLET_NOINLINE(slp_switch); \
+	g_initialstub = GREENLET_NOINLINE(g_initialstub); \
+} while(0)
+#endif
+
+/*
+ * the following macros are spliced into the OS/compiler
+ * specific code, in order to simplify maintenance.
+ */
+
+#define SLP_SAVE_STATE(stackref, stsizediff)            \
+	stackref += STACK_MAGIC;                        \
+	if (slp_save_state((char*)stackref)) return -1; \
+	if (!PyGreenlet_ACTIVE(ts_target)) return 1;    \
+	stsizediff = ts_target->stack_start - (char*)stackref
+
+#define SLP_RESTORE_STATE()                             \
+	slp_restore_state()
+
+
+#define SLP_EVAL
+#define slp_switch GREENLET_NOINLINE(slp_switch)
+#include "slp_platformselect.h"
+#undef slp_switch
+
+#ifndef STACK_MAGIC
+#error "greenlet needs to be ported to this platform, or teached how to detect your compiler properly."
+#endif /* !STACK_MAGIC */
+
+#ifdef EXTERNAL_ASM
+/* CCP addition: Make these functions, to be called from assembler.
+ * The token include file for the given platform should enable the
+ * EXTERNAL_ASM define so that this is included.
+ */
+
+intptr_t slp_save_state_asm(intptr_t *ref) {
+	intptr_t diff;
+	SLP_SAVE_STATE(ref, diff);
+	return diff;
+}
+
+void slp_restore_state_asm(void) {
+	SLP_RESTORE_STATE();
+}
+
+extern int slp_switch(void);
+
+#endif
+
+/***********************************************************/
+
+static int g_save(PyGreenlet* g, char* stop)
+{
+	/* Save more of g's stack into the heap -- at least up to 'stop'
+
+	   g->stack_stop |________|
+	                 |        |
+	                 |    __ stop       . . . . .
+	                 |        |    ==>  .       .
+	                 |________|          _______
+	                 |        |         |       |
+	                 |        |         |       |
+	  g->stack_start |        |         |_______| g->stack_copy
+
+	 */
+	intptr_t sz1 = g->stack_saved;
+	intptr_t sz2 = stop - g->stack_start;
+	assert(g->stack_start != NULL);
+	if (sz2 > sz1) {
+		char* c = (char*)PyMem_Realloc(g->stack_copy, sz2);
+		if (!c) {
+			PyErr_NoMemory();
+			return -1;
+		}
+		memcpy(c+sz1, g->stack_start+sz1, sz2-sz1);
+		g->stack_copy = c;
+		g->stack_saved = sz2;
+	}
+	return 0;
+}
+
+static void GREENLET_NOINLINE(slp_restore_state)(void)
+{
+	PyGreenlet* g = ts_target;
+	PyGreenlet* owner = ts_current;
+
+#ifdef SLP_BEFORE_RESTORE_STATE
+	SLP_BEFORE_RESTORE_STATE();
+#endif
+
+	/* Restore the heap copy back into the C stack */
+	if (g->stack_saved != 0) {
+		memcpy(g->stack_start, g->stack_copy, g->stack_saved);
+		PyMem_Free(g->stack_copy);
+		g->stack_copy = NULL;
+		g->stack_saved = 0;
+	}
+	if (owner->stack_start == NULL)
+		owner = owner->stack_prev; /* greenlet is dying, skip it */
+	while (owner && owner->stack_stop <= g->stack_stop)
+		owner = owner->stack_prev; /* find greenlet with more stack */
+	g->stack_prev = owner;
+}
+
+static int GREENLET_NOINLINE(slp_save_state)(char* stackref)
+{
+	/* must free all the C stack up to target_stop */
+	char* target_stop = ts_target->stack_stop;
+	PyGreenlet* owner = ts_current;
+	assert(owner->stack_saved == 0);
+	if (owner->stack_start == NULL)
+		owner = owner->stack_prev;  /* not saved if dying */
+	else
+		owner->stack_start = stackref;
+
+#ifdef SLP_BEFORE_SAVE_STATE
+	SLP_BEFORE_SAVE_STATE();
+#endif
+
+	while (owner->stack_stop < target_stop) {
+		/* ts_current is entierely within the area to free */
+		if (g_save(owner, owner->stack_stop))
+			return -1;  /* XXX */
+		owner = owner->stack_prev;
+	}
+	if (owner != ts_target) {
+		if (g_save(owner, target_stop))
+			return -1;  /* XXX */
+	}
+	return 0;
+}
+
+static int g_switchstack(void)
+{
+	/* Perform a stack switch according to some global variables
+	   that must be set before:
+	   - ts_current: current greenlet (holds a reference)
+	   - ts_target: greenlet to switch to (weak reference)
+	   - ts_passaround_args: NULL if PyErr_Occurred(),
+	       else a tuple of args sent to ts_target (holds a reference)
+	   - ts_passaround_kwargs: switch kwargs (holds a reference)
+	   On return results are passed via global variables as well:
+	   - ts_origin: originating greenlet (holds a reference)
+	   - ts_current: current greenlet (holds a reference)
+	   - ts_passaround_args: NULL if PyErr_Occurred(),
+	       else a tuple of args sent to ts_current (holds a reference)
+	   - ts_passaround_kwargs: switch kwargs (holds a reference)
+	   It is very important that stack switch is 'atomic', i.e. no
+	   calls into other Python code allowed (except very few that
+	   are safe), because global variables are very fragile.
+	*/
+	int err;
+	{   /* save state */
+		PyGreenlet* current = ts_current;
+		PyThreadState* tstate = PyThreadState_GET();
+		current->recursion_depth = tstate->recursion_depth;
+		current->top_frame = tstate->frame;
+		current->exc_type = tstate->exc_type;
+		current->exc_value = tstate->exc_value;
+		current->exc_traceback = tstate->exc_traceback;
+	}
+	err = slp_switch();
+	if (err < 0) {   /* error */
+		PyGreenlet* current = ts_current;
+		current->top_frame = NULL;
+		current->exc_type = NULL;
+		current->exc_value = NULL;
+		current->exc_traceback = NULL;
+
+		assert(ts_origin == NULL);
+		ts_target = NULL;
+	}
+	else {
+		PyGreenlet* target = ts_target;
+		PyGreenlet* origin = ts_current;
+		PyThreadState* tstate = PyThreadState_GET();
+		tstate->recursion_depth = target->recursion_depth;
+		tstate->frame = target->top_frame;
+		target->top_frame = NULL;
+		tstate->exc_type = target->exc_type;
+		target->exc_type = NULL;
+		tstate->exc_value = target->exc_value;
+		target->exc_value = NULL;
+		tstate->exc_traceback = target->exc_traceback;
+		target->exc_traceback = NULL;
+
+		assert(ts_origin == NULL);
+		Py_INCREF(target);
+		ts_current = target;
+		ts_origin = origin;
+		ts_target = NULL;
+	}
+	return err;
+}
+
+#if GREENLET_USE_TRACING
+static int
+g_calltrace(PyObject* tracefunc, PyObject* event, PyGreenlet* origin, PyGreenlet* target)
+{
+	PyObject *retval;
+	PyObject *exc_type, *exc_val, *exc_tb;
+	PyThreadState *tstate;
+	PyErr_Fetch(&exc_type, &exc_val, &exc_tb);
+	tstate = PyThreadState_GET();
+	tstate->tracing++;
+	tstate->use_tracing = 0;
+	retval = PyObject_CallFunction(tracefunc, "O(OO)", event, origin, target);
+	tstate->tracing--;
+	tstate->use_tracing = (tstate->tracing <= 0 &&
+	                       ((tstate->c_tracefunc != NULL) ||
+	                        (tstate->c_profilefunc != NULL)));
+	if (retval == NULL) {
+		/* In case of exceptions trace function is removed */
+		if (PyDict_GetItem(tstate->dict, ts_tracekey))
+			PyDict_DelItem(tstate->dict, ts_tracekey);
+		Py_XDECREF(exc_type);
+		Py_XDECREF(exc_val);
+		Py_XDECREF(exc_tb);
+		return -1;
+	} else
+		Py_DECREF(retval);
+	PyErr_Restore(exc_type, exc_val, exc_tb);
+	return 0;
+}
+#endif
+
+static PyObject *
+g_switch(PyGreenlet* target, PyObject* args, PyObject* kwargs)
+{
+	/* _consumes_ a reference to the args tuple and kwargs dict,
+	   and return a new tuple reference */
+	int err = 0;
+	PyObject* run_info;
+
+	/* check ts_current */
+	if (!STATE_OK) {
+		Py_XDECREF(args);
+		Py_XDECREF(kwargs);
+		return NULL;
+	}
+	run_info = green_statedict(target);
+	if (run_info == NULL || run_info != ts_current->run_info) {
+		Py_XDECREF(args);
+		Py_XDECREF(kwargs);
+		PyErr_SetString(PyExc_GreenletError, run_info
+		                ? "cannot switch to a different thread"
+		                : "cannot switch to a garbage collected greenlet");
+		return NULL;
+	}
+
+	ts_passaround_args = args;
+	ts_passaround_kwargs = kwargs;
+
+	/* find the real target by ignoring dead greenlets,
+	   and if necessary starting a greenlet. */
+	while (target) {
+		if (PyGreenlet_ACTIVE(target)) {
+			ts_target = target;
+			err = g_switchstack();
+			break;
+		}
+		if (!PyGreenlet_STARTED(target)) {
+			void* dummymarker;
+			ts_target = target;
+			err = g_initialstub(&dummymarker);
+			if (err == 1) {
+				continue; /* retry the switch */
+			}
+			break;
+		}
+		target = target->parent;
+	}
+
+	/* For a very short time, immediately after the 'atomic'
+	   g_switchstack() call, global variables are in a known state.
+	   We need to save everything we need, before it is destroyed
+	   by calls into arbitrary Python code. */
+	args = ts_passaround_args;
+	ts_passaround_args = NULL;
+	kwargs = ts_passaround_kwargs;
+	ts_passaround_kwargs = NULL;
+	if (err < 0) {
+		/* Turn switch errors into switch throws */
+		assert(ts_origin == NULL);
+		Py_CLEAR(kwargs);
+		Py_CLEAR(args);
+	} else {
+		PyGreenlet *origin;
+#if GREENLET_USE_TRACING
+		PyGreenlet *current;
+		PyObject *tracefunc;
+#endif
+		origin = ts_origin;
+		ts_origin = NULL;
+#if GREENLET_USE_TRACING
+		current = ts_current;
+		if ((tracefunc = PyDict_GetItem(current->run_info, ts_tracekey)) != NULL) {
+			Py_INCREF(tracefunc);
+			if (g_calltrace(tracefunc, args ? ts_event_switch : ts_event_throw, origin, current) < 0) {
+				/* Turn trace errors into switch throws */
+				Py_CLEAR(kwargs);
+				Py_CLEAR(args);
+			}
+			Py_DECREF(tracefunc);
+		}
+#endif
+		Py_DECREF(origin);
+	}
+
+	/* We need to figure out what values to pass to the target greenlet
+	   based on the arguments that have been passed to greenlet.switch(). If
+	   switch() was just passed an arg tuple, then we'll just return that.
+	   If only keyword arguments were passed, then we'll pass the keyword
+	   argument dict. Otherwise, we'll create a tuple of (args, kwargs) and
+	   return both. */
+	if (kwargs == NULL)
+	{
+		return args;
+	}
+	else if (PyDict_Size(kwargs) == 0)
+	{
+		Py_DECREF(kwargs);
+		return args;
+	}
+	else if (PySequence_Length(args) == 0)
+	{
+		Py_DECREF(args);
+		return kwargs;
+	}
+	else
+	{
+		PyObject *tuple = PyTuple_New(2);
+		if (tuple == NULL) {
+			Py_DECREF(args);
+			Py_DECREF(kwargs);
+			return NULL;
+		}
+		PyTuple_SET_ITEM(tuple, 0, args);
+		PyTuple_SET_ITEM(tuple, 1, kwargs);
+		return tuple;
+	}
+}
+
+static PyObject *
+g_handle_exit(PyObject *result)
+{
+	if (result == NULL && PyErr_ExceptionMatches(PyExc_GreenletExit))
+	{
+		/* catch and ignore GreenletExit */
+		PyObject *exc, *val, *tb;
+		PyErr_Fetch(&exc, &val, &tb);
+		if (val == NULL)
+		{
+			Py_INCREF(Py_None);
+			val = Py_None;
+		}
+		result = val;
+		Py_DECREF(exc);
+		Py_XDECREF(tb);
+	}
+	if (result != NULL)
+	{
+		/* package the result into a 1-tuple */
+		PyObject *r = result;
+		result = PyTuple_New(1);
+		if (result)
+		{
+			PyTuple_SET_ITEM(result, 0, r);
+		}
+		else
+		{
+			Py_DECREF(r);
+		}
+	}
+	return result;
+}
+
+static int GREENLET_NOINLINE(g_initialstub)(void* mark)
+{
+	int err;
+	PyObject *o, *run;
+	PyObject *exc, *val, *tb;
+	PyObject *run_info;
+	PyGreenlet* self = ts_target;
+	PyObject* args = ts_passaround_args;
+	PyObject* kwargs = ts_passaround_kwargs;
+
+	/* save exception in case getattr clears it */
+	PyErr_Fetch(&exc, &val, &tb);
+	/* self.run is the object to call in the new greenlet */
+	run = PyObject_GetAttrString((PyObject*) self, "run");
+	if (run == NULL) {
+		Py_XDECREF(exc);
+		Py_XDECREF(val);
+		Py_XDECREF(tb);
+		return -1;
+	}
+	/* restore saved exception */
+	PyErr_Restore(exc, val, tb);
+
+	/* recheck the state in case getattr caused thread switches */
+	if (!STATE_OK) {
+		Py_DECREF(run);
+		return -1;
+	}
+
+	/* recheck run_info in case greenlet reparented anywhere above */
+	run_info = green_statedict(self);
+	if (run_info == NULL || run_info != ts_current->run_info) {
+		Py_DECREF(run);
+		PyErr_SetString(PyExc_GreenletError, run_info
+		                ? "cannot switch to a different thread"
+		                : "cannot switch to a garbage collected greenlet");
+		return -1;
+	}
+
+	/* by the time we got here another start could happen elsewhere,
+	 * that means it should now be a regular switch
+	 */
+	if (PyGreenlet_STARTED(self)) {
+		Py_DECREF(run);
+		ts_passaround_args = args;
+		ts_passaround_kwargs = kwargs;
+		return 1;
+	}
+
+	/* start the greenlet */
+	self->stack_start = NULL;
+	self->stack_stop = (char*) mark;
+	if (ts_current->stack_start == NULL) {
+		/* ts_current is dying */
+		self->stack_prev = ts_current->stack_prev;
+	}
+	else {
+		self->stack_prev = ts_current;
+	}
+	self->top_frame = NULL;
+	self->exc_type = NULL;
+	self->exc_value = NULL;
+	self->exc_traceback = NULL;
+	self->recursion_depth = PyThreadState_GET()->recursion_depth;
+
+	/* restore arguments in case they are clobbered */
+	ts_target = self;
+	ts_passaround_args = args;
+	ts_passaround_kwargs = kwargs;
+
+	/* perform the initial switch */
+	err = g_switchstack();
+
+	/* returns twice!
+	   The 1st time with err=1: we are in the new greenlet
+	   The 2nd time with err=0: back in the caller's greenlet
+	*/
+	if (err == 1) {
+		/* in the new greenlet */
+		PyGreenlet* origin;
+#if GREENLET_USE_TRACING
+		PyObject* tracefunc;
+#endif
+		PyObject* result;
+		PyGreenlet* parent;
+		self->stack_start = (char*) 1;  /* running */
+
+		/* grab origin while we still can */
+		origin = ts_origin;
+		ts_origin = NULL;
+
+		/* now use run_info to store the statedict */
+		o = self->run_info;
+		self->run_info = green_statedict(self->parent);
+		Py_INCREF(self->run_info);
+		Py_XDECREF(o);
+
+#if GREENLET_USE_TRACING
+		if ((tracefunc = PyDict_GetItem(self->run_info, ts_tracekey)) != NULL) {
+			Py_INCREF(tracefunc);
+			if (g_calltrace(tracefunc, args ? ts_event_switch : ts_event_throw, origin, self) < 0) {
+				/* Turn trace errors into switch throws */
+				Py_CLEAR(kwargs);
+				Py_CLEAR(args);
+			}
+			Py_DECREF(tracefunc);
+		}
+#endif
+		Py_DECREF(origin);
+
+		if (args == NULL) {
+			/* pending exception */
+			result = NULL;
+		} else {
+			/* call g.run(*args, **kwargs) */
+			result = PyEval_CallObjectWithKeywords(
+				run, args, kwargs);
+			Py_DECREF(args);
+			Py_XDECREF(kwargs);
+		}
+		Py_DECREF(run);
+		result = g_handle_exit(result);
+
+		/* jump back to parent */
+		self->stack_start = NULL;  /* dead */
+		for (parent = self->parent; parent != NULL; parent = parent->parent) {
+			result = g_switch(parent, result, NULL);
+			/* Return here means switch to parent failed,
+			 * in which case we throw *current* exception
+			 * to the next parent in chain.
+			 */
+			assert(result == NULL);
+		}
+		/* We ran out of parents, cannot continue */
+		PyErr_WriteUnraisable((PyObject *) self);
+		Py_FatalError("greenlets cannot continue");
+	}
+	/* back in the parent */
+	if (err < 0) {
+		/* start failed badly, restore greenlet state */
+		self->stack_start = NULL;
+		self->stack_stop = NULL;
+		self->stack_prev = NULL;
+	}
+	return err;
+}
+
+
+/***********************************************************/
+
+
+static PyObject* green_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+	PyObject* o = PyBaseObject_Type.tp_new(type, ts_empty_tuple, ts_empty_dict);
+	if (o != NULL) {
+		if (!STATE_OK) {
+			Py_DECREF(o);
+			return NULL;
+		}
+		Py_INCREF(ts_current);
+		((PyGreenlet*) o)->parent = ts_current;
+	}
+	return o;
+}
+
+static int green_setrun(PyGreenlet* self, PyObject* nrun, void* c);
+static int green_setparent(PyGreenlet* self, PyObject* nparent, void* c);
+
+static int green_init(PyGreenlet *self, PyObject *args, PyObject *kwargs)
+{
+	PyObject *run = NULL;
+	PyObject* nparent = NULL;
+	static char *kwlist[] = {"run", "parent", 0};
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO:green", kwlist,
+	                                 &run, &nparent))
+		return -1;
+
+	if (run != NULL) {
+		if (green_setrun(self, run, NULL))
+			return -1;
+	}
+	if (nparent != NULL && nparent != Py_None)
+		return green_setparent(self, nparent, NULL);
+	return 0;
+}
+
+static int kill_greenlet(PyGreenlet* self)
+{
+	/* Cannot raise an exception to kill the greenlet if
+	   it is not running in the same thread! */
+	if (self->run_info == PyThreadState_GET()->dict) {
+		/* The dying greenlet cannot be a parent of ts_current
+		   because the 'parent' field chain would hold a
+		   reference */
+		PyObject* result;
+		PyGreenlet* oldparent;
+		PyGreenlet* tmp;
+		if (!STATE_OK) {
+			return -1;
+		}
+		oldparent = self->parent;
+		self->parent = ts_current;
+		Py_INCREF(self->parent);
+		/* Send the greenlet a GreenletExit exception. */
+		PyErr_SetNone(PyExc_GreenletExit);
+		result = g_switch(self, NULL, NULL);
+		tmp = self->parent;
+		self->parent = oldparent;
+		Py_XDECREF(tmp);
+		if (result == NULL)
+			return -1;
+		Py_DECREF(result);
+		return 0;
+	}
+	else {
+		/* Not the same thread! Temporarily save the greenlet
+		   into its thread's ts_delkey list. */
+		PyObject* lst;
+		lst = PyDict_GetItem(self->run_info, ts_delkey);
+		if (lst == NULL) {
+			lst = PyList_New(0);
+			if (lst == NULL || PyDict_SetItem(self->run_info,
+			                                  ts_delkey, lst) < 0)
+				return -1;
+		}
+		if (PyList_Append(lst, (PyObject*) self) < 0)
+			return -1;
+		if (!STATE_OK)  /* to force ts_delkey to be reconsidered */
+			return -1;
+		return 0;
+	}
+}
+
+#if GREENLET_USE_GC
+static int
+green_traverse(PyGreenlet *self, visitproc visit, void *arg)
+{
+	/* We must only visit referenced objects, i.e. only objects
+	   Py_INCREF'ed by this greenlet (directly or indirectly):
+	   - stack_prev is not visited: holds previous stack pointer, but it's not referenced
+	   - frames are not visited: alive greenlets are not garbage collected anyway */
+	Py_VISIT((PyObject*)self->parent);
+	Py_VISIT(self->run_info);
+	Py_VISIT(self->exc_type);
+	Py_VISIT(self->exc_value);
+	Py_VISIT(self->exc_traceback);
+	Py_VISIT(self->dict);
+	return 0;
+}
+
+static int green_is_gc(PyGreenlet* self)
+{
+	/* Main greenlet can be garbage collected since it can only
+	   become unreachable if the underlying thread exited.
+	   Active greenlet cannot be garbage collected, however. */
+	if (PyGreenlet_MAIN(self) || !PyGreenlet_ACTIVE(self))
+		return 1;
+	return 0;
+}
+
+static int green_clear(PyGreenlet* self)
+{
+	/* Greenlet is only cleared if it is about to be collected.
+	   Since active greenlets are not garbage collectable, we can
+	   be sure that, even if they are deallocated during clear,
+	   nothing they reference is in unreachable or finalizers,
+	   so even if it switches we are relatively safe. */
+	Py_CLEAR(self->parent);
+	Py_CLEAR(self->run_info);
+	Py_CLEAR(self->exc_type);
+	Py_CLEAR(self->exc_value);
+	Py_CLEAR(self->exc_traceback);
+	Py_CLEAR(self->dict);
+	return 0;
+}
+#endif
+
+static void green_dealloc(PyGreenlet* self)
+{
+	PyObject *error_type, *error_value, *error_traceback;
+
+#if GREENLET_USE_GC
+	PyObject_GC_UnTrack(self);
+#endif
+
+	if (PyGreenlet_ACTIVE(self) && self->run_info != NULL && !PyGreenlet_MAIN(self)) {
+		/* Hacks hacks hacks copied from instance_dealloc() */
+		/* Temporarily resurrect the greenlet. */
+		assert(Py_REFCNT(self) == 0);
+		Py_REFCNT(self) = 1;
+		/* Save the current exception, if any. */
+		PyErr_Fetch(&error_type, &error_value, &error_traceback);
+		if (kill_greenlet(self) < 0) {
+			PyErr_WriteUnraisable((PyObject*) self);
+			/* XXX what else should we do? */
+		}
+		/* Check for no resurrection must be done while we keep
+		 * our internal reference, otherwise PyFile_WriteObject
+		 * causes recursion if using Py_INCREF/Py_DECREF
+		 */
+		if (Py_REFCNT(self) == 1 && PyGreenlet_ACTIVE(self)) {
+			/* Not resurrected, but still not dead!
+			   XXX what else should we do? we complain. */
+			PyObject* f = PySys_GetObject("stderr");
+			Py_INCREF(self); /* leak! */
+			if (f != NULL) {
+				PyFile_WriteString("GreenletExit did not kill ",
+				                   f);
+				PyFile_WriteObject((PyObject*) self, f, 0);
+				PyFile_WriteString("\n", f);
+			}
+		}
+		/* Restore the saved exception. */
+		PyErr_Restore(error_type, error_value, error_traceback);
+		/* Undo the temporary resurrection; can't use DECREF here,
+		 * it would cause a recursive call.
+		 */
+		assert(Py_REFCNT(self) > 0);
+		if (--Py_REFCNT(self) != 0) {
+			/* Resurrected! */
+			Py_ssize_t refcnt = Py_REFCNT(self);
+			_Py_NewReference((PyObject*) self);
+			Py_REFCNT(self) = refcnt;
+#if GREENLET_USE_GC
+			PyObject_GC_Track((PyObject *)self);
+#endif
+			_Py_DEC_REFTOTAL;
+#ifdef COUNT_ALLOCS
+			--Py_TYPE(self)->tp_frees;
+			--Py_TYPE(self)->tp_allocs;
+#endif /* COUNT_ALLOCS */
+			return;
+		}
+	}
+	if (self->weakreflist != NULL)
+		PyObject_ClearWeakRefs((PyObject *) self);
+	Py_CLEAR(self->parent);
+	Py_CLEAR(self->run_info);
+	Py_CLEAR(self->exc_type);
+	Py_CLEAR(self->exc_value);
+	Py_CLEAR(self->exc_traceback);
+	Py_CLEAR(self->dict);
+	Py_TYPE(self)->tp_free((PyObject*) self);
+}
+
+static PyObject* single_result(PyObject* results)
+{
+	if (results != NULL && PyTuple_Check(results) &&
+	    PyTuple_GET_SIZE(results) == 1) {
+		PyObject *result = PyTuple_GET_ITEM(results, 0);
+		Py_INCREF(result);
+		Py_DECREF(results);
+		return result;
+	}
+	else
+		return results;
+}
+
+static PyObject *
+throw_greenlet(PyGreenlet *self, PyObject *typ, PyObject *val, PyObject *tb)
+{
+	/* Note: _consumes_ a reference to typ, val, tb */
+	PyObject *result = NULL;
+	PyErr_Restore(typ, val, tb);
+	if (PyGreenlet_STARTED(self) && !PyGreenlet_ACTIVE(self))
+	{
+		/* dead greenlet: turn GreenletExit into a regular return */
+		result = g_handle_exit(result);
+	}
+	return single_result(g_switch(self, result, NULL));
+}
+
+PyDoc_STRVAR(green_switch_doc,
+"switch(*args, **kwargs)\n"
+"\n"
+"Switch execution to this greenlet.\n"
+"\n"
+"If this greenlet has never been run, then this greenlet\n"
+"will be switched to using the body of self.run(*args, **kwargs).\n"
+"\n"
+"If the greenlet is active (has been run, but was switch()'ed\n"
+"out before leaving its run function), then this greenlet will\n"
+"be resumed and the return value to its switch call will be\n"
+"None if no arguments are given, the given argument if one\n"
+"argument is given, or the args tuple and keyword args dict if\n"
+"multiple arguments are given.\n"
+"\n"
+"If the greenlet is dead, or is the current greenlet then this\n"
+"function will simply return the arguments using the same rules as\n"
+"above.\n");
+
+static PyObject* green_switch(
+	PyGreenlet* self,
+	PyObject* args,
+	PyObject* kwargs)
+{
+	Py_INCREF(args);
+	Py_XINCREF(kwargs);
+	return single_result(g_switch(self, args, kwargs));
+}
+
+/* Macros required to support Python < 2.6 for green_throw() */
+#ifndef PyExceptionClass_Check
+#  define PyExceptionClass_Check    PyClass_Check
+#endif
+#ifndef PyExceptionInstance_Check
+#  define PyExceptionInstance_Check PyInstance_Check
+#endif
+#ifndef PyExceptionInstance_Class
+#  define PyExceptionInstance_Class(x) \
+	((PyObject *) ((PyInstanceObject *)(x))->in_class)
+#endif
+
+PyDoc_STRVAR(green_throw_doc,
+"Switches execution to the greenlet ``g``, but immediately raises the\n"
+"given exception in ``g``.  If no argument is provided, the exception\n"
+"defaults to ``greenlet.GreenletExit``.  The normal exception\n"
+"propagation rules apply, as described above.  Note that calling this\n"
+"method is almost equivalent to the following::\n"
+"\n"
+"    def raiser():\n"
+"        raise typ, val, tb\n"
+"    g_raiser = greenlet(raiser, parent=g)\n"
+"    g_raiser.switch()\n"
+"\n"
+"except that this trick does not work for the\n"
+"``greenlet.GreenletExit`` exception, which would not propagate\n"
+"from ``g_raiser`` to ``g``.\n");
+
+static PyObject *
+green_throw(PyGreenlet *self, PyObject *args)
+{
+	PyObject *typ = PyExc_GreenletExit;
+	PyObject *val = NULL;
+	PyObject *tb = NULL;
+
+	if (!PyArg_ParseTuple(args, "|OOO:throw", &typ, &val, &tb))
+	{
+		return NULL;
+	}
+
+	/* First, check the traceback argument, replacing None, with NULL */
+	if (tb == Py_None)
+	{
+		tb = NULL;
+	}
+	else if (tb != NULL && !PyTraceBack_Check(tb))
+	{
+		PyErr_SetString(
+			PyExc_TypeError,
+			"throw() third argument must be a traceback object");
+		return NULL;
+	}
+
+	Py_INCREF(typ);
+	Py_XINCREF(val);
+	Py_XINCREF(tb);
+
+	if (PyExceptionClass_Check(typ))
+	{
+		PyErr_NormalizeException(&typ, &val, &tb);
+	}
+	else if (PyExceptionInstance_Check(typ))
+	{
+		/* Raising an instance. The value should be a dummy. */
+		if (val && val != Py_None)
+		{
+			PyErr_SetString(
+				PyExc_TypeError,
+				"instance exception may not have a separate value");
+			goto failed_throw;
+		}
+		else
+		{
+			/* Normalize to raise <class>, <instance> */
+			Py_XDECREF(val);
+			val = typ;
+			typ = PyExceptionInstance_Class(typ);
+			Py_INCREF(typ);
+		}
+	}
+	else
+	{
+		/* Not something you can raise. throw() fails. */
+		PyErr_Format(
+			PyExc_TypeError,
+			"exceptions must be classes, or instances, not %s",
+			Py_TYPE(typ)->tp_name);
+		goto failed_throw;
+	}
+
+	return throw_greenlet(self, typ, val, tb);
+
+failed_throw:
+	/* Didn't use our arguments, so restore their original refcounts */
+	Py_DECREF(typ);
+	Py_XDECREF(val);
+	Py_XDECREF(tb);
+	return NULL;
+}
+
+static int green_bool(PyGreenlet* self)
+{
+	return PyGreenlet_ACTIVE(self);
+}
+
+static PyObject* green_getdict(PyGreenlet* self, void* c)
+{
+	if (self->dict == NULL) {
+		self->dict = PyDict_New();
+		if (self->dict == NULL)
+			return NULL;
+	}
+	Py_INCREF(self->dict);
+	return self->dict;
+}
+
+static int green_setdict(PyGreenlet* self, PyObject* val, void* c)
+{
+	PyObject* tmp;
+
+	if (val == NULL) {
+		PyErr_SetString(PyExc_TypeError, "__dict__ may not be deleted");
+		return -1;
+	}
+	if (!PyDict_Check(val)) {
+		PyErr_SetString(PyExc_TypeError, "__dict__ must be a dictionary");
+		return -1;
+	}
+	tmp = self->dict;
+	Py_INCREF(val);
+	self->dict = val;
+	Py_XDECREF(tmp);
+	return 0;
+}
+
+static PyObject* green_getdead(PyGreenlet* self, void* c)
+{
+	if (PyGreenlet_ACTIVE(self) || !PyGreenlet_STARTED(self))
+		Py_RETURN_FALSE;
+	else
+		Py_RETURN_TRUE;
+}
+
+
+static PyObject* green_get_stack_saved(PyGreenlet* self, void* c)
+{
+	return PyLong_FromSsize_t(self->stack_saved);
+}
+
+
+static PyObject* green_getrun(PyGreenlet* self, void* c)
+{
+	if (PyGreenlet_STARTED(self) || self->run_info == NULL) {
+		PyErr_SetString(PyExc_AttributeError, "run");
+		return NULL;
+	}
+	Py_INCREF(self->run_info);
+	return self->run_info;
+}
+
+static int green_setrun(PyGreenlet* self, PyObject* nrun, void* c)
+{
+	PyObject* o;
+	if (PyGreenlet_STARTED(self)) {
+		PyErr_SetString(PyExc_AttributeError,
+		                "run cannot be set "
+		                "after the start of the greenlet");
+		return -1;
+	}
+	o = self->run_info;
+	self->run_info = nrun;
+	Py_XINCREF(nrun);
+	Py_XDECREF(o);
+	return 0;
+}
+
+static PyObject* green_getparent(PyGreenlet* self, void* c)
+{
+	PyObject* result = self->parent ? (PyObject*) self->parent : Py_None;
+	Py_INCREF(result);
+	return result;
+}
+
+static int green_setparent(PyGreenlet* self, PyObject* nparent, void* c)
+{
+	PyGreenlet* p;
+	PyObject* run_info = NULL;
+	if (nparent == NULL) {
+		PyErr_SetString(PyExc_AttributeError, "can't delete attribute");
+		return -1;
+	}
+	if (!PyGreenlet_Check(nparent)) {
+		PyErr_SetString(PyExc_TypeError, "parent must be a greenlet");
+		return -1;
+	}
+	for (p=(PyGreenlet*) nparent; p; p=p->parent) {
+		if (p == self) {
+			PyErr_SetString(PyExc_ValueError, "cyclic parent chain");
+			return -1;
+		}
+		run_info = PyGreenlet_ACTIVE(p) ? p->run_info : NULL;
+	}
+	if (run_info == NULL) {
+		PyErr_SetString(PyExc_ValueError, "parent must not be garbage collected");
+		return -1;
+	}
+	if (PyGreenlet_STARTED(self) && self->run_info != run_info) {
+		PyErr_SetString(PyExc_ValueError, "parent cannot be on a different thread");
+		return -1;
+	}
+	p = self->parent;
+	self->parent = (PyGreenlet*) nparent;
+	Py_INCREF(nparent);
+	Py_XDECREF(p);
+	return 0;
+}
+
+static PyObject* green_getframe(PyGreenlet* self, void* c)
+{
+	PyObject* result = self->top_frame ? (PyObject*) self->top_frame : Py_None;
+	Py_INCREF(result);
+	return result;
+}
+
+static PyObject* green_getstate(PyGreenlet* self)
+{
+	PyErr_Format(PyExc_TypeError,
+	             "cannot serialize '%s' object",
+	             Py_TYPE(self)->tp_name);
+	return NULL;
+}
+
+
+/*****************************************************************************
+ * C interface
+ *
+ * These are exported using the CObject API
+ */
+
+static PyGreenlet *
+PyGreenlet_GetCurrent(void)
+{
+	if (!STATE_OK) {
+		return NULL;
+	}
+	Py_INCREF(ts_current);
+	return ts_current;
+}
+
+static int
+PyGreenlet_SetParent(PyGreenlet *g, PyGreenlet *nparent)
+{
+	if (!PyGreenlet_Check(g)) {
+		PyErr_SetString(PyExc_TypeError, "parent must be a greenlet");
+		return -1;
+	}
+
+	return green_setparent((PyGreenlet*) g, (PyObject *) nparent, NULL);
+}
+
+static PyGreenlet *
+PyGreenlet_New(PyObject *run, PyGreenlet *parent)
+{
+	PyGreenlet* g = NULL;
+
+	g = (PyGreenlet *) PyType_GenericAlloc(&PyGreenlet_Type, 0);
+	if (g == NULL) {
+		return NULL;
+	}
+
+	if (run != NULL) {
+		Py_INCREF(run);
+		g->run_info = run;
+	}
+
+	if (parent != NULL) {
+		if (PyGreenlet_SetParent(g, parent)) {
+			Py_DECREF(g);
+			return NULL;
+		}
+	} else {
+		if ((g->parent = PyGreenlet_GetCurrent()) == NULL) {
+			Py_DECREF(g);
+			return NULL;
+		}
+	}
+
+	return g;
+}
+
+static PyObject *
+PyGreenlet_Switch(PyGreenlet *g, PyObject *args, PyObject *kwargs)
+{
+	PyGreenlet *self = (PyGreenlet *) g;
+
+	if (!PyGreenlet_Check(self)) {
+		PyErr_BadArgument();
+		return NULL;
+	}
+
+	if (args == NULL) {
+		args = Py_BuildValue("()");
+	}
+	else {
+		Py_INCREF(args);
+	}
+
+	if (kwargs != NULL && PyDict_Check(kwargs)) {
+		Py_INCREF(kwargs);
+	}
+	else {
+		kwargs = NULL;
+	}
+
+	return single_result(g_switch(self, args, kwargs));
+}
+
+static PyObject *
+PyGreenlet_Throw(PyGreenlet *self, PyObject *typ, PyObject *val, PyObject *tb)
+{
+	if (!PyGreenlet_Check(self)) {
+		PyErr_BadArgument();
+		return NULL;
+	}
+	Py_INCREF(typ);
+	Py_XINCREF(val);
+	Py_XINCREF(tb);
+	return throw_greenlet(self, typ, val, tb);
+}
+
+/** End C API ****************************************************************/
+
+static PyMethodDef green_methods[] = {
+	{"switch", (PyCFunction)green_switch,
+	 METH_VARARGS | METH_KEYWORDS, green_switch_doc},
+	{"throw",  (PyCFunction)green_throw,  METH_VARARGS, green_throw_doc},
+	{"__getstate__", (PyCFunction)green_getstate, METH_NOARGS, NULL},
+	{NULL,     NULL} /* sentinel */
+};
+
+static PyGetSetDef green_getsets[] = {
+	{"__dict__", (getter)green_getdict,
+	             (setter)green_setdict, /*XXX*/ NULL},
+	{"run",      (getter)green_getrun,
+	             (setter)green_setrun, /*XXX*/ NULL},
+	{"parent",   (getter)green_getparent,
+	             (setter)green_setparent, /*XXX*/ NULL},
+	{"gr_frame", (getter)green_getframe,
+	             NULL, /*XXX*/ NULL},
+	{"dead",     (getter)green_getdead,
+	             NULL, /*XXX*/ NULL},
+	{"_stack_saved", (getter)green_get_stack_saved,
+	             NULL, /*XXX*/ NULL},
+	{NULL}
+};
+
+static PyNumberMethods green_as_number = {
+	NULL,                /* nb_add */
+	NULL,                /* nb_subtract */
+	NULL,                /* nb_multiply */
+#if PY_MAJOR_VERSION < 3
+	NULL,                /* nb_divide */
+#endif
+	NULL,                /* nb_remainder */
+	NULL,                /* nb_divmod */
+	NULL,                /* nb_power */
+	NULL,                /* nb_negative */
+	NULL,                /* nb_positive */
+	NULL,                /* nb_absolute */
+	(inquiry)green_bool, /* nb_bool */
+};
+
+
+PyTypeObject PyGreenlet_Type = {
+	PyVarObject_HEAD_INIT(NULL, 0)
+	"greenlet.greenlet",                    /* tp_name */
+	sizeof(PyGreenlet),                     /* tp_basicsize */
+	0,                                      /* tp_itemsize */
+	/* methods */
+	(destructor)green_dealloc,              /* tp_dealloc */
+	0,                                      /* tp_print */
+	0,                                      /* tp_getattr */
+	0,                                      /* tp_setattr */
+	0,                                      /* tp_compare */
+	0,                                      /* tp_repr */
+	&green_as_number,                       /* tp_as _number*/
+	0,                                      /* tp_as _sequence*/
+	0,                                      /* tp_as _mapping*/
+	0,                                      /* tp_hash */
+	0,                                      /* tp_call */
+	0,                                      /* tp_str */
+	0,                                      /* tp_getattro */
+	0,                                      /* tp_setattro */
+	0,                                      /* tp_as_buffer*/
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | GREENLET_GC_FLAGS, /* tp_flags */
+	"greenlet(run=None, parent=None) -> greenlet\n\n"
+	"Creates a new greenlet object (without running it).\n\n"
+	" - *run* -- The callable to invoke.\n"
+	" - *parent* -- The parent greenlet. The default is the current "
+	"greenlet.",                            /* tp_doc */
+	(traverseproc)GREENLET_tp_traverse,     /* tp_traverse */
+	(inquiry)GREENLET_tp_clear,             /* tp_clear */
+	0,                                      /* tp_richcompare */
+	offsetof(PyGreenlet, weakreflist),      /* tp_weaklistoffset */
+	0,                                      /* tp_iter */
+	0,                                      /* tp_iternext */
+	green_methods,                          /* tp_methods */
+	0,                                      /* tp_members */
+	green_getsets,                          /* tp_getset */
+	0,                                      /* tp_base */
+	0,                                      /* tp_dict */
+	0,                                      /* tp_descr_get */
+	0,                                      /* tp_descr_set */
+	offsetof(PyGreenlet, dict),             /* tp_dictoffset */
+	(initproc)green_init,                   /* tp_init */
+	GREENLET_tp_alloc,                      /* tp_alloc */
+	green_new,                              /* tp_new */
+	GREENLET_tp_free,                       /* tp_free */
+	(inquiry)GREENLET_tp_is_gc,             /* tp_is_gc */
+};
+
+static PyObject* mod_getcurrent(PyObject* self)
+{
+	if (!STATE_OK)
+		return NULL;
+	Py_INCREF(ts_current);
+	return (PyObject*) ts_current;
+}
+
+#if GREENLET_USE_TRACING
+static PyObject* mod_settrace(PyObject* self, PyObject* args)
+{
+	int err;
+	PyObject* previous;
+	PyObject* tracefunc;
+	PyGreenlet* current;
+	if (!PyArg_ParseTuple(args, "O", &tracefunc))
+		return NULL;
+	if (!STATE_OK)
+		return NULL;
+	current = ts_current;
+	previous = PyDict_GetItem(current->run_info, ts_tracekey);
+	if (previous == NULL)
+		previous = Py_None;
+	Py_INCREF(previous);
+	if (tracefunc == Py_None)
+		err = previous != Py_None ? PyDict_DelItem(current->run_info, ts_tracekey) : 0;
+	else
+		err = PyDict_SetItem(current->run_info, ts_tracekey, tracefunc);
+	if (err < 0)
+		Py_CLEAR(previous);
+	return previous;
+}
+
+static PyObject* mod_gettrace(PyObject* self)
+{
+	PyObject* tracefunc;
+	if (!STATE_OK)
+		return NULL;
+	tracefunc = PyDict_GetItem(ts_current->run_info, ts_tracekey);
+	if (tracefunc == NULL)
+		tracefunc = Py_None;
+	Py_INCREF(tracefunc);
+	return tracefunc;
+}
+#endif
+
+static PyMethodDef GreenMethods[] = {
+	{"getcurrent", (PyCFunction)mod_getcurrent, METH_NOARGS, /*XXX*/ NULL},
+#if GREENLET_USE_TRACING
+	{"settrace", (PyCFunction)mod_settrace, METH_VARARGS, NULL},
+	{"gettrace", (PyCFunction)mod_gettrace, METH_NOARGS, NULL},
+#endif
+	{NULL,     NULL}        /* Sentinel */
+};
+
+static char* copy_on_greentype[] = {
+	"getcurrent",
+	"error",
+	"GreenletExit",
+#if GREENLET_USE_TRACING
+	"settrace",
+	"gettrace",
+#endif
+	NULL
+};
+
+#if PY_MAJOR_VERSION >= 3
+#define INITERROR return NULL
+
+static struct PyModuleDef greenlet_module_def = {
+	PyModuleDef_HEAD_INIT,
+	"greenlet",
+	NULL,
+	-1,
+	GreenMethods,
+};
+
+PyMODINIT_FUNC
+PyInit_greenlet(void)
+#else
+#define INITERROR return
+
+PyMODINIT_FUNC
+initgreenlet(void)
+#endif
+{
+	PyObject* m = NULL;
+	char** p = NULL;
+	PyObject *c_api_object;
+	static void *_PyGreenlet_API[PyGreenlet_API_pointers];
+
+	GREENLET_NOINLINE_INIT();
+
+#if PY_MAJOR_VERSION >= 3
+	m = PyModule_Create(&greenlet_module_def);
+#else
+	m = Py_InitModule("greenlet", GreenMethods);
+#endif
+	if (m == NULL)
+	{
+		INITERROR;
+	}
+
+	if (PyModule_AddStringConstant(m, "__version__", GREENLET_VERSION) < 0)
+	{
+		INITERROR;
+	}
+
+#if PY_MAJOR_VERSION >= 3
+	ts_curkey = PyUnicode_InternFromString("__greenlet_ts_curkey");
+	ts_delkey = PyUnicode_InternFromString("__greenlet_ts_delkey");
+#if GREENLET_USE_TRACING
+	ts_tracekey = PyUnicode_InternFromString("__greenlet_ts_tracekey");
+	ts_event_switch = PyUnicode_InternFromString("switch");
+	ts_event_throw = PyUnicode_InternFromString("throw");
+#endif
+#else
+	ts_curkey = PyString_InternFromString("__greenlet_ts_curkey");
+	ts_delkey = PyString_InternFromString("__greenlet_ts_delkey");
+#if GREENLET_USE_TRACING
+	ts_tracekey = PyString_InternFromString("__greenlet_ts_tracekey");
+	ts_event_switch = PyString_InternFromString("switch");
+	ts_event_throw = PyString_InternFromString("throw");
+#endif
+#endif
+	if (ts_curkey == NULL || ts_delkey == NULL)
+	{
+		INITERROR;
+	}
+	if (PyType_Ready(&PyGreenlet_Type) < 0)
+	{
+		INITERROR;
+	}
+	PyExc_GreenletError = PyErr_NewException("greenlet.error", NULL, NULL);
+	if (PyExc_GreenletError == NULL)
+	{
+		INITERROR;
+	}
+#if PY_MAJOR_VERSION >= 3 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 5)
+	PyExc_GreenletExit = PyErr_NewException("greenlet.GreenletExit",
+	                                        PyExc_BaseException, NULL);
+#else
+	PyExc_GreenletExit = PyErr_NewException("greenlet.GreenletExit",
+	                                        NULL, NULL);
+#endif
+	if (PyExc_GreenletExit == NULL)
+	{
+		INITERROR;
+	}
+
+	ts_empty_tuple = PyTuple_New(0);
+	if (ts_empty_tuple == NULL)
+	{
+		INITERROR;
+	}
+
+	ts_empty_dict = PyDict_New();
+	if (ts_empty_dict == NULL)
+	{
+		INITERROR;
+	}
+
+	ts_current = green_create_main();
+	if (ts_current == NULL)
+	{
+		INITERROR;
+	}
+
+	Py_INCREF(&PyGreenlet_Type);
+	PyModule_AddObject(m, "greenlet", (PyObject*) &PyGreenlet_Type);
+	Py_INCREF(PyExc_GreenletError);
+	PyModule_AddObject(m, "error", PyExc_GreenletError);
+	Py_INCREF(PyExc_GreenletExit);
+	PyModule_AddObject(m, "GreenletExit", PyExc_GreenletExit);
+	PyModule_AddObject(m, "GREENLET_USE_GC", PyBool_FromLong(GREENLET_USE_GC));
+	PyModule_AddObject(m, "GREENLET_USE_TRACING", PyBool_FromLong(GREENLET_USE_TRACING));
+
+	/* also publish module-level data as attributes of the greentype. */
+	for (p=copy_on_greentype; *p; p++) {
+		PyObject* o = PyObject_GetAttrString(m, *p);
+		if (!o) continue;
+		PyDict_SetItemString(PyGreenlet_Type.tp_dict, *p, o);
+		Py_DECREF(o);
+	}
+
+	/*
+	 * Expose C API
+	 */
+
+	/* types */
+	_PyGreenlet_API[PyGreenlet_Type_NUM] = (void *) &PyGreenlet_Type;
+
+	/* exceptions */
+	_PyGreenlet_API[PyExc_GreenletError_NUM] = (void *) PyExc_GreenletError;
+	_PyGreenlet_API[PyExc_GreenletExit_NUM] = (void *) PyExc_GreenletExit;
+
+	/* methods */
+	_PyGreenlet_API[PyGreenlet_New_NUM] = (void *) PyGreenlet_New;
+	_PyGreenlet_API[PyGreenlet_GetCurrent_NUM] =
+		(void *) PyGreenlet_GetCurrent;
+	_PyGreenlet_API[PyGreenlet_Throw_NUM] = (void *) PyGreenlet_Throw;
+	_PyGreenlet_API[PyGreenlet_Switch_NUM] = (void *) PyGreenlet_Switch;
+	_PyGreenlet_API[PyGreenlet_SetParent_NUM] =
+		(void *) PyGreenlet_SetParent;
+
+#ifdef GREENLET_USE_PYCAPSULE
+	c_api_object = PyCapsule_New((void *) _PyGreenlet_API, "greenlet._C_API", NULL);
+#else
+	c_api_object = PyCObject_FromVoidPtr((void *) _PyGreenlet_API, NULL);
+#endif
+	if (c_api_object != NULL)
+	{
+		PyModule_AddObject(m, "_C_API", c_api_object);
+	}
+
+#if PY_MAJOR_VERSION >= 3
+	return m;
+#endif
+}

+ 148 - 0
desktop/core/ext-py/greenlet-0.4.12/greenlet.h

@@ -0,0 +1,148 @@
+/* vim:set noet ts=8 sw=8 : */
+
+/* Greenlet object interface */
+
+#ifndef Py_GREENLETOBJECT_H
+#define Py_GREENLETOBJECT_H
+
+#include <Python.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GREENLET_VERSION "0.4.12"
+
+typedef struct _greenlet {
+	PyObject_HEAD
+	char* stack_start;
+	char* stack_stop;
+	char* stack_copy;
+	intptr_t stack_saved;
+	struct _greenlet* stack_prev;
+	struct _greenlet* parent;
+	PyObject* run_info;
+	struct _frame* top_frame;
+	int recursion_depth;
+	PyObject* weakreflist;
+	PyObject* exc_type;
+	PyObject* exc_value;
+	PyObject* exc_traceback;
+	PyObject* dict;
+} PyGreenlet;
+
+#define PyGreenlet_Check(op)      PyObject_TypeCheck(op, &PyGreenlet_Type)
+#define PyGreenlet_MAIN(op)       (((PyGreenlet*)(op))->stack_stop == (char*) -1)
+#define PyGreenlet_STARTED(op)    (((PyGreenlet*)(op))->stack_stop != NULL)
+#define PyGreenlet_ACTIVE(op)     (((PyGreenlet*)(op))->stack_start != NULL)
+#define PyGreenlet_GET_PARENT(op) (((PyGreenlet*)(op))->parent)
+
+#if (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 7) || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 1) || PY_MAJOR_VERSION > 3
+#define GREENLET_USE_PYCAPSULE
+#endif
+
+/* C API functions */
+
+/* Total number of symbols that are exported */
+#define PyGreenlet_API_pointers  8
+
+#define PyGreenlet_Type_NUM       0
+#define PyExc_GreenletError_NUM   1
+#define PyExc_GreenletExit_NUM    2
+
+#define PyGreenlet_New_NUM        3
+#define PyGreenlet_GetCurrent_NUM 4
+#define PyGreenlet_Throw_NUM      5
+#define PyGreenlet_Switch_NUM     6
+#define PyGreenlet_SetParent_NUM  7
+
+#ifndef GREENLET_MODULE
+/* This section is used by modules that uses the greenlet C API */
+static void **_PyGreenlet_API = NULL;
+
+#define PyGreenlet_Type (*(PyTypeObject *) _PyGreenlet_API[PyGreenlet_Type_NUM])
+
+#define PyExc_GreenletError \
+	((PyObject *) _PyGreenlet_API[PyExc_GreenletError_NUM])
+
+#define PyExc_GreenletExit \
+	((PyObject *) _PyGreenlet_API[PyExc_GreenletExit_NUM])
+
+/*
+ * PyGreenlet_New(PyObject *args)
+ *
+ * greenlet.greenlet(run, parent=None)
+ */
+#define PyGreenlet_New \
+	(* (PyGreenlet * (*)(PyObject *run, PyGreenlet *parent)) \
+	 _PyGreenlet_API[PyGreenlet_New_NUM])
+
+/*
+ * PyGreenlet_GetCurrent(void)
+ *
+ * greenlet.getcurrent()
+ */
+#define PyGreenlet_GetCurrent \
+	(* (PyGreenlet * (*)(void)) _PyGreenlet_API[PyGreenlet_GetCurrent_NUM])
+
+/*
+ * PyGreenlet_Throw(
+ *         PyGreenlet *greenlet,
+ *         PyObject *typ,
+ *         PyObject *val,
+ *         PyObject *tb)
+ *
+ * g.throw(...)
+ */
+#define PyGreenlet_Throw \
+	(* (PyObject * (*) \
+	    (PyGreenlet *self, PyObject *typ, PyObject *val, PyObject *tb)) \
+	 _PyGreenlet_API[PyGreenlet_Throw_NUM])
+
+/*
+ * PyGreenlet_Switch(PyGreenlet *greenlet, PyObject *args)
+ *
+ * g.switch(*args, **kwargs)
+ */
+#define PyGreenlet_Switch \
+	(* (PyObject * (*)(PyGreenlet *greenlet, PyObject *args, PyObject *kwargs)) \
+	 _PyGreenlet_API[PyGreenlet_Switch_NUM])
+
+/*
+ * PyGreenlet_SetParent(PyObject *greenlet, PyObject *new_parent)
+ *
+ * g.parent = new_parent
+ */
+#define PyGreenlet_SetParent \
+	(* (int (*)(PyGreenlet *greenlet, PyGreenlet *nparent)) \
+	 _PyGreenlet_API[PyGreenlet_SetParent_NUM])
+
+/* Macro that imports greenlet and initializes C API */
+#ifdef GREENLET_USE_PYCAPSULE
+#define PyGreenlet_Import() \
+{ \
+	_PyGreenlet_API = (void**)PyCapsule_Import("greenlet._C_API", 0); \
+}
+#else
+#define PyGreenlet_Import() \
+{ \
+	PyObject *module = PyImport_ImportModule("greenlet"); \
+	if (module != NULL) { \
+		PyObject *c_api_object = PyObject_GetAttrString( \
+			module, "_C_API"); \
+		if (c_api_object != NULL && PyCObject_Check(c_api_object)) { \
+			_PyGreenlet_API = \
+				(void **) PyCObject_AsVoidPtr(c_api_object); \
+			Py_DECREF(c_api_object); \
+		} \
+		Py_DECREF(module); \
+	} \
+}
+#endif
+
+#endif /* GREENLET_MODULE */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_GREENLETOBJECT_H */

+ 19 - 0
desktop/core/ext-py/greenlet-0.4.12/make-manylinux

@@ -0,0 +1,19 @@
+#!/bin/bash
+set -e
+export PYTHONUNBUFFERED=1
+export PYTHONDONTWRITEBYTECODE=1
+
+if [ -d /greenlet -a -d /opt/python ]; then
+    # Running inside docker
+    cd /greenlet
+    rm -rf wheelhouse
+    for variant in /opt/python/*; do
+        rm -rf dist build *.egg-info
+        $variant/bin/python setup.py clean --all bdist_wheel
+        auditwheel repair dist/*.whl
+    done
+    rm -rf dist build *.egg-info
+    exit 0
+fi
+
+docker run --rm -ti -v "$(pwd):/greenlet:Z" quay.io/pypa/manylinux1_x86_64 /greenlet/$(basename $0)

+ 50 - 0
desktop/core/ext-py/greenlet-0.4.12/make-win-release

@@ -0,0 +1,50 @@
+#! /usr/bin/env python
+
+import sys, os, subprocess, re
+
+common_dist = ("bdist_wheel", "bdist_egg", "test")
+pyver2dist = {
+    "Python26": common_dist,
+    "Python26x64": common_dist,
+    "Python27": common_dist,
+    "Python27x64": common_dist,
+    "Python33": common_dist,
+    "Python33x64": common_dist,
+    "Python34": common_dist,
+    "Python34x64": common_dist,
+    "Python35": common_dist,
+    "Python35x64": common_dist,
+}
+
+
+def system(cmd):
+    sys.stdout.write("====> Running %s\n" % cmd)
+
+    popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
+    nl = True
+    while 1:
+        char = popen.stdout.read(1)
+        if not char:
+            break
+        if nl:
+            sys.stdout.write("    ")
+        sys.stdout.write(char)
+        sys.stdout.flush()
+        nl = char == "\n"
+
+    st = popen.wait()
+    if st != 0:
+        sys.exit("Error: command %r failed" % cmd)
+    sys.stdout.write("\n")
+
+
+def main():
+    here = os.path.dirname(os.path.dirname(sys.executable))
+    for pyver, dists in sorted(pyver2dist.items()):
+        exe = os.path.join(here, pyver, "python.exe")
+        for d in dists:
+            cmd = "%s setup.py -q %s" % (exe, d)
+            system(cmd)
+
+if __name__ == "__main__":
+    main()

+ 60 - 0
desktop/core/ext-py/greenlet-0.4.12/my_build_ext.py

@@ -0,0 +1,60 @@
+# this code has been taken from gevent's setup.py file. it provides a
+# build_ext command that puts .so/.pyd files in-place (like "setup.py
+# build_ext -i"). it uses symlinks if possible and will rebuild when
+# changing the python version (unlike "setup.py build_ext -i")
+
+import sys, os, shutil
+
+from distutils.command.build_ext import build_ext as _build_ext
+
+
+def symlink_or_copy(src, dst):
+    if hasattr(os, 'symlink'):
+        try:
+            os.symlink(src, dst)
+            return
+        except OSError:  # symbolic link privilege not held??
+            pass
+        except NotImplementedError:  # running on XP/'CreateSymbolicLinkW not found'
+            pass
+
+    shutil.copyfile(src, dst)
+
+
+class build_ext(_build_ext):
+    """Command for building extensions
+
+    Prepends library directory to sys.path on normal builds (for tests).
+    Otherwise it forces a non-inplace build and symlinks libraries instead.
+    """
+
+    def initialize_options(self):
+        self.my_inplace = None
+        _build_ext.initialize_options(self)
+
+    def finalize_options(self):
+        if self.my_inplace is None:
+            self.my_inplace = self.inplace
+            self.inplace = 0
+        _build_ext.finalize_options(self)
+
+    def build_extension(self, ext):
+        _build_ext.build_extension(self, ext)
+        if not self.my_inplace:
+            build_lib = os.path.abspath(self.build_lib)
+            if build_lib not in sys.path:
+                sys.path.insert(0, build_lib)
+            return
+        filename = self.get_ext_filename(ext.name)
+        build_path = os.path.abspath(os.path.join(self.build_lib, filename))
+        src_path = os.path.abspath(filename)
+        if build_path != src_path:
+            try:
+                os.unlink(src_path)
+            except OSError:
+                pass
+
+            if self.verbose:
+                sys.stderr.write('Linking %s to %s\n' % (build_path, src_path))
+
+            symlink_or_copy(build_path, src_path)

+ 69 - 0
desktop/core/ext-py/greenlet-0.4.12/platform/switch_aarch64_gcc.h

@@ -0,0 +1,69 @@
+/*
+ * this is the internal transfer function.
+ *
+ * HISTORY
+ * 07-Sep-16 Add clang support using x register naming. Fredrik Fornwall
+ * 13-Apr-13 Add support for strange GCC caller-save decisions
+ * 08-Apr-13 File creation. Michael Matz
+ *
+ * NOTES
+ *
+ * Simply save all callee saved registers
+ *
+ */
+
+#define STACK_REFPLUS 1
+
+#ifdef SLP_EVAL
+#define STACK_MAGIC 0
+#define REGS_TO_SAVE "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", \
+                     "x27", "x28", "x30" /* aka lr */, \
+                     "v8", "v9", "v10", "v11", \
+                     "v12", "v13", "v14", "v15"
+
+static int
+slp_switch(void)
+{
+	int err;
+	void *fp;
+        register long *stackref, stsizediff;
+        __asm__ volatile ("" : : : REGS_TO_SAVE);
+	__asm__ volatile ("str x29, %0" : "=m"(fp) : : );
+        __asm__ ("mov %0, sp" : "=r" (stackref));
+        {
+                SLP_SAVE_STATE(stackref, stsizediff);
+                __asm__ volatile (
+                    "add sp,sp,%0\n"
+                    "add x29,x29,%0\n"
+                    :
+                    : "r" (stsizediff)
+                    );
+		SLP_RESTORE_STATE();
+		/* SLP_SAVE_STATE macro contains some return statements
+		   (of -1 and 1).  It falls through only when
+		   the return value of slp_save_state() is zero, which
+		   is placed in x0.
+		   In that case we (slp_switch) also want to return zero
+		   (also in x0 of course).
+		   Now, some GCC versions (seen with 4.8) think it's a
+		   good idea to save/restore x0 around the call to
+		   slp_restore_state(), instead of simply zeroing it
+		   at the return below.  But slp_restore_state
+		   writes random values to the stack slot used for this
+		   save/restore (from when it once was saved above in
+		   SLP_SAVE_STATE, when it was still uninitialized), so
+		   "restoring" that precious zero actually makes us
+		   return random values.  There are some ways to make
+		   GCC not use that zero value in the normal return path
+		   (e.g. making err volatile, but that costs a little
+		   stack space), and the simplest is to call a function
+		   that returns an unknown value (which happens to be zero),
+		   so the saved/restored value is unused.  */
+           __asm__ volatile ("mov %0, #0" : "=r" (err));
+        }
+        __asm__ volatile ("ldr x29, %0" : : "m" (fp) :);
+        __asm__ volatile ("" : : : REGS_TO_SAVE);
+        return err;
+}
+
+#endif

+ 84 - 0
desktop/core/ext-py/greenlet-0.4.12/platform/switch_amd64_unix.h

@@ -0,0 +1,84 @@
+/*
+ * this is the internal transfer function.
+ *
+ * HISTORY
+ * 3-May-13   Ralf Schmitt  <ralf@systemexit.de>
+ *     Add support for strange GCC caller-save decisions
+ *     (ported from switch_aarch64_gcc.h)
+ * 18-Aug-11  Alexey Borzenkov  <snaury@gmail.com>
+ *      Correctly save rbp, csr and cw
+ * 01-Apr-04  Hye-Shik Chang    <perky@FreeBSD.org>
+ *      Ported from i386 to amd64.
+ * 24-Nov-02  Christian Tismer  <tismer@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@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@GMD.DE>
+ *      slightly changed framework for spark
+ * 31-Avr-02  Armin Rigo         <arigo@ulb.ac.be>
+ *      Added ebx, esi and edi register-saves.
+ * 01-Mar-02  Samual M. Rushing  <rushing@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 "r12", "r13", "r14", "r15"
+
+static int
+slp_switch(void)
+{
+    int err;
+    void* rbp;
+    void* rbx;
+    unsigned int csr;
+    unsigned short cw;
+    register long *stackref, stsizediff;
+    __asm__ volatile ("" : : : REGS_TO_SAVE);
+    __asm__ volatile ("fstcw %0" : "=m" (cw));
+    __asm__ volatile ("stmxcsr %0" : "=m" (csr));
+    __asm__ volatile ("movq %%rbp, %0" : "=m" (rbp));
+    __asm__ volatile ("movq %%rbx, %0" : "=m" (rbx));
+    __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();
+        __asm__ volatile ("xorq %%rax, %%rax" : "=a" (err));
+    }
+    __asm__ volatile ("movq %0, %%rbx" : : "m" (rbx));
+    __asm__ volatile ("movq %0, %%rbp" : : "m" (rbp));
+    __asm__ volatile ("ldmxcsr %0" : : "m" (csr));
+    __asm__ volatile ("fldcw %0" : : "m" (cw));
+    __asm__ volatile ("" : : : REGS_TO_SAVE);
+    return err;
+}
+
+#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.
+ */

+ 79 - 0
desktop/core/ext-py/greenlet-0.4.12/platform/switch_arm32_gcc.h

@@ -0,0 +1,79 @@
+/*
+ * this is the internal transfer function.
+ *
+ * HISTORY
+ * 14-Aug-06 File creation. Ported from Arm Thumb. Sylvain Baro
+ *  3-Sep-06 Commented out saving of r1-r3 (r4 already commented out) as I
+ *           read that these do not need to be saved.  Also added notes and
+ *           errors related to the frame pointer. Richard Tew.
+ *
+ * NOTES
+ *
+ *   It is not possible to detect if fp is used or not, so the supplied
+ *   switch function needs to support it, so that you can remove it if
+ *   it does not apply to you.
+ *
+ * POSSIBLE ERRORS
+ *
+ *   "fp cannot be used in asm here"
+ *
+ *   - Try commenting out "fp" in REGS_TO_SAVE.
+ *
+ */
+
+#define STACK_REFPLUS 1
+
+#ifdef SLP_EVAL
+#define STACK_MAGIC 0
+#define REG_SP "sp"
+#define REG_SPSP "sp,sp"
+#ifdef __thumb__
+#define REG_FP "r7"
+#define REG_FPFP "r7,r7"
+#define REGS_TO_SAVE_GENERAL "r4", "r5", "r6", "r8", "r9", "r10", "r11", "lr"
+#else
+#define REG_FP "fp"
+#define REG_FPFP "fp,fp"
+#define REGS_TO_SAVE_GENERAL "r4", "r5", "r6", "r7", "r8", "r9", "r10", "lr"
+#endif
+#if defined(__SOFTFP__)
+#define REGS_TO_SAVE REGS_TO_SAVE_GENERAL
+#elif defined(__VFP_FP__)
+#define REGS_TO_SAVE REGS_TO_SAVE_GENERAL, "d8", "d9", "d10", "d11", \
+                                           "d12", "d13", "d14", "d15"
+#elif defined(__MAVERICK__)
+#define REGS_TO_SAVE REGS_TO_SAVE_GENERAL, "mvf4", "mvf5", "mvf6", "mvf7", \
+                                           "mvf8", "mvf9", "mvf10", "mvf11", \
+                                           "mvf12", "mvf13", "mvf14", "mvf15"
+#else
+#define REGS_TO_SAVE REGS_TO_SAVE_GENERAL, "f4", "f5", "f6", "f7"
+#endif
+
+static int
+#ifdef __GNUC__
+__attribute__((optimize("no-omit-frame-pointer")))
+#endif
+slp_switch(void)
+{
+        void *fp;
+        register int *stackref, stsizediff;
+        int result;
+        __asm__ volatile ("" : : : REGS_TO_SAVE);
+        __asm__ volatile ("mov r0," REG_FP "\n\tstr r0,%0" : "=m" (fp) : : "r0");
+        __asm__ ("mov %0," REG_SP : "=r" (stackref));
+        {
+                SLP_SAVE_STATE(stackref, stsizediff);
+                __asm__ volatile (
+                    "add " REG_SPSP ",%0\n"
+                    "add " REG_FPFP ",%0\n"
+                    :
+                    : "r" (stsizediff)
+                    );
+                SLP_RESTORE_STATE();
+        }
+        __asm__ volatile ("ldr r0,%1\n\tmov " REG_FP ",r0\n\tmov %0, #0" : "=r" (result) : "m" (fp) : "r0");
+        __asm__ volatile ("" : : : REGS_TO_SAVE);
+        return result;
+}
+
+#endif

+ 67 - 0
desktop/core/ext-py/greenlet-0.4.12/platform/switch_arm32_ios.h

@@ -0,0 +1,67 @@
+/*
+ * this is the internal transfer function.
+ *
+ * HISTORY
+ * 31-May-15 iOS support. Ported from arm32. Proton <feisuzhu@163.com>
+ *
+ * NOTES
+ *
+ *   It is not possible to detect if fp is used or not, so the supplied
+ *   switch function needs to support it, so that you can remove it if
+ *   it does not apply to you.
+ *
+ * POSSIBLE ERRORS
+ *
+ *   "fp cannot be used in asm here"
+ *
+ *   - Try commenting out "fp" in REGS_TO_SAVE.
+ *
+ */
+
+#define STACK_REFPLUS 1
+
+#ifdef SLP_EVAL
+
+#define STACK_MAGIC 0
+#define REG_SP "sp"
+#define REG_SPSP "sp,sp"
+#define REG_FP "r7"
+#define REG_FPFP "r7,r7"
+#define REGS_TO_SAVE_GENERAL "r4", "r5", "r6", "r8", "r10", "r11", "lr"
+#define REGS_TO_SAVE REGS_TO_SAVE_GENERAL, "d8", "d9", "d10", "d11", \
+                                           "d12", "d13", "d14", "d15"
+
+static int
+#ifdef __GNUC__
+__attribute__((optimize("no-omit-frame-pointer")))
+#endif
+slp_switch(void)
+{
+        void *fp;
+        register int *stackref, stsizediff, result;
+        __asm__ volatile ("" : : : REGS_TO_SAVE);
+        __asm__ volatile ("str " REG_FP ",%0" : "=m" (fp));
+        __asm__ ("mov %0," REG_SP : "=r" (stackref));
+        {
+                SLP_SAVE_STATE(stackref, stsizediff);
+                __asm__ volatile (
+                    "add " REG_SPSP ",%0\n"
+                    "add " REG_FPFP ",%0\n"
+                    :
+                    : "r" (stsizediff)
+                    : REGS_TO_SAVE /* Clobber registers, force compiler to
+                                    * recalculate address of void *fp from REG_SP or REG_FP */
+                );
+                SLP_RESTORE_STATE();
+        }
+        __asm__ volatile (
+            "ldr " REG_FP ", %1\n\t"
+            "mov %0, #0"
+            : "=r" (result)
+            : "m" (fp)
+            : REGS_TO_SAVE /* Force compiler to restore saved registers after this */
+        );
+        return result;
+}
+
+#endif

+ 38 - 0
desktop/core/ext-py/greenlet-0.4.12/platform/switch_m68k_gcc.h

@@ -0,0 +1,38 @@
+/*
+ * this is the internal transfer function.
+ *
+ * HISTORY
+ * 2014-01-06  Andreas Schwab  <schwab@linux-m68k.org>
+ *      File created.
+ */
+
+#ifdef SLP_EVAL
+
+#define STACK_MAGIC 0
+
+#define REGS_TO_SAVE "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
+		     "%a2", "%a3", "%a4"
+
+static int
+slp_switch(void)
+{
+  int err;
+  int *stackref, stsizediff;
+  void *fp, *a5;
+  __asm__ volatile ("" : : : REGS_TO_SAVE);
+  __asm__ volatile ("move.l %%fp, %0" : "=m"(fp));
+  __asm__ volatile ("move.l %%a5, %0" : "=m"(a5));
+  __asm__ ("move.l %%sp, %0" : "=r"(stackref));
+  {
+    SLP_SAVE_STATE(stackref, stsizediff);
+    __asm__ volatile ("add.l %0, %%sp; add.l %0, %%fp" : : "r"(stsizediff));
+    SLP_RESTORE_STATE();
+    __asm__ volatile ("clr.l %0" : "=g" (err));
+  }
+  __asm__ volatile ("move.l %0, %%a5" : : "m"(a5));
+  __asm__ volatile ("move.l %0, %%fp" : : "m"(fp));
+  __asm__ volatile ("" : : : REGS_TO_SAVE);
+  return err;
+}
+
+#endif

+ 64 - 0
desktop/core/ext-py/greenlet-0.4.12/platform/switch_mips_unix.h

@@ -0,0 +1,64 @@
+/*
+ * this is the internal transfer function.
+ *
+ * HISTORY
+ * 20-Sep-14 Matt Madison <madison@bliss-m.org>
+ *      Re-code the saving of the gp register for MIPS64.
+ * 05-Jan-08 Thiemo Seufer  <ths@debian.org>
+ *      Ported from ppc.
+ */
+
+#define STACK_REFPLUS 1
+
+#ifdef SLP_EVAL
+
+#define STACK_MAGIC 0
+
+#define REGS_TO_SAVE "$16", "$17", "$18", "$19", "$20", "$21", "$22", \
+       "$23", "$30"
+static int
+slp_switch(void)
+{
+    register int err;
+    register int *stackref, stsizediff;
+#ifdef __mips64
+    uint64_t gpsave;
+#endif
+    __asm__ __volatile__ ("" : : : REGS_TO_SAVE);
+#ifdef __mips64
+    __asm__ __volatile__ ("sd $28,%0" : "=m" (gpsave) : : );
+#endif
+    __asm__ ("move %0, $29" : "=r" (stackref) : );
+    {
+        SLP_SAVE_STATE(stackref, stsizediff);
+        __asm__ __volatile__ (
+#ifdef __mips64
+            "daddu $29, %0\n"
+#else
+            "addu $29, %0\n"
+#endif
+            : /* no outputs */
+            : "r" (stsizediff)
+            );
+        SLP_RESTORE_STATE();
+    }
+#ifdef __mips64
+    __asm__ __volatile__ ("ld $28,%0" : : "m" (gpsave) : );
+#endif
+    __asm__ __volatile__ ("" : : : REGS_TO_SAVE);
+    __asm__ __volatile__ ("move %0, $0" : "=r" (err));
+    return err;
+}
+
+#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.
+ */

+ 90 - 0
desktop/core/ext-py/greenlet-0.4.12/platform/switch_ppc64_linux.h

@@ -0,0 +1,90 @@
+/*
+ * this is the internal transfer function.
+ *
+ * HISTORY
+ * 10-Dec-13  Ulrich Weigand  <uweigand@de.ibm.com>
+ *	Support ELFv2 ABI.  Save float/vector registers.
+ * 09-Mar-12 Michael Ellerman <michael@ellerman.id.au>
+ *      64-bit implementation, copied from 32-bit.
+ * 07-Sep-05 (py-dev mailing list discussion)
+ *      removed 'r31' from the register-saved.  !!!! WARNING !!!!
+ *      It means that this file can no longer be compiled statically!
+ *      It is now only suitable as part of a dynamic library!
+ * 14-Jan-04  Bob Ippolito <bob@redivi.com>
+ *      added cr2-cr4 to the registers to be saved.
+ *      Open questions: Should we save FP registers?
+ *      What about vector registers?
+ *      Differences between darwin and unix?
+ * 24-Nov-02  Christian Tismer  <tismer@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.
+ * 04-Oct-02  Gustavo Niemeyer <niemeyer@conectiva.com>
+ *      Ported from MacOS version.
+ * 17-Sep-02  Christian Tismer  <tismer@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@GMD.DE>
+ *      slightly changed framework for sparc
+ * 29-Jun-02  Christian Tismer  <tismer@tismer.com>
+ *      Added register 13-29, 31 saves. The same way as
+ *      Armin Rigo did for the x86_unix version.
+ *      This seems to be now fully functional!
+ * 04-Mar-02  Hye-Shik Chang  <perky@fallin.lv>
+ *      Ported from i386.
+ * 31-Jul-12  Trevor Bowen    <trevorbowen@gmail.com>
+ *      Changed memory constraints to register only.
+ */
+
+#define STACK_REFPLUS 1
+
+#ifdef SLP_EVAL
+
+#if _CALL_ELF == 2
+#define STACK_MAGIC 4
+#else
+#define STACK_MAGIC 6
+#endif
+
+#if defined(__ALTIVEC__)
+#define ALTIVEC_REGS \
+       "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", \
+       "v28", "v29", "v30", "v31",
+#else
+#define ALTIVEC_REGS
+#endif
+
+#define REGS_TO_SAVE "r2", "r14", "r15", "r16", "r17", "r18", "r19", "r20", \
+       "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r31", \
+       "fr14", "fr15", "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", \
+       "fr22", "fr23", "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", \
+       "fr30", "fr31", \
+       ALTIVEC_REGS \
+       "cr2", "cr3", "cr4"
+
+static int
+slp_switch(void)
+{
+    register int err;
+    register long *stackref, stsizediff;
+    __asm__ volatile ("" : : : REGS_TO_SAVE);
+    __asm__ ("mr %0, 1" : "=r" (stackref) : );
+    {
+        SLP_SAVE_STATE(stackref, stsizediff);
+        __asm__ volatile (
+            "mr 11, %0\n"
+            "add 1, 1, 11\n"
+            : /* no outputs */
+            : "r" (stsizediff)
+            : "11"
+            );
+        SLP_RESTORE_STATE();
+    }
+    __asm__ volatile ("" : : : REGS_TO_SAVE);
+    __asm__ volatile ("li %0, 0" : "=r" (err));
+    return err;
+}
+
+#endif

+ 87 - 0
desktop/core/ext-py/greenlet-0.4.12/platform/switch_ppc_aix.h

@@ -0,0 +1,87 @@
+/*
+ * this is the internal transfer function.
+ *
+ * HISTORY
+ * 07-Mar-11 Floris Bruynooghe <flub@devork.be>
+ *      Do not add stsizediff to general purpose
+ *      register (GPR) 30 as this is a non-volatile and
+ *      unused by the PowerOpen Environment, therefore
+ *      this was modifying a user register instead of the
+ *      frame pointer (which does not seem to exist).
+ * 07-Sep-05 (py-dev mailing list discussion)
+ *      removed 'r31' from the register-saved.  !!!! WARNING !!!!
+ *      It means that this file can no longer be compiled statically!
+ *      It is now only suitable as part of a dynamic library!
+ * 14-Jan-04  Bob Ippolito <bob@redivi.com>
+ *      added cr2-cr4 to the registers to be saved.
+ *      Open questions: Should we save FP registers?
+ *      What about vector registers?
+ *      Differences between darwin and unix?
+ * 24-Nov-02  Christian Tismer  <tismer@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.
+ * 04-Oct-02  Gustavo Niemeyer <niemeyer@conectiva.com>
+ *      Ported from MacOS version.
+ * 17-Sep-02  Christian Tismer  <tismer@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@GMD.DE>
+ *      slightly changed framework for sparc
+ * 29-Jun-02  Christian Tismer  <tismer@tismer.com>
+ *      Added register 13-29, 31 saves. The same way as
+ *      Armin Rigo did for the x86_unix version.
+ *      This seems to be now fully functional!
+ * 04-Mar-02  Hye-Shik Chang  <perky@fallin.lv>
+ *      Ported from i386.
+ */
+
+#define STACK_REFPLUS 1
+
+#ifdef SLP_EVAL
+
+#define STACK_MAGIC 3
+
+/* !!!!WARNING!!!! need to add "r31" in the next line if this header file
+ * is meant to be compiled non-dynamically!
+ */
+#define REGS_TO_SAVE "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", \
+       "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", \
+       "cr2", "cr3", "cr4"
+static int
+slp_switch(void)
+{
+    register int err;
+    register int *stackref, stsizediff;
+    __asm__ volatile ("" : : : REGS_TO_SAVE);
+    __asm__ ("mr %0, 1" : "=g" (stackref) : );
+    {
+        SLP_SAVE_STATE(stackref, stsizediff);
+        __asm__ volatile (
+            "mr 11, %0\n"
+            "add 1, 1, 11\n"
+            : /* no outputs */
+            : "g" (stsizediff)
+            : "11"
+            );
+        SLP_RESTORE_STATE();
+    }
+    __asm__ volatile ("" : : : REGS_TO_SAVE);
+    __asm__ volatile ("li %0, 0" : "=r" (err));
+    return err;
+}
+
+#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.
+ */

+ 84 - 0
desktop/core/ext-py/greenlet-0.4.12/platform/switch_ppc_linux.h

@@ -0,0 +1,84 @@
+/*
+ * this is the internal transfer function.
+ *
+ * HISTORY
+ * 07-Sep-05 (py-dev mailing list discussion)
+ *      removed 'r31' from the register-saved.  !!!! WARNING !!!!
+ *      It means that this file can no longer be compiled statically!
+ *      It is now only suitable as part of a dynamic library!
+ * 14-Jan-04  Bob Ippolito <bob@redivi.com>
+ *      added cr2-cr4 to the registers to be saved.
+ *      Open questions: Should we save FP registers?
+ *      What about vector registers?
+ *      Differences between darwin and unix?
+ * 24-Nov-02  Christian Tismer  <tismer@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.
+ * 04-Oct-02  Gustavo Niemeyer <niemeyer@conectiva.com>
+ *      Ported from MacOS version.
+ * 17-Sep-02  Christian Tismer  <tismer@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@GMD.DE>
+ *      slightly changed framework for sparc
+ * 29-Jun-02  Christian Tismer  <tismer@tismer.com>
+ *      Added register 13-29, 31 saves. The same way as
+ *      Armin Rigo did for the x86_unix version.
+ *      This seems to be now fully functional!
+ * 04-Mar-02  Hye-Shik Chang  <perky@fallin.lv>
+ *      Ported from i386.
+ * 31-Jul-12  Trevor Bowen    <trevorbowen@gmail.com>
+ *      Changed memory constraints to register only.
+ */
+
+#define STACK_REFPLUS 1
+
+#ifdef SLP_EVAL
+
+#define STACK_MAGIC 3
+
+/* !!!!WARNING!!!! need to add "r31" in the next line if this header file
+ * is meant to be compiled non-dynamically!
+ */
+#define REGS_TO_SAVE "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", \
+       "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", \
+       "cr2", "cr3", "cr4"
+static int
+slp_switch(void)
+{
+    register int err;
+    register int *stackref, stsizediff;
+    __asm__ volatile ("" : : : REGS_TO_SAVE);
+    __asm__ ("mr %0, 1" : "=r" (stackref) : );
+    {
+        SLP_SAVE_STATE(stackref, stsizediff);
+        __asm__ volatile (
+            "mr 11, %0\n"
+            "add 1, 1, 11\n"
+            "add 30, 30, 11\n"
+            : /* no outputs */
+            : "r" (stsizediff)
+            : "11"
+            );
+        SLP_RESTORE_STATE();
+    }
+    __asm__ volatile ("" : : : REGS_TO_SAVE);
+    __asm__ volatile ("li %0, 0" : "=r" (err));
+    return err;
+}
+
+#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.
+ */

+ 82 - 0
desktop/core/ext-py/greenlet-0.4.12/platform/switch_ppc_macosx.h

@@ -0,0 +1,82 @@
+/*
+ * this is the internal transfer function.
+ *
+ * HISTORY
+ * 07-Sep-05 (py-dev mailing list discussion)
+ *      removed 'r31' from the register-saved.  !!!! WARNING !!!!
+ *      It means that this file can no longer be compiled statically!
+ *      It is now only suitable as part of a dynamic library!
+ * 14-Jan-04  Bob Ippolito <bob@redivi.com>
+ *      added cr2-cr4 to the registers to be saved.
+ *      Open questions: Should we save FP registers?
+ *      What about vector registers?
+ *      Differences between darwin and unix?
+ * 24-Nov-02  Christian Tismer  <tismer@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@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@GMD.DE>
+ *      slightly changed framework for sparc
+ * 29-Jun-02  Christian Tismer  <tismer@tismer.com>
+ *      Added register 13-29, 31 saves. The same way as
+ *      Armin Rigo did for the x86_unix version.
+ *      This seems to be now fully functional!
+ * 04-Mar-02  Hye-Shik Chang  <perky@fallin.lv>
+ *      Ported from i386.
+ */
+
+#define STACK_REFPLUS 1
+
+#ifdef SLP_EVAL
+
+#define STACK_MAGIC 3
+
+/* !!!!WARNING!!!! need to add "r31" in the next line if this header file
+ * is meant to be compiled non-dynamically!
+ */
+#define REGS_TO_SAVE "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", \
+       "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", \
+       "cr2", "cr3", "cr4"
+
+static int
+slp_switch(void)
+{
+    register int err;
+    register int *stackref, stsizediff;
+    __asm__ volatile ("" : : : REGS_TO_SAVE);
+    __asm__ ("; asm block 2\n\tmr %0, r1" : "=g" (stackref) : );
+    {
+        SLP_SAVE_STATE(stackref, stsizediff);
+        __asm__ volatile (
+            "; asm block 3\n"
+            "\tmr r11, %0\n"
+            "\tadd r1, r1, r11\n"
+            "\tadd r30, r30, r11\n"
+            : /* no outputs */
+            : "g" (stsizediff)
+            : "r11"
+            );
+        SLP_RESTORE_STATE();
+    }
+    __asm__ volatile ("" : : : REGS_TO_SAVE);
+    __asm__ volatile ("li %0, 0" : "=r" (err));
+    return err;
+}
+
+#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.
+ */

+ 82 - 0
desktop/core/ext-py/greenlet-0.4.12/platform/switch_ppc_unix.h

@@ -0,0 +1,82 @@
+/*
+ * this is the internal transfer function.
+ *
+ * HISTORY
+ * 07-Sep-05 (py-dev mailing list discussion)
+ *      removed 'r31' from the register-saved.  !!!! WARNING !!!!
+ *      It means that this file can no longer be compiled statically!
+ *      It is now only suitable as part of a dynamic library!
+ * 14-Jan-04  Bob Ippolito <bob@redivi.com>
+ *      added cr2-cr4 to the registers to be saved.
+ *      Open questions: Should we save FP registers?
+ *      What about vector registers?
+ *      Differences between darwin and unix?
+ * 24-Nov-02  Christian Tismer  <tismer@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.
+ * 04-Oct-02  Gustavo Niemeyer <niemeyer@conectiva.com>
+ *      Ported from MacOS version.
+ * 17-Sep-02  Christian Tismer  <tismer@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@GMD.DE>
+ *      slightly changed framework for sparc
+ * 29-Jun-02  Christian Tismer  <tismer@tismer.com>
+ *      Added register 13-29, 31 saves. The same way as
+ *      Armin Rigo did for the x86_unix version.
+ *      This seems to be now fully functional!
+ * 04-Mar-02  Hye-Shik Chang  <perky@fallin.lv>
+ *      Ported from i386.
+ */
+
+#define STACK_REFPLUS 1
+
+#ifdef SLP_EVAL
+
+#define STACK_MAGIC 3
+
+/* !!!!WARNING!!!! need to add "r31" in the next line if this header file
+ * is meant to be compiled non-dynamically!
+ */
+#define REGS_TO_SAVE "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", \
+       "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", \
+       "cr2", "cr3", "cr4"
+static int
+slp_switch(void)
+{
+    register int err;
+    register int *stackref, stsizediff;
+    __asm__ volatile ("" : : : REGS_TO_SAVE);
+    __asm__ ("mr %0, 1" : "=g" (stackref) : );
+    {
+        SLP_SAVE_STATE(stackref, stsizediff);
+        __asm__ volatile (
+            "mr 11, %0\n"
+            "add 1, 1, 11\n"
+            "add 30, 30, 11\n"
+            : /* no outputs */
+            : "g" (stsizediff)
+            : "11"
+            );
+        SLP_RESTORE_STATE();
+    }
+    __asm__ volatile ("" : : : REGS_TO_SAVE);
+    __asm__ volatile ("li %0, 0" : "=r" (err));
+    return err;
+}
+
+#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.
+ */

+ 87 - 0
desktop/core/ext-py/greenlet-0.4.12/platform/switch_s390_unix.h

@@ -0,0 +1,87 @@
+/*
+ * this is the internal transfer function.
+ *
+ * HISTORY
+ * 25-Jan-12  Alexey Borzenkov <snaury@gmail.com>
+ *      Fixed Linux/S390 port to work correctly with
+ *      different optimization options both on 31-bit
+ *      and 64-bit. Thanks to Stefan Raabe for lots
+ *      of testing.
+ * 24-Nov-02  Christian Tismer  <tismer@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.
+ * 06-Oct-02  Gustavo Niemeyer <niemeyer@conectiva.com>
+ *      Ported to Linux/S390.
+ */
+
+#define STACK_REFPLUS 1
+
+#ifdef SLP_EVAL
+
+#ifdef __s390x__
+#define STACK_MAGIC 20 /* 20 * 8 = 160 bytes of function call area */
+#else
+#define STACK_MAGIC 24 /* 24 * 4 = 96 bytes of function call area */
+#endif
+
+/* Technically, r11-r13 also need saving, but function prolog starts
+   with stm(g) and since there are so many saved registers already
+   it won't be optimized, resulting in all r6-r15 being saved */
+#define REGS_TO_SAVE "r6", "r7", "r8", "r9", "r10", "r14", \
+		     "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+		     "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15"
+
+static int
+slp_switch(void)
+{
+    register int ret;
+    register long *stackref, stsizediff;
+    __asm__ volatile ("" : : : REGS_TO_SAVE);
+#ifdef __s390x__
+    __asm__ volatile ("lgr %0, 15" : "=r" (stackref) : );
+#else
+    __asm__ volatile ("lr %0, 15" : "=r" (stackref) : );
+#endif
+    {
+        SLP_SAVE_STATE(stackref, stsizediff);
+/* N.B.
+   r11 may be used as the frame pointer, and in that case it cannot be
+   clobbered and needs offsetting just like the stack pointer (but in cases
+   where frame pointer isn't used we might clobber it accidentally). What's
+   scary is that r11 is 2nd (and even 1st when GOT is used) callee saved
+   register that gcc would chose for surviving function calls. However,
+   since r6-r10 are clobbered above, their cost for reuse is reduced, so
+   gcc IRA will chose them over r11 (not seeing r11 is implicitly saved),
+   making it relatively safe to offset in all cases. :) */
+        __asm__ volatile (
+#ifdef __s390x__
+            "agr 15, %0\n\t"
+            "agr 11, %0"
+#else
+            "ar 15, %0\n\t"
+            "ar 11, %0"
+#endif
+            : /* no outputs */
+            : "r" (stsizediff)
+            );
+        SLP_RESTORE_STATE();
+    }
+    __asm__ volatile ("" : : : REGS_TO_SAVE);
+    __asm__ volatile ("lhi %0, 0" : "=r" (ret) : );
+    return ret;
+}
+
+#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.
+ */

+ 92 - 0
desktop/core/ext-py/greenlet-0.4.12/platform/switch_sparc_sun_gcc.h

@@ -0,0 +1,92 @@
+/*
+ * this is the internal transfer function.
+ *
+ * HISTORY
+ * 16-May-15  Alexey Borzenkov <snaury@gmail.com>
+ *      Move stack spilling code inside save/restore functions
+ * 30-Aug-13  Floris Bruynooghe <flub@devork.be>
+        Clean the register windows again before returning.
+        This does not clobber the PIC register as it leaves
+        the current window intact and is required for multi-
+        threaded code to work correctly.
+ * 08-Mar-11  Floris Bruynooghe <flub@devork.be>
+ *      No need to set return value register explicitly
+ *      before the stack and framepointer are adjusted
+ *      as none of the other registers are influenced by
+ *      this.  Also don't needlessly clean the windows
+ *      ('ta %0" :: "i" (ST_CLEAN_WINDOWS)') as that
+ *      clobbers the gcc PIC register (%l7).
+ * 24-Nov-02  Christian Tismer  <tismer@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@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@GMD.DE>
+ *      added support for SunOS sparc with gcc
+ */
+
+#define STACK_REFPLUS 1
+
+#ifdef SLP_EVAL
+
+
+#define STACK_MAGIC 0
+
+
+#if defined(__sparcv9)
+#define SLP_FLUSHW __asm__ volatile ("flushw")
+#else
+#define SLP_FLUSHW __asm__ volatile ("ta 3") /* ST_FLUSH_WINDOWS */
+#endif
+
+/* On sparc we need to spill register windows inside save/restore functions */
+#define SLP_BEFORE_SAVE_STATE() SLP_FLUSHW
+#define SLP_BEFORE_RESTORE_STATE() SLP_FLUSHW
+
+
+static int
+slp_switch(void)
+{
+    register int err;
+    register int *stackref, stsizediff;
+
+    /* Put current stack pointer into stackref.
+     * Register spilling is done in save/restore.
+     */
+    __asm__ volatile ("mov %%sp, %0" : "=r" (stackref));
+
+    {
+        /* Thou shalt put SLP_SAVE_STATE into a local block */
+        /* Copy the current stack onto the heap */
+        SLP_SAVE_STATE(stackref, stsizediff);
+
+        /* Increment stack and frame pointer by stsizediff */
+        __asm__ volatile (
+            "add %0, %%sp, %%sp\n\t"
+            "add %0, %%fp, %%fp"
+            : : "r" (stsizediff));
+
+        /* Copy new stack from it's save store on the heap */
+        SLP_RESTORE_STATE();
+
+        __asm__ volatile ("mov %1, %0" : "=r" (err) : "i" (0));
+        return err;
+    }
+}
+
+#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.
+ */

+ 63 - 0
desktop/core/ext-py/greenlet-0.4.12/platform/switch_x32_unix.h

@@ -0,0 +1,63 @@
+/*
+ * this is the internal transfer function.
+ *
+ * HISTORY
+ * 17-Aug-12  Fantix King <fantix.king@gmail.com>
+ *      Ported from amd64.
+ */
+
+#define STACK_REFPLUS 1
+
+#ifdef SLP_EVAL
+
+#define STACK_MAGIC 0
+
+#define REGS_TO_SAVE "r12", "r13", "r14", "r15"
+
+
+static int
+slp_switch(void)
+{
+    void* ebp;
+    void* ebx;
+    unsigned int csr;
+    unsigned short cw;
+    register int err;
+    register int *stackref, stsizediff;
+    __asm__ volatile ("" : : : REGS_TO_SAVE);
+    __asm__ volatile ("fstcw %0" : "=m" (cw));
+    __asm__ volatile ("stmxcsr %0" : "=m" (csr));
+    __asm__ volatile ("movl %%ebp, %0" : "=m" (ebp));
+    __asm__ volatile ("movl %%ebx, %0" : "=m" (ebx));
+    __asm__ ("movl %%esp, %0" : "=g" (stackref));
+    {
+        SLP_SAVE_STATE(stackref, stsizediff);
+        __asm__ volatile (
+            "addl %0, %%esp\n"
+            "addl %0, %%ebp\n"
+            :
+            : "r" (stsizediff)
+            );
+        SLP_RESTORE_STATE();
+    }
+    __asm__ volatile ("movl %0, %%ebx" : : "m" (ebx));
+    __asm__ volatile ("movl %0, %%ebp" : : "m" (ebp));
+    __asm__ volatile ("ldmxcsr %0" : : "m" (csr));
+    __asm__ volatile ("fldcw %0" : : "m" (cw));
+    __asm__ volatile ("" : : : REGS_TO_SAVE);
+    __asm__ volatile ("xorl %%eax, %%eax" : "=a" (err));
+    return err;
+}
+
+#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.
+ */

+ 111 - 0
desktop/core/ext-py/greenlet-0.4.12/platform/switch_x64_masm.asm

@@ -0,0 +1,111 @@
+;
+; stack switching code for MASM on x641
+; Kristjan Valur Jonsson, sept 2005
+;
+
+
+;prototypes for our calls
+slp_save_state_asm PROTO
+slp_restore_state_asm PROTO
+
+
+pushxmm MACRO reg
+    sub rsp, 16
+    .allocstack 16
+    movaps [rsp], reg ; faster than movups, but we must be aligned
+    ; .savexmm128 reg, offset  (don't know what offset is, no documentation)
+ENDM
+popxmm MACRO reg
+    movaps reg, [rsp] ; faster than movups, but we must be aligned
+    add rsp, 16
+ENDM
+
+pushreg MACRO reg
+    push reg
+    .pushreg reg
+ENDM
+popreg MACRO reg
+    pop reg
+ENDM
+
+
+.code
+slp_switch PROC FRAME
+    ;realign stack to 16 bytes after return address push, makes the following faster
+    sub rsp,8
+    .allocstack 8
+
+    pushxmm xmm15
+    pushxmm xmm14
+    pushxmm xmm13
+    pushxmm xmm12
+    pushxmm xmm11
+    pushxmm xmm10
+    pushxmm xmm9
+    pushxmm xmm8
+    pushxmm xmm7
+    pushxmm xmm6
+
+    pushreg r15
+    pushreg r14
+    pushreg r13
+    pushreg r12
+
+    pushreg rbp
+    pushreg rbx
+    pushreg rdi
+    pushreg rsi
+
+    sub rsp, 10h ;allocate the singlefunction argument (must be multiple of 16)
+    .allocstack 10h
+.endprolog
+
+    lea rcx, [rsp+10h] ;load stack base that we are saving
+    call slp_save_state_asm ;pass stackpointer, return offset in eax
+    cmp rax, 1
+    je EXIT1
+    cmp rax, -1
+    je EXIT2
+    ;actual stack switch:
+    add rsp, rax
+    call slp_restore_state_asm
+    xor rax, rax ;return 0
+
+EXIT:
+
+    add rsp, 10h
+    popreg rsi
+    popreg rdi
+    popreg rbx
+    popreg rbp
+
+    popreg r12
+    popreg r13
+    popreg r14
+    popreg r15
+
+    popxmm xmm6
+    popxmm xmm7
+    popxmm xmm8
+    popxmm xmm9
+    popxmm xmm10
+    popxmm xmm11
+    popxmm xmm12
+    popxmm xmm13
+    popxmm xmm14
+    popxmm xmm15
+
+    add rsp, 8
+    ret
+
+EXIT1:
+    mov rax, 1
+    jmp EXIT
+
+EXIT2:
+    sar rax, 1
+    jmp EXIT
+
+slp_switch ENDP
+
+END

BIN
desktop/core/ext-py/greenlet-0.4.12/platform/switch_x64_masm.obj


+ 57 - 0
desktop/core/ext-py/greenlet-0.4.12/platform/switch_x64_msvc.h

@@ -0,0 +1,57 @@
+/*
+ * this is the internal transfer function.
+ *
+ * HISTORY
+ * 24-Nov-02  Christian Tismer  <tismer@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.
+ * 26-Sep-02  Christian Tismer  <tismer@tismer.com>
+ *      again as a result of virtualized stack access,
+ *      the compiler used less registers. Needed to
+ *      explicit mention registers in order to get them saved.
+ *      Thanks to Jeff Senn for pointing this out and help.
+ * 17-Sep-02  Christian Tismer  <tismer@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@GMD.DE>
+ *      slightly changed framework for sparc
+ * 01-Mar-02  Christian Tismer  <tismer@tismer.com>
+ *      Initial final version after lots of iterations for i386.
+ */
+
+#define alloca _alloca
+
+#define STACK_REFPLUS 1
+#define STACK_MAGIC 0
+
+/* Use the generic support for an external assembly language slp_switch function. */
+#define EXTERNAL_ASM
+
+#ifdef SLP_EVAL
+/* This always uses the external masm assembly file. */
+#endif
+
+/*
+ * further self-processing support
+ */
+
+/* we have IsBadReadPtr available, so we can peek at objects */
+/*
+#define STACKLESS_SPY
+
+#ifdef IMPLEMENT_STACKLESSMODULE
+#include "Windows.h"
+#define CANNOT_READ_MEM(p, bytes) IsBadReadPtr(p, bytes)
+
+static int IS_ON_STACK(void*p)
+{
+    int stackref;
+    intptr_t stackbase = ((intptr_t)&stackref) & 0xfffff000;
+    return (intptr_t)p >= stackbase && (intptr_t)p < stackbase + 0x00100000;
+}
+
+#endif
+*/

+ 88 - 0
desktop/core/ext-py/greenlet-0.4.12/platform/switch_x86_msvc.h

@@ -0,0 +1,88 @@
+/*
+ * this is the internal transfer function.
+ *
+ * HISTORY
+ * 24-Nov-02  Christian Tismer  <tismer@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.
+ * 26-Sep-02  Christian Tismer  <tismer@tismer.com>
+ *      again as a result of virtualized stack access,
+ *      the compiler used less registers. Needed to
+ *      explicit mention registers in order to get them saved.
+ *      Thanks to Jeff Senn for pointing this out and help.
+ * 17-Sep-02  Christian Tismer  <tismer@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@GMD.DE>
+ *      slightly changed framework for sparc
+ * 01-Mar-02  Christian Tismer  <tismer@tismer.com>
+ *      Initial final version after lots of iterations for i386.
+ */
+
+#define alloca _alloca
+
+#define STACK_REFPLUS 1
+
+#ifdef SLP_EVAL
+
+#define STACK_MAGIC 0
+
+/* Some magic to quell warnings and keep slp_switch() from crashing when built
+   with VC90. Disable global optimizations, and the warning: frame pointer
+   register 'ebp' modified by inline assembly code */
+#pragma optimize("g", off)
+#pragma warning(disable:4731)
+
+static int
+slp_switch(void)
+{
+    void* seh;
+    register int *stackref, stsizediff;
+    __asm mov eax, fs:[0]
+    __asm mov [seh], eax
+    __asm mov stackref, esp;
+    /* modify EBX, ESI and EDI in order to get them preserved */
+    __asm mov ebx, ebx;
+    __asm xchg esi, edi;
+    {
+        SLP_SAVE_STATE(stackref, stsizediff);
+        __asm {
+            mov     eax, stsizediff
+            add     esp, eax
+            add     ebp, eax
+        }
+        SLP_RESTORE_STATE();
+    }
+    __asm mov eax, [seh]
+    __asm mov fs:[0], eax
+    return 0;
+}
+
+/* re-enable ebp warning and global optimizations. */
+#pragma optimize("g", on)
+#pragma warning(default:4731)
+
+#endif
+
+/*
+ * further self-processing support
+ */
+
+/* we have IsBadReadPtr available, so we can peek at objects */
+#define STACKLESS_SPY
+
+#ifdef IMPLEMENT_STACKLESSMODULE
+#include "Windows.h"
+#define CANNOT_READ_MEM(p, bytes) IsBadReadPtr(p, bytes)
+
+static int IS_ON_STACK(void*p)
+{
+    int stackref;
+    int stackbase = ((int)&stackref) & 0xfffff000;
+    return (int)p >= stackbase && (int)p < stackbase + 0x00100000;
+} 
+
+#endif

+ 105 - 0
desktop/core/ext-py/greenlet-0.4.12/platform/switch_x86_unix.h

@@ -0,0 +1,105 @@
+/*
+ * this is the internal transfer function.
+ *
+ * HISTORY
+ * 3-May-13   Ralf Schmitt  <ralf@systemexit.de>
+ *     Add support for strange GCC caller-save decisions
+ *     (ported from switch_aarch64_gcc.h)
+ * 19-Aug-11  Alexey Borzenkov  <snaury@gmail.com>
+ *      Correctly save ebp, ebx and cw
+ * 07-Sep-05 (py-dev mailing list discussion)
+ *      removed 'ebx' from the register-saved.  !!!! WARNING !!!!
+ *      It means that this file can no longer be compiled statically!
+ *      It is now only suitable as part of a dynamic library!
+ * 24-Nov-02  Christian Tismer  <tismer@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@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@GMD.DE>
+ *      slightly changed framework for spark
+ * 31-Avr-02  Armin Rigo         <arigo@ulb.ac.be>
+ *      Added ebx, esi and edi register-saves.
+ * 01-Mar-02  Samual M. Rushing  <rushing@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
+
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+# define ATTR_NOCLONE __attribute__((noclone))
+#else
+# define ATTR_NOCLONE
+#endif
+
+static int
+slp_switch(void)
+{
+    int err;
+#ifdef _WIN32
+    void *seh;
+#endif
+    void *ebp, *ebx;
+    unsigned short cw;
+    register int *stackref, stsizediff;
+    __asm__ volatile ("" : : : "esi", "edi");
+    __asm__ volatile ("fstcw %0" : "=m" (cw));
+    __asm__ volatile ("movl %%ebp, %0" : "=m" (ebp));
+    __asm__ volatile ("movl %%ebx, %0" : "=m" (ebx));
+#ifdef _WIN32
+    __asm__ volatile (
+        "movl %%fs:0x0, %%eax\n"
+        "movl %%eax, %0\n"
+        : "=m" (seh)
+        :
+        : "eax");
+#endif
+    __asm__ ("movl %%esp, %0" : "=g" (stackref));
+    {
+        SLP_SAVE_STATE(stackref, stsizediff);
+        __asm__ volatile (
+            "addl %0, %%esp\n"
+            "addl %0, %%ebp\n"
+            :
+            : "r" (stsizediff)
+            );
+        SLP_RESTORE_STATE();
+        __asm__ volatile ("xorl %%eax, %%eax" : "=a" (err));
+    }
+#ifdef _WIN32
+    __asm__ volatile (
+        "movl %0, %%eax\n"
+        "movl %%eax, %%fs:0x0\n"
+        :
+        : "m" (seh)
+        : "eax");
+#endif
+    __asm__ volatile ("movl %0, %%ebx" : : "m" (ebx));
+    __asm__ volatile ("movl %0, %%ebp" : : "m" (ebp));
+    __asm__ volatile ("fldcw %0" : : "m" (cw));
+    __asm__ volatile ("" : : : "esi", "edi");
+    return err;
+}
+
+#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.
+ */

+ 63 - 0
desktop/core/ext-py/greenlet-0.4.12/run-tests.py

@@ -0,0 +1,63 @@
+#! /usr/bin/env python
+
+import sys, os, getopt, struct, unittest
+from distutils.spawn import spawn
+
+build = True
+verbosity = 2
+build_base = None
+here = os.path.dirname(os.path.abspath(__file__))
+os.chdir(here)
+
+
+def bits():
+    """determine if running on a 32 bit or 64 bit platform
+    """
+    return struct.calcsize("P") * 8
+
+# -- parse options
+try:
+    opts, args = getopt.getopt(sys.argv[1:], "nqb:")
+    if args:
+        raise getopt.GetoptError("too many arguments")
+except getopt.GetoptError:
+    sys.exit("run-tests.py: error: %s" % sys.exc_info()[1])
+
+for o, a in opts:
+    if o == "-q":
+        verbosity = 0
+    elif o == "-n":
+        build = False
+    elif o == "-b":
+        build_base = a
+
+# -- build greenlet
+if build:
+    if verbosity == 0:
+        cmd = [sys.executable, "setup.py", "-q", "build_ext", "-q", "-i"]
+    else:
+        cmd = [sys.executable, "setup.py", "build_ext", "-i"]
+
+    spawn(cmd, search_path=0)
+
+
+# -- find greenlet but skip the one in "."
+if not build:
+    oldpath = sys.path[:]
+    sys.path.remove(here)
+
+import greenlet
+
+if not build:
+    sys.path[:] = oldpath
+
+sys.stdout.write("python %s (%s bit) using greenlet %s from %s\n" %
+                 (sys.version.split()[0], bits(), greenlet.__version__, greenlet.__file__))
+sys.stdout.flush()
+
+
+# -- run tests
+from tests import test_collector
+result = unittest.TextTestRunner(verbosity=verbosity).run(test_collector(build_base))
+if result.failures or result.errors:
+    sys.exit(1)

+ 2 - 0
desktop/core/ext-py/greenlet-0.4.12/setup.cfg

@@ -0,0 +1,2 @@
+[sdist]
+formats=gztar zip

+ 105 - 0
desktop/core/ext-py/greenlet-0.4.12/setup.py

@@ -0,0 +1,105 @@
+#! /usr/bin/env python
+
+import sys, os, glob, platform, tempfile, shutil
+
+# workaround segfaults on openbsd and RHEL 3 / CentOS 3 . see
+# https://bitbucket.org/ambroff/greenlet/issue/11/segfault-on-openbsd-i386
+# https://github.com/python-greenlet/greenlet/issues/4
+# https://github.com/python-greenlet/greenlet/issues/94
+if ((sys.platform == "openbsd4" and os.uname()[-1] == "i386")
+    or ("-with-redhat-3." in platform.platform() and platform.machine() == 'i686')
+    or (sys.platform == "sunos5" and os.uname()[-1] == "sun4v")
+    or ("SunOS" in platform.platform() and platform.machine() == "sun4v")
+    or (sys.platform == "linux" and platform.machine() == "ppc")):
+    os.environ["CFLAGS"] = ("%s %s" % (os.environ.get("CFLAGS", ""), "-Os")).lstrip()
+
+try:
+    if not (sys.modules.get("setuptools")
+            or "develop" in sys.argv
+            or "upload" in sys.argv
+            or "bdist_egg" in sys.argv
+            or "bdist_wheel" in sys.argv
+            or "test" in sys.argv):
+        raise ImportError()
+    from setuptools import setup, Extension
+    setuptools_args = dict(test_suite='tests.test_collector', zip_safe=False)
+except ImportError:
+    from distutils.core import setup, Extension
+    setuptools_args = dict()
+
+def readfile(filename):
+    f = open(filename)
+    try:
+        return f.read()
+    finally:
+        f.close()
+
+def _find_platform_headers():
+    return glob.glob("platform/switch_*.h")
+
+if hasattr(sys, "pypy_version_info"):
+    ext_modules = []
+    headers = []
+else:
+    headers = ['greenlet.h']
+
+    if sys.platform == 'win32' and '64 bit' in sys.version:
+        # this works when building with msvc, not with 64 bit gcc
+        # switch_x64_masm.obj can be created with setup_switch_x64_masm.cmd
+        extra_objects = ['platform/switch_x64_masm.obj']
+    else:
+        extra_objects = []
+
+    if sys.platform == 'win32' and os.environ.get('GREENLET_STATIC_RUNTIME') in ('1', 'yes'):
+        extra_compile_args = ['/MT']
+    elif hasattr(os, 'uname') and os.uname()[4] in ['ppc64el', 'ppc64le']:
+        extra_compile_args = ['-fno-tree-dominator-opts']
+    else:
+        extra_compile_args = []
+
+    ext_modules = [Extension(
+        name='greenlet',
+        sources=['greenlet.c'],
+        extra_objects=extra_objects,
+        extra_compile_args=extra_compile_args,
+        depends=['greenlet.h', 'slp_platformselect.h'] + _find_platform_headers())]
+
+from distutils.core import Command
+from my_build_ext import build_ext
+
+
+setup(
+    name="greenlet",
+    version='0.4.12',
+    description='Lightweight in-process concurrent programming',
+    long_description=readfile("README.rst"),
+    maintainer="Alexey Borzenkov",
+    maintainer_email="snaury@gmail.com",
+    url="https://github.com/python-greenlet/greenlet",
+    license="MIT License",
+    platforms=['any'],
+    headers=headers,
+    ext_modules=ext_modules,
+    cmdclass=dict(build_ext=build_ext),
+    classifiers=[
+        'Intended Audience :: Developers',
+        'License :: OSI Approved :: MIT License',
+        'Natural Language :: English',
+        'Programming Language :: C',
+        'Programming Language :: Python',
+        'Programming Language :: Python :: 2',
+        'Programming Language :: Python :: 2.4',
+        'Programming Language :: Python :: 2.5',
+        'Programming Language :: Python :: 2.6',
+        'Programming Language :: Python :: 2.7',
+        'Programming Language :: Python :: 3',
+        'Programming Language :: Python :: 3.0',
+        'Programming Language :: Python :: 3.1',
+        'Programming Language :: Python :: 3.2',
+        'Programming Language :: Python :: 3.3',
+        'Programming Language :: Python :: 3.4',
+        'Programming Language :: Python :: 3.5',
+        'Programming Language :: Python :: 3.6',
+        'Operating System :: OS Independent',
+        'Topic :: Software Development :: Libraries :: Python Modules'],
+    **setuptools_args)

+ 2 - 0
desktop/core/ext-py/greenlet-0.4.12/setup_switch_x64_masm.cmd

@@ -0,0 +1,2 @@
+call "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" amd64
+ml64 /nologo /c /Fo platform\switch_x64_masm.obj platform\switch_x64_masm.asm

+ 50 - 0
desktop/core/ext-py/greenlet-0.4.12/slp_platformselect.h

@@ -0,0 +1,50 @@
+/*
+ * Platform Selection for Stackless Python
+ */
+
+#if   defined(MS_WIN32) && !defined(MS_WIN64) && defined(_M_IX86) && defined(_MSC_VER)
+#include "platform/switch_x86_msvc.h" /* MS Visual Studio on X86 */
+#elif defined(MS_WIN64) && defined(_M_X64) && defined(_MSC_VER)
+#include "platform/switch_x64_msvc.h" /* MS Visual Studio on X64 */
+#elif defined(__GNUC__) && defined(__amd64__) && defined(__ILP32__)
+#include "platform/switch_x32_unix.h" /* gcc on amd64 with x32 ABI */
+#elif defined(__GNUC__) && defined(__amd64__)
+#include "platform/switch_amd64_unix.h" /* gcc on amd64 */
+#elif defined(__GNUC__) && defined(__i386__)
+#include "platform/switch_x86_unix.h" /* gcc on X86 */
+#elif defined(__GNUC__) && defined(__powerpc64__) && defined(__linux__)
+#include "platform/switch_ppc64_linux.h" /* gcc on PowerPC 64-bit */
+#elif defined(__GNUC__) && defined(__PPC__) && defined(__linux__)
+#include "platform/switch_ppc_linux.h" /* gcc on PowerPC */
+#elif defined(__GNUC__) && defined(__ppc__) && defined(__APPLE__)
+#include "platform/switch_ppc_macosx.h" /* Apple MacOS X on PowerPC */
+#elif defined(__GNUC__) && defined(_ARCH_PPC) && defined(_AIX)
+#include "platform/switch_ppc_aix.h" /* gcc on AIX/PowerPC */
+#elif defined(__GNUC__) && defined(sparc)
+#include "platform/switch_sparc_sun_gcc.h" /* SunOS sparc with gcc */
+#elif defined(__SUNPRO_C) && defined(sparc) && defined(sun)
+#include "platform/switch_sparc_sun_gcc.h" /* SunStudio on amd64 */
+#elif defined(__SUNPRO_C) && defined(__amd64__) && defined(sun)
+#include "platform/switch_amd64_unix.h" /* SunStudio on amd64 */
+#elif defined(__SUNPRO_C) && defined(__i386__) && defined(sun)
+#include "platform/switch_x86_unix.h" /* SunStudio on x86 */
+#elif defined(__GNUC__) && defined(__s390__) && defined(__linux__)
+#include "platform/switch_s390_unix.h"	/* Linux/S390 */
+#elif defined(__GNUC__) && defined(__s390x__) && defined(__linux__)
+#include "platform/switch_s390_unix.h"	/* Linux/S390 zSeries (64-bit) */
+#elif defined(__GNUC__) && defined(__arm__)
+#ifdef __APPLE__
+#include <TargetConditionals.h>
+#endif
+#if TARGET_OS_IPHONE
+#include "platform/switch_arm32_ios.h" /* iPhone OS on arm32 */
+#else
+#include "platform/switch_arm32_gcc.h" /* gcc using arm32 */
+#endif
+#elif defined(__GNUC__) && defined(__mips__) && defined(__linux__)
+#include "platform/switch_mips_unix.h" /* Linux/MIPS */
+#elif defined(__GNUC__) && defined(__aarch64__)
+#include "platform/switch_aarch64_gcc.h" /* Aarch64 ABI */
+#elif defined(__GNUC__) && defined(__mc68000__)
+#include "platform/switch_m68k_gcc.h" /* gcc on m68k */
+#endif

+ 39 - 0
desktop/core/ext-py/greenlet-0.4.12/tox.ini

@@ -0,0 +1,39 @@
+[testenv]
+commands={envpython} run-tests.py -nq
+sitepackages=False
+
+# this is 32 bit only
+[testenv:x-py25]
+basepython=/usr/bin/python2.5
+
+# test both 32 bit and 64 bit on OS X
+[testenv:x-py26]
+commands=/usr/bin/arch -i386 {envpython} run-tests.py -qn
+	 /usr/bin/arch -x86_64 {envpython} run-tests.py -qn
+basepython=/usr/bin/python2.6
+
+[testenv:x-py27]
+commands=/usr/bin/arch -i386 {envpython} run-tests.py -qn
+	 /usr/bin/arch -x86_64 {envpython} run-tests.py -qn
+basepython=/usr/bin/python2.7
+
+
+# test with specific gcc version on OS X
+[testenv:x-py26-gcc40]
+commands=/usr/bin/arch -i386 {envpython} run-tests.py -qn
+	 /usr/bin/arch -x86_64 {envpython} run-tests.py -qn
+basepython=/usr/bin/python2.6
+setenv=
+	CC=gcc-4.0
+
+[testenv:x-py26-gcc42]
+commands=/usr/bin/arch -i386 {envpython} run-tests.py -qn
+	 /usr/bin/arch -x86_64 {envpython} run-tests.py -qn
+basepython=/usr/bin/python2.6
+setenv=	CC=gcc-4.2
+
+[testenv:docs]
+deps=docutils
+     sphinx
+commands=make html
+changedir={toxinidir}/doc