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");