/* -*- indent-tabs-mode: nil; tab-width: 4; -*- */
/* Format with:
* clang-format -i --style=file src/greenlet/greenlet.c
*
*
* Fix missing braces with:
* clang-tidy src/greenlet/greenlet.c -fix -checks="readability-braces-around-statements"
*/
#define GREENLET_MODULE
#include "greenlet.h"
#include "structmember.h"
#ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunused-parameter"
# pragma clang diagnostic ignored "-Wmissing-field-initializers"
#endif
/***********************************************************
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'.
*/
extern PyTypeObject PyGreenlet_Type;
#if PY_VERSION_HEX >= 0x030700A3
# define GREENLET_PY37 1
#else
# define GREENLET_PY37 0
#endif
#if PY_VERSION_HEX >= 0x30A00B1
/*
Python 3.10 beta 1 changed tstate->use_tracing to a nested cframe member.
See https://github.com/python/cpython/pull/25276
We have to save and restore this as well.
*/
#define TSTATE_USE_TRACING(tstate) (tstate->cframe->use_tracing)
#define GREENLET_USE_CFRAME 1
#else
#define TSTATE_USE_TRACING(tstate) (tstate->use_tracing)
#define GREENLET_USE_CFRAME 0
#endif
#ifndef Py_SET_REFCNT
/* Py_REFCNT and Py_SIZE macros are converted to functions
https://bugs.python.org/issue39573 */
# define Py_SET_REFCNT(obj, refcnt) Py_REFCNT(obj) = (refcnt)
#endif
#ifndef _Py_DEC_REFTOTAL
/* _Py_DEC_REFTOTAL macro has been removed from Python 3.9 by:
https://github.com/python/cpython/commit/49932fec62c616ec88da52642339d83ae719e924
*/
# ifdef Py_REF_DEBUG
# define _Py_DEC_REFTOTAL _Py_RefTotal--
# else
# define _Py_DEC_REFTOTAL
# endif
#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;
/* Used internally in ``g_switchstack()`` */
#if GREENLET_USE_CFRAME
static int volatile ts__g_switchstack_use_tracing = 0;
#endif
/***********************************************************/
/* 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;
static PyObject* ts_tracekey;
static PyObject* ts_event_switch;
static PyObject* ts_event_throw;
static PyObject* PyExc_GreenletError;
static PyObject* PyExc_GreenletExit;
static PyObject* ts_empty_tuple;
static PyObject* ts_empty_dict;
#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
static void
green_clear_exc(PyGreenlet* g)
{
#if GREENLET_PY37
g->exc_info = NULL;
g->exc_state.exc_type = NULL;
g->exc_state.exc_value = NULL;
g->exc_state.exc_traceback = NULL;
g->exc_state.previous_item = NULL;
#else
g->exc_type = NULL;
g->exc_value = NULL;
g->exc_traceback = NULL;
#endif
}
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;
/* GetDict() returns a borrowed reference. Make it strong. */
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)) {
P
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
【资源说明】 基于Python+Flask框架的观影清单系统设计与实现-毕业设计源码+使用文档(高分优秀项目).zip基于Python+Flask框架的观影清单系统设计与实现-毕业设计源码+使用文档(高分优秀项目).zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如软件工程、计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也可作为毕设项目、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 3、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!
资源推荐
资源详情
资源评论
收起资源包目录
基于Python+Flask框架的观影清单系统设计与实现-毕业设计源码+使用文档(高分优秀项目).zip (2000个子文件)
AUTHORS 849B
greenlet.c 64KB
_speedups.c 7KB
_test_extension.c 5KB
sysconfig.cfg 3KB
_test_extension_cpp.cpp 3KB
style.css 6KB
style.css 2KB
.env 0B
t64.exe 104KB
w64.exe 98KB
t32.exe 95KB
w32.exe 88KB
gui-64.exe 74KB
cli-64.exe 73KB
cli-32.exe 64KB
cli.exe 64KB
gui-32.exe 64KB
gui.exe 64KB
.flaskenv 61B
greenlet.h 4KB
greenlet.h 4KB
switch_ppc64_aix.h 4KB
switch_ppc64_linux.h 4KB
slp_platformselect.h 3KB
switch_x86_unix.h 3KB
switch_ppc_aix.h 3KB
switch_sparc_sun_gcc.h 3KB
switch_s390_unix.h 3KB
switch_ppc_linux.h 3KB
switch_ppc_unix.h 3KB
switch_ppc_macosx.h 3KB
switch_amd64_unix.h 3KB
switch_arm32_gcc.h 2KB
switch_x86_msvc.h 2KB
switch_aarch64_gcc.h 2KB
switch_arm32_ios.h 2KB
switch_x64_msvc.h 2KB
switch_x32_unix.h 1KB
switch_mips_unix.h 1KB
switch_csky_gcc.h 1KB
switch_m68k_gcc.h 928B
switch_riscv_unix.h 758B
switch_alpha_unix.h 689B
index.html 1KB
base.html 1KB
login.html 416B
edit.html 370B
settings.html 279B
404.html 247B
INSTALLER 4B
INSTALLER 4B
INSTALLER 4B
INSTALLER 4B
INSTALLER 4B
INSTALLER 4B
INSTALLER 4B
INSTALLER 4B
INSTALLER 4B
INSTALLER 4B
INSTALLER 4B
INSTALLER 4B
INSTALLER 4B
INSTALLER 4B
INSTALLER 4B
INSTALLER 4B
debugger.js 10KB
LICENSE 11KB
LICENSE 4KB
LICENSE 1KB
LICENSE 1KB
LICENSE 1KB
LICENSE 1KB
LICENSE 1KB
ICON_LICENSE.md 222B
README.md 0B
METADATA 19KB
METADATA 15KB
METADATA 10KB
METADATA 6KB
METADATA 5KB
METADATA 4KB
METADATA 4KB
METADATA 4KB
METADATA 4KB
METADATA 4KB
METADATA 3KB
METADATA 3KB
METADATA 3KB
METADATA 3KB
METADATA 3KB
METADATA 3KB
cacert.pem 276KB
console.png 507B
more.png 200B
less.png 191B
LICENSE.PSF 2KB
pyparsing.py 267KB
selectable.py 232KB
pyparsing.py 221KB
共 2000 条
- 1
- 2
- 3
- 4
- 5
- 6
- 20
资源评论
不走小道
- 粉丝: 3313
- 资源: 5062
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功