1 /*
2  * This file is part of the MicroPython project, http://micropython.org/
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2014 Damien P. George
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24  * THE SOFTWARE.
25  */
26 #ifndef MICROPY_INCLUDED_PY_MPSTATE_H
27 #define MICROPY_INCLUDED_PY_MPSTATE_H
28 
29 #include <stdint.h>
30 
31 #include "py/mpconfig.h"
32 #include "py/mpthread.h"
33 #include "py/misc.h"
34 #include "py/nlr.h"
35 #include "py/obj.h"
36 #include "py/objlist.h"
37 #include "py/objexcept.h"
38 
39 // This file contains structures defining the state of the MicroPython
40 // memory system, runtime and virtual machine.  The state is a global
41 // variable, but in the future it is hoped that the state can become local.
42 
43 // This structure contains dynamic configuration for the compiler.
44 #if MICROPY_DYNAMIC_COMPILER
45 typedef struct mp_dynamic_compiler_t {
46     uint8_t small_int_bits; // must be <= host small_int_bits
47     bool opt_cache_map_lookup_in_bytecode;
48     bool py_builtins_str_unicode;
49     uint8_t native_arch;
50     uint8_t nlr_buf_num_regs;
51 } mp_dynamic_compiler_t;
52 extern mp_dynamic_compiler_t mp_dynamic_compiler;
53 #endif
54 
55 // These are the values for sched_state
56 #define MP_SCHED_IDLE (1)
57 #define MP_SCHED_LOCKED (-1)
58 #define MP_SCHED_PENDING (0) // 0 so it's a quick check in the VM
59 
60 typedef struct _mp_sched_item_t {
61     mp_obj_t func;
62     mp_obj_t arg;
63 } mp_sched_item_t;
64 
65 // This structure hold information about the memory allocation system.
66 typedef struct _mp_state_mem_t {
67     #if MICROPY_MEM_STATS
68     size_t total_bytes_allocated;
69     size_t current_bytes_allocated;
70     size_t peak_bytes_allocated;
71     #endif
72 
73     byte *gc_alloc_table_start;
74     size_t gc_alloc_table_byte_len;
75     #if MICROPY_ENABLE_FINALISER
76     byte *gc_finaliser_table_start;
77     #endif
78     byte *gc_pool_start;
79     byte *gc_pool_end;
80 
81     int gc_stack_overflow;
82     MICROPY_GC_STACK_ENTRY_TYPE gc_stack[MICROPY_ALLOC_GC_STACK_SIZE];
83 
84     // This variable controls auto garbage collection.  If set to 0 then the
85     // GC won't automatically run when gc_alloc can't find enough blocks.  But
86     // you can still allocate/free memory and also explicitly call gc_collect.
87     uint16_t gc_auto_collect_enabled;
88 
89     #if MICROPY_GC_ALLOC_THRESHOLD
90     size_t gc_alloc_amount;
91     size_t gc_alloc_threshold;
92     #endif
93 
94     size_t gc_last_free_atb_index;
95 
96     #if MICROPY_PY_GC_COLLECT_RETVAL
97     size_t gc_collected;
98     #endif
99 
100     #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL
101     // This is a global mutex used to make the GC thread-safe.
102     mp_thread_mutex_t gc_mutex;
103     #endif
104 } mp_state_mem_t;
105 
106 // This structure hold runtime and VM information.  It includes a section
107 // which contains root pointers that must be scanned by the GC.
108 typedef struct _mp_state_vm_t {
109     //
110     // CONTINUE ROOT POINTER SECTION
111     // This must start at the start of this structure and follows
112     // the state in the mp_state_thread_t structure, continuing
113     // the root pointer section from there.
114     //
115 
116     qstr_pool_t *last_pool;
117 
118     // non-heap memory for creating an exception if we can't allocate RAM
119     mp_obj_exception_t mp_emergency_exception_obj;
120 
121     // memory for exception arguments if we can't allocate RAM
122     #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF
123     #if MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE > 0
124     // statically allocated buf (needs to be aligned to mp_obj_t)
125     mp_obj_t mp_emergency_exception_buf[MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE / sizeof(mp_obj_t)];
126     #else
127     // dynamically allocated buf
128     byte *mp_emergency_exception_buf;
129     #endif
130     #endif
131 
132     #if MICROPY_KBD_EXCEPTION
133     // exception object of type KeyboardInterrupt
134     mp_obj_exception_t mp_kbd_exception;
135     #endif
136 
137     // dictionary with loaded modules (may be exposed as sys.modules)
138     mp_obj_dict_t mp_loaded_modules_dict;
139 
140     #if MICROPY_ENABLE_SCHEDULER
141     mp_sched_item_t sched_queue[MICROPY_SCHEDULER_DEPTH];
142     #endif
143 
144     // current exception being handled, for sys.exc_info()
145     #if MICROPY_PY_SYS_EXC_INFO
146     mp_obj_base_t *cur_exception;
147     #endif
148 
149     #if MICROPY_PY_SYS_ATEXIT
150     // exposed through sys.atexit function
151     mp_obj_t sys_exitfunc;
152     #endif
153 
154     // dictionary for the __main__ module
155     mp_obj_dict_t dict_main;
156 
157     // these two lists must be initialised per port, after the call to mp_init
158     mp_obj_list_t mp_sys_path_obj;
159     mp_obj_list_t mp_sys_argv_obj;
160 
161     // dictionary for overridden builtins
162     #if MICROPY_CAN_OVERRIDE_BUILTINS
163     mp_obj_dict_t *mp_module_builtins_override_dict;
164     #endif
165 
166     #if MICROPY_PERSISTENT_CODE_TRACK_RELOC_CODE
167     // An mp_obj_list_t that tracks relocated native code to prevent the GC from reclaiming them.
168     mp_obj_t track_reloc_code_list;
169     #endif
170 
171     // include any root pointers defined by a port
172     MICROPY_PORT_ROOT_POINTERS
173 
174     // root pointers for extmod
175 
176     #if MICROPY_REPL_EVENT_DRIVEN
177     vstr_t *repl_line;
178     #endif
179 
180     #if MICROPY_PY_OS_DUPTERM
181     mp_obj_t dupterm_objs[MICROPY_PY_OS_DUPTERM];
182     #endif
183 
184     #if MICROPY_PY_LWIP_SLIP
185     mp_obj_t lwip_slip_stream;
186     #endif
187 
188     #if MICROPY_VFS
189     struct _mp_vfs_mount_t *vfs_cur;
190     struct _mp_vfs_mount_t *vfs_mount_table;
191     #endif
192 
193     #if MICROPY_PY_BLUETOOTH
194     mp_obj_t bluetooth;
195     #endif
196 
197     //
198     // END ROOT POINTER SECTION
199     ////////////////////////////////////////////////////////////
200 
201     // pointer and sizes to store interned string data
202     // (qstr_last_chunk can be root pointer but is also stored in qstr pool)
203     byte *qstr_last_chunk;
204     size_t qstr_last_alloc;
205     size_t qstr_last_used;
206 
207     #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL
208     // This is a global mutex used to make qstr interning thread-safe.
209     mp_thread_mutex_t qstr_mutex;
210     #endif
211 
212     #if MICROPY_ENABLE_COMPILER
213     mp_uint_t mp_optimise_value;
214     #if MICROPY_EMIT_NATIVE
215     uint8_t default_emit_opt; // one of MP_EMIT_OPT_xxx
216     #endif
217     #endif
218 
219     // size of the emergency exception buf, if it's dynamically allocated
220     #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF && MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE == 0
221     mp_int_t mp_emergency_exception_buf_size;
222     #endif
223 
224     #if MICROPY_ENABLE_SCHEDULER
225     volatile int16_t sched_state;
226     uint8_t sched_len;
227     uint8_t sched_idx;
228     #endif
229 
230     #if MICROPY_PY_THREAD_GIL
231     // This is a global mutex used to make the VM/runtime thread-safe.
232     mp_thread_mutex_t gil_mutex;
233     #endif
234 } mp_state_vm_t;
235 
236 // This structure holds state that is specific to a given thread.
237 // Everything in this structure is scanned for root pointers.
238 typedef struct _mp_state_thread_t {
239     // Stack top at the start of program
240     char *stack_top;
241 
242     #if MICROPY_STACK_CHECK
243     size_t stack_limit;
244     #endif
245 
246     #if MICROPY_ENABLE_PYSTACK
247     uint8_t *pystack_start;
248     uint8_t *pystack_end;
249     uint8_t *pystack_cur;
250     #endif
251 
252     // Locking of the GC is done per thread.
253     uint16_t gc_lock_depth;
254 
255     ////////////////////////////////////////////////////////////
256     // START ROOT POINTER SECTION
257     // Everything that needs GC scanning must start here, and
258     // is followed by state in the mp_state_vm_t structure.
259     //
260 
261     mp_obj_dict_t *dict_locals;
262     mp_obj_dict_t *dict_globals;
263 
264     nlr_buf_t *nlr_top;
265 
266     // pending exception object (MP_OBJ_NULL if not pending)
267     volatile mp_obj_t mp_pending_exception;
268 
269     // If MP_OBJ_STOP_ITERATION is propagated then this holds its argument.
270     mp_obj_t stop_iteration_arg;
271 
272     #if MICROPY_PY_SYS_SETTRACE
273     mp_obj_t prof_trace_callback;
274     bool prof_callback_is_executing;
275     struct _mp_code_state_t *current_code_state;
276     #endif
277 } mp_state_thread_t;
278 
279 // This structure combines the above 3 structures.
280 // The order of the entries are important for root pointer scanning in the GC to work.
281 typedef struct _mp_state_ctx_t {
282     mp_state_thread_t thread;
283     mp_state_vm_t vm;
284     mp_state_mem_t mem;
285 } mp_state_ctx_t;
286 
287 extern mp_state_ctx_t mp_state_ctx;
288 
289 #define MP_STATE_VM(x) (mp_state_ctx.vm.x)
290 #define MP_STATE_MEM(x) (mp_state_ctx.mem.x)
291 #define MP_STATE_MAIN_THREAD(x) (mp_state_ctx.thread.x)
292 
293 #if MICROPY_PY_THREAD
294 extern mp_state_thread_t *mp_thread_get_state(void);
295 #define MP_STATE_THREAD(x) (mp_thread_get_state()->x)
296 #else
297 #define MP_STATE_THREAD(x)  MP_STATE_MAIN_THREAD(x)
298 #endif
299 
300 #endif // MICROPY_INCLUDED_PY_MPSTATE_H
301