1 /** 2 Mirror _pystate.h 3 4 Thread and interpreter state structures and their interfaces 5 */ 6 module deimos.python.pystate; 7 8 import core.stdc.stddef : wchar_t; 9 10 import deimos.python.pyport; 11 import deimos.python.object; 12 import deimos.python.frameobject; 13 import deimos.python.pyatomic; 14 import deimos.python.moduleobject; 15 import deimos.python.pythread; 16 17 extern(C): 18 // Python-header-file: Include/pystate.h: 19 20 enum MAX_CO_EXTRA_USERS = 255; 21 22 version(Python_3_5_Or_Later) { 23 alias PyObject* function(PyFrameObject*, int) _PyFrameEvalFunction; 24 } 25 26 version(Python_3_7_Or_Later) { 27 struct _PyCoreConfig { 28 int install_signal_handlers; /* Install signal handlers? -1 means unset */ 29 30 int ignore_environment; /* -E, Py_IgnoreEnvironmentFlag */ 31 int use_hash_seed; /* PYTHONHASHSEED=x */ 32 C_long hash_seed; 33 char* allocator; /* Memory allocator: _PyMem_SetupAllocators() */ 34 int dev_mode; /* PYTHONDEVMODE, -X dev */ 35 int faulthandler; /* PYTHONFAULTHANDLER, -X faulthandler */ 36 int tracemalloc; /* PYTHONTRACEMALLOC, -X tracemalloc=N */ 37 int import_time; /* PYTHONPROFILEIMPORTTIME, -X importtime */ 38 int show_ref_count; /* -X showrefcount */ 39 int show_alloc_count; /* -X showalloccount */ 40 int dump_refs; /* PYTHONDUMPREFS */ 41 int malloc_stats; /* PYTHONMALLOCSTATS */ 42 int coerce_c_locale; /* PYTHONCOERCECLOCALE, -1 means unknown */ 43 int coerce_c_locale_warn; /* PYTHONCOERCECLOCALE=warn */ 44 int utf8_mode; /* PYTHONUTF8, -X utf8; -1 means unknown */ 45 46 wchar_t* program_name; /* Program name, see also Py_GetProgramName() */ 47 int argc; /* Number of command line arguments, 48 -1 means unset */ 49 wchar_t** argv; /* Command line arguments */ 50 wchar_t* program; /* argv[0] or "" */ 51 52 int nxoption; /* Number of -X options */ 53 wchar_t** xoptions; /* -X options */ 54 55 int nwarnoption; /* Number of warnings options */ 56 wchar_t** warnoptions; /* Warnings options */ 57 58 /* Path configuration inputs */ 59 wchar_t* module_search_path_env; /* PYTHONPATH environment variable */ 60 wchar_t* home; /* PYTHONHOME environment variable, 61 see also Py_SetPythonHome(). */ 62 /* Path configuration outputs */ 63 int nmodule_search_path; /* Number of sys.path paths, 64 -1 means unset */ 65 wchar_t** module_search_paths; /* sys.path paths */ 66 wchar_t* executable; /* sys.executable */ 67 wchar_t* prefix; /* sys.prefix */ 68 wchar_t* base_prefix; /* sys.base_prefix */ 69 wchar_t* exec_prefix; /* sys.exec_prefix */ 70 wchar_t* base_exec_prefix; /* sys.base_exec_prefix */ 71 72 /* Private fields */ 73 int _disable_importlib; /* Needed by freeze_importlib */ 74 } 75 76 struct _PyMainInterpreterConfig{ 77 int install_signal_handlers; /* Install signal handlers? -1 means unset */ 78 PyObject* argv; /* sys.argv list, can be NULL */ 79 PyObject* executable; /* sys.executable str */ 80 PyObject* prefix; /* sys.prefix str */ 81 PyObject* base_prefix; /* sys.base_prefix str, can be NULL */ 82 PyObject* exec_prefix; /* sys.exec_prefix str */ 83 PyObject* base_exec_prefix; /* sys.base_exec_prefix str, can be NULL */ 84 PyObject* warnoptions; /* sys.warnoptions list, can be NULL */ 85 PyObject* xoptions; /* sys._xoptions dict, can be NULL */ 86 PyObject* module_search_path; /* sys.path list */ 87 } 88 89 struct _PyErr_StackItem{ 90 /* This struct represents an entry on the exception stack, which is a 91 * per-coroutine state. (Coroutine in the computer science sense, 92 * including the thread and generators). 93 * This ensures that the exception state is not impacted by "yields" 94 * from an except handler. 95 */ 96 PyObject* exc_type; 97 PyObject* exc_value; 98 PyObject* exc_traceback; 99 100 _PyErr_StackItem* previous_item; 101 102 } 103 } 104 105 /// _ 106 struct PyInterpreterState { 107 /// _ 108 PyInterpreterState* next; 109 /// _ 110 PyThreadState* tstate_head; 111 112 version(Python_3_7_Or_Later) { 113 /// Availability >= 3.7 114 long id; 115 /// Availability >= 3.7 116 long id_refcount; 117 /// Availability >= 3.7 118 PyThread_type_lock id_mutex; 119 } 120 /// _ 121 PyObject* modules; 122 version(Python_3_0_Or_Later) { 123 /// Availability: 3.* 124 PyObject* modules_by_index; 125 } 126 /// _ 127 PyObject* sysdict; 128 /// _ 129 PyObject* builtins; 130 131 version(Python_3_0_Or_Later) { 132 }else version(Python_2_7_Or_Later) { 133 /// Availability: 2.7 (?) 134 PyObject* modules_reloading; 135 } 136 137 version(Python_3_3_Or_Later) { 138 /// _ 139 PyObject* importlib; 140 } 141 version(Python_3_7_Or_Later) { 142 /// _ 143 int check_interval; 144 C_long num_threads; 145 size_t pythread_stacksize; 146 } 147 148 /// _ 149 PyObject* codec_search_path; 150 /// _ 151 PyObject* codec_search_cache; 152 /// _ 153 PyObject* codec_error_registry; 154 version(Python_3_0_Or_Later) { 155 /// Availability: 3.* 156 int codecs_initialized; 157 /// Availability: 3.* 158 int fscodec_initialized; 159 } 160 161 version(Python_3_7_Or_Later) { 162 _PyCoreConfig core_config; 163 _PyMainInterpreterConfig config; 164 } 165 166 /// _ 167 int dlopenflags; 168 169 // XXX: Not sure what WITH_TSC refers to, or how to conditionalize it in D: 170 //#ifdef WITH_TSC 171 // int tscdump; 172 //#endif 173 174 version(Python_3_4_Or_Later) { 175 PyObject* builtins_copy; 176 } 177 version(Python_3_6_Or_Later) { 178 PyObject* import_func; 179 _PyFrameEvalFunction eval_frame; 180 } 181 182 version(Python_3_7_Or_Later) { 183 Py_ssize_t co_extra_user_count; 184 freefunc[MAX_CO_EXTRA_USERS] co_extra_freefuncs; 185 186 // ifdef HAVE_FORK 187 PyObject* before_forkers; 188 PyObject* after_forkers_parent; 189 PyObject* after_forkers_child; 190 // end ifdef HAVE_FORK 191 192 void function(PyObject*) pyexitfunc; 193 PyObject* pyexitmodule; 194 195 ulong tstate_next_unique_id; 196 197 } 198 } 199 200 /// _ 201 alias int function(PyObject*, PyFrameObject*, int, PyObject*) Py_tracefunc; 202 203 /// _ 204 enum PyTrace_CALL = 0; 205 /// ditto 206 enum PyTrace_EXCEPTION = 1; 207 /// ditto 208 enum PyTrace_LINE = 2; 209 /// ditto 210 enum PyTrace_RETURN = 3; 211 /// ditto 212 enum PyTrace_C_CALL = 4; 213 /// ditto 214 enum PyTrace_C_EXCEPTION = 5; 215 /// ditto 216 enum PyTrace_C_RETURN = 6; 217 218 /// _ 219 struct PyThreadState { 220 version(Python_3_4_Or_Later) { 221 /// Availability: >= 3.4 222 PyThreadState* prev; 223 } 224 /// _ 225 PyThreadState* next; 226 /// _ 227 PyInterpreterState* interp; 228 229 /// _ 230 PyFrameObject* frame; 231 /// _ 232 int recursion_depth; 233 version(Python_3_0_Or_Later) { 234 /** The stack has overflowed. Allow 50 more calls 235 to handle the runtime error. */ 236 /// Availability: 3.* 237 ubyte overflowed; 238 /** The current calls must not cause 239 a stack overflow. */ 240 /// Availability: 3.* 241 ubyte recursion_critical; 242 } 243 version(Python_3_7_Or_Later) { 244 /// _ 245 int stackcheck_counter; 246 } 247 /// _ 248 int tracing; 249 /// _ 250 int use_tracing; 251 252 /// _ 253 Py_tracefunc c_profilefunc; 254 /// _ 255 Py_tracefunc c_tracefunc; 256 /// _ 257 PyObject* c_profileobj; 258 /// _ 259 PyObject* c_traceobj; 260 261 /// _ 262 PyObject* curexc_type; 263 /// _ 264 PyObject* curexc_value; 265 /// _ 266 PyObject* curexc_traceback; 267 268 version(Python_3_7_Or_Later) { 269 /// _ 270 _PyErr_StackItem exc_state; 271 /// _ 272 _PyErr_StackItem* exc_info; 273 }else{ 274 /// _ 275 PyObject* exc_type; 276 /// _ 277 PyObject* exc_value; 278 /// _ 279 PyObject* exc_traceback; 280 } 281 282 /// _ 283 PyObject* dict; 284 285 version(Python_3_4_Or_Later) { 286 }else{ 287 /** tick_counter is incremented whenever the check_interval ticker 288 * reaches zero. The purpose is to give a useful measure of the number 289 * of interpreted bytecode instructions in a given thread. This 290 * extremely lightweight statistic collector may be of interest to 291 * profilers (like psyco.jit()), although nothing in the core uses it. 292 */ 293 /// Availability: < 3.4 294 int tick_counter; 295 } 296 /// _ 297 int gilstate_counter; 298 /** Asynchronous exception to raise */ 299 PyObject* async_exc; 300 /** Thread id where this tstate was created */ 301 C_long thread_id; 302 303 version(Python_3_3_Or_Later) { 304 /// Availability: >= 3.3 305 int trash_delete_nesting; 306 307 /// Availability: >= 3.3 308 PyObject *trash_delete_later; 309 } 310 version(Python_3_4_Or_Later) { 311 /// Availability: >= 3.4 312 void function(void *) on_delete; 313 /// Availability: >= 3.4 314 void* on_delete_data; 315 } 316 version(Python_3_7_Or_Later) { 317 int coroutine_origin_tracking_depth; 318 } 319 version(Python_3_8_Or_Later) { 320 }else version(Python_3_5_Or_Later) { 321 /// Availability: = 3.5 - 3.7 322 PyObject* coroutine_wrapper; 323 /// Availability: = 3.5 - 3.7 324 int in_coroutine_wrapper; 325 } 326 327 version(Python_3_7_Or_Later) { 328 PyObject* async_gen_firstiter; 329 PyObject* async_gen_finalizer; 330 331 PyObject* context; 332 ulong context_ver; 333 334 ulong id; 335 }else version(Python_3_6_Or_Later) { 336 /// Availability: = 3.6 337 Py_ssize_t co_extra_user_count; 338 /// Availability: = 3.6 339 freefunc[MAX_CO_EXTRA_USERS] co_extra_freefuncs; 340 /// Availability: >= 3.6 341 PyObject* async_gen_firstiter; 342 /// Availability: >= 3.6 343 PyObject* async_gen_finalizer; 344 } 345 } 346 347 /// _ 348 PyInterpreterState* PyInterpreterState_New(); 349 /// _ 350 void PyInterpreterState_Clear(PyInterpreterState *); 351 /// _ 352 void PyInterpreterState_Delete(PyInterpreterState *); 353 version(Python_3_8_Or_Later) { 354 /// Availability: >=3.8 355 PyObject* PyInterpreterState_GetDict(PyInterpreterState*); 356 } 357 358 version(Python_3_0_Or_Later) { 359 /// Availability: 3.* 360 int _PyState_AddModule(PyObject*, PyModuleDef*); 361 /// Availability: 3.* 362 PyObject* PyState_FindModule(PyModuleDef*); 363 } 364 365 /// _ 366 PyThreadState* PyThreadState_New(PyInterpreterState *); 367 version(Python_2_6_Or_Later){ 368 /// Availability: >= 2.6 369 PyThreadState * _PyThreadState_Prealloc(PyInterpreterState *); 370 /// Availability: >= 2.6 371 void _PyThreadState_Init(PyThreadState *); 372 } 373 /// _ 374 void PyThreadState_Clear(PyThreadState *); 375 /// _ 376 void PyThreadState_Delete(PyThreadState *); 377 /// _ 378 void PyThreadState_DeleteCurrent(); 379 version(Python_3_0_Or_Later) { 380 /// Availability: 3.* 381 void _PyGILState_Reinit(); 382 } 383 384 /// _ 385 PyThreadState* PyThreadState_Get(); 386 /// _ 387 PyThreadState* PyThreadState_Swap(PyThreadState*); 388 /// _ 389 PyObject_BorrowedRef* PyThreadState_GetDict(); 390 /// _ 391 int PyThreadState_SetAsyncExc(C_long, PyObject*); 392 393 version(Python_3_3_Or_Later) { 394 /// _ 395 auto PyThreadState_GET()() { 396 return PyThreadState_Get(); 397 } 398 } else version(Python_3_0_Or_Later) { 399 /// _ 400 mixin(PyAPI_DATA!"_Py_atomic_address _PyThreadState_Current"); 401 402 /// _ 403 auto PyThreadState_GET()() { 404 return cast(PyThreadState*) 405 _Py_atomic_load_relaxed(&_PyThreadState_Current); 406 } 407 } else { 408 /// _ 409 mixin(PyAPI_DATA!"PyThreadState* _PyThreadState_Current"); 410 411 /// _ 412 auto PyThreadState_GET()() { 413 return _PyThreadState_Current; 414 } 415 } 416 417 /// _ 418 enum PyGILState_STATE { 419 /// _ 420 PyGILState_LOCKED, 421 /// _ 422 PyGILState_UNLOCKED 423 }; 424 425 /** Ensure that the current thread is ready to call the Python 426 C API, regardless of the current state of Python, or of its 427 thread lock. This may be called as many times as desired 428 by a thread so long as each call is matched with a call to 429 PyGILState_Release(). In general, other thread-state APIs may 430 be used between _Ensure() and _Release() calls, so long as the 431 thread-state is restored to its previous state before the Release(). 432 For example, normal use of the Py_BEGIN_ALLOW_THREADS/ 433 Py_END_ALLOW_THREADS macros are acceptable. 434 435 The return value is an opaque "handle" to the thread state when 436 PyGILState_Ensure() was called, and must be passed to 437 PyGILState_Release() to ensure Python is left in the same state. Even 438 though recursive calls are allowed, these handles can *not* be shared - 439 each unique call to PyGILState_Ensure must save the handle for its 440 call to PyGILState_Release. 441 442 When the function returns, the current thread will hold the GIL. 443 444 Failure is a fatal error. 445 */ 446 PyGILState_STATE PyGILState_Ensure(); 447 448 /** Release any resources previously acquired. After this call, Python's 449 state will be the same as it was prior to the corresponding 450 PyGILState_Ensure() call (but generally this state will be unknown to 451 the caller, hence the use of the GILState API.) 452 453 Every call to PyGILState_Ensure must be matched by a call to 454 PyGILState_Release on the same thread. 455 */ 456 void PyGILState_Release(PyGILState_STATE); 457 458 /** Helper/diagnostic function - get the current thread state for 459 this thread. May return NULL if no GILState API has been used 460 on the current thread. Note that the main thread always has such a 461 thread-state, even if no auto-thread-state call has been made 462 on the main thread. 463 */ 464 PyThreadState* PyGILState_GetThisThreadState(); 465 /// _ 466 PyInterpreterState* PyInterpreterState_Head(); 467 /// _ 468 PyInterpreterState* PyInterpreterState_Next(PyInterpreterState*); 469 /// _ 470 PyThreadState* PyInterpreterState_ThreadHead(PyInterpreterState*); 471 /// _ 472 PyThreadState* PyThreadState_Next(PyThreadState*); 473 474 /// _ 475 alias PyFrameObject* function(PyThreadState* self_) PyThreadFrameGetter; 476 477 /// _ 478 mixin(PyAPI_DATA!"PyThreadFrameGetter _PyThreadState_GetFrame");