summaryrefslogtreecommitdiff
path: root/py/gc.c
AgeCommit message (Collapse)Author
2023-05-09py/gc: Make improvements to MICROPY_GC_HOOK_LOOP.David Lechner
Changes in this commit: - Add MICROPY_GC_HOOK_LOOP to gc_info() and gc_alloc(). Both of these can be long running (many milliseconds) which is too long to be blocking in some applications. - Pass loop variable to MICROPY_GC_HOOK_LOOP(i) macro so that implementers can use it, e.g. to improve performance by only calling a function every X number of iterations. - Drop outer call to MICROPY_GC_HOOK_LOOP in gc_mark_subtree().
2023-04-27all: Fix spelling mistakes based on codespell check.Damien George
Signed-off-by: Damien George <damien@micropython.org>
2023-04-26extmod/btstack: Fix indicate/notify queuing.Jim Mussared
This adds a mechanism to track a pending notify/indicate operation that is deferred due to the send buffer being full. This uses a tracked alloc that is passed as the content arg to the callback. This replaces the previous mechanism that did this via the global pending op queue, shared with client read/write ops. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-03-10py/gc: Make gc_dump_info/gc_dump_alloc_table take a printer as argument.Damien George
So that callers can redirect the output if needed. Signed-off-by: Damien George <damien@micropython.org>
2023-01-16py/gc: Increase the address length in gc_dump_alloc_table().robert-hh
Showing 8 digits instead of 5, supporting devices with more than 1 MByte of RAM (which is common these days). The masking was never needed, and the related commented-out line can go.
2022-12-08py/gc: Fix debug printing of GC layout.Damien George
Signed-off-by: Damien George <damien@micropython.org>
2022-12-08unix/coverage: Add extra GC coverage test for ATB gap byte.Jeff Epler
The assertion that is added here (to gc.c) fails when running this new test if ALLOC_TABLE_GAP_BYTE is set to 0. Signed-off-by: Jeff Epler <jepler@gmail.com> Signed-off-by: Damien George <damien@micropython.org>
2022-12-08py/gc: Ensure a gap of one byte after the ATB.Jeff Epler
Prior to this fix the follow crash occurred. With a GC layout of: GC layout: alloc table at 0x3fd80428, length 32001 bytes, 128004 blocks finaliser table at 0x3fd88129, length 16001 bytes, 128008 blocks pool at 0x3fd8bfc0, length 2048064 bytes, 128004 blocks Block 128003 is an AT_HEAD and eventually is passed to gc_mark_subtree. This causes gc_mark_subtree to call ATB_GET_KIND(128004). When block 1 is created with a finaliser, the first byte of the finaliser table becomes 0x2, but ATB_GET_KIND(128004) reads these bits as AT_TAIL, and then gc_mark_subtree references past the end of the heap, which happened to be past the end of PSRAM on the esp32-s2. The fix in this commit is to ensure there is a one-byte gap after the ATB filled permanently with AT_FREE. Fixes issue #7116. See also https://github.com/adafruit/circuitpython/issues/5021 Signed-off-by: Jeff Epler <jepler@gmail.com> Signed-off-by: Damien George <damien@micropython.org>
2022-12-08py/gc: Avoid valgrind false positives.Jeff Epler
When you want to use the valgrind memory analysis tool on MicroPython, you can arrange to define MICROPY_DEBUG_VALGRIND to enable use of special valgrind macros. For now, this only fixes `gc_get_ptr` so that it never emits the diagnostic "Conditional jump or move depends on uninitialised value(s)". Signed-off-by: Jeff Epler <jepler@gmail.com>
2022-07-23py/gc: Reduce code size when MICROPY_GC_SPLIT_HEAP is disabled.Rob Knegjens
Use C macros to reduce the size of firmware images when the GC split-heap feature is disabled. The code size difference of this commit versus HEAD~2 (ie the commit prior to MICROPY_GC_SPLIT_HEAP being introduced) when split-heap is disabled is: bare-arm: +0 +0.000% minimal x86: +0 +0.000% unix x64: -16 -0.003% unix nanbox: -20 -0.004% stm32: -8 -0.002% PYBV10 cc3200: +0 +0.000% esp8266: +8 +0.001% GENERIC esp32: +0 +0.000% GENERIC nrf: -20 -0.011% pca10040 rp2: +0 +0.000% PICO samd: -4 -0.003% ADAFRUIT_ITSYBITSY_M4_EXPRESS The code size difference of this commit versus HEAD~2 split-heap is enabled with MICROPY_GC_MULTIHEAP=1 (but no extra code to add more heaps): unix x64: +1032 +0.197% [incl +544(bss)] esp32: +592 +0.039% GENERIC[incl +16(data) +264(bss)]
2022-07-23py/gc: Allow the GC heap to be split over multiple memory areas.Ayke van Laethem
This commit adds a new option MICROPY_GC_SPLIT_HEAP (disabled by default) which, when enabled, allows the GC heap to be split over multiple memory areas/regions. The first area is added with gc_init() and subsequent areas can be added with gc_add(). New areas can be added at runtime. Areas are stored internally as a linked list, and calls to gc_alloc() can be satisfied from any area. This feature has the following use-cases (among others): - The ESP32 has a fragmented OS heap, so to use all (or more) of it the GC heap must be split. - Other MCUs may have disjoint RAM regions and are now able to use them all for the GC heap. - The user could explicitly increase the size of the GC heap. - Support a dynamic heap while running on an OS, adding more heap when necessary.
2022-02-17py/gc: Update debug code to compile with changes to qstr pool types.Damien George
Following on from 18b1ba086c0e5547ca81030bf13b026961f80720 and f46a7140f55a8f6d80f9c2d5f8db7af3de116794. Signed-off-by: Damien George <damien@micropython.org>
2021-11-01py/gc: Add hook to run code during time consuming GC operations.Laurens Valk
This makes it possible for cooperative multitasking systems to keep running event loops during garbage collector operations. For example, this can be used to ensure that a motor control loop runs approximately each 5 ms. Without this hook, the loop time can jump to about 15 ms. Addresses #3475. Signed-off-by: Laurens Valk <laurens@pybricks.com>
2021-06-18py/gc: Only use no_sanitize_address attribute for GCC 4.8 and above.Damien George
It's not supported on older GCC versions. Signed-off-by: Damien George <damien@micropython.org>
2021-05-30py/gc: Access the list of root pointers in an asan-compatible way.Jeff Epler
Signed-off-by: Jeff Epler <jepler@gmail.com>
2021-05-10py/gc: Make gc_lock_depth have a count per thread.Damien George
This commit makes gc_lock_depth have one counter per thread, instead of one global counter. This makes threads properly independent with respect to the GC, in particular threads can now independently lock the GC for themselves without locking it for other threads. It also means a given thread can run a hard IRQ without temporarily locking the GC for all other threads and potentially making them have MemoryError exceptions at random locations (this really only occurs on MCUs with multiple cores and no GIL, eg on the rp2 port). The commit also removes protection of the GC lock/unlock functions, which is no longer needed when the counter is per thread (and this also fixes the cas where a hard IRQ calling gc_lock() may stall waiting for the mutex). It also puts the check for `gc_lock_depth > 0` outside the GC mutex in gc_alloc, gc_realloc and gc_free, to potentially prevent a hard IRQ from waiting on a mutex if it does attempt to allocate heap memory (and putting the check outside the GC mutex is now safe now that there is a gc_lock_depth per thread). Signed-off-by: Damien George <damien@micropython.org>
2021-02-04all: Rename BYTES_PER_WORD to MP_BYTES_PER_OBJ_WORD.Damien George
The "word" referred to by BYTES_PER_WORD is actually the size of mp_obj_t which is not always the same as the size of a pointer on the target architecture. So rename this config value to better reflect what it measures, and also prefix it with MP_. For uses of BYTES_PER_WORD in setting the stack limit this has been changed to sizeof(void *), because the stack usually grows with machine-word sized values (eg an nlr_buf_t has many machine words in it). Signed-off-by: Damien George <damien@micropython.org>
2021-02-04py: Rename BITS_PER_BYTE to MP_BITS_PER_BYTE.Damien George
To give this macro a standard MP_ prefix. Signed-off-by: Damien George <damien@micropython.org>
2021-01-30py/gc: Fix debug printing of pointer.stijn
When DEBUG_printf is the standard printf, compilers require the value for %p to be an actual pointer instead of an integer.
2020-10-22py, extmod: Introduce and use MP_FALLTHROUGH macro.Emil Renner Berthing
Newer GCC versions are able to warn about switch cases that fall through. This is usually a sign of a forgotten break statement, but in the few cases where a fall through is intended we annotate it with this macro to avoid the warning.
2020-04-23all: Format code to add space after C++-style comment start.stijn
Note: the uncrustify configuration is explicitly set to 'add' instead of 'force' in order not to alter the comments which use extra spaces after // as a means of indenting text for clarity.
2020-02-28all: Reformat C and Python source code with tools/codeformat.py.Damien George
This is run with uncrustify 0.70.1, and black 19.10b0.
2020-02-28all: Add *FORMAT-OFF* in various places.Damien George
This string is recognised by uncrustify, to disable formatting in the region marked by these comments. This is necessary in the qstrdef*.h files to prevent modification of the strings within the Q(...). In other places it is used to prevent excessive reformatting that would make the code less readable.
2020-01-23py/gc: Don't include or init gc_mutex when GIL is enabled.David Lechner
When threads and the GIL are enabled, then the GC mutex is not needed. The gc_mutex field is never used in this case because of: #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL #define GC_ENTER() mp_thread_mutex_lock(&MP_STATE_MEM(gc_mutex), 1) #define GC_EXIT() mp_thread_mutex_unlock(&MP_STATE_MEM(gc_mutex)) #else #define GC_ENTER() #define GC_EXIT() #endif So, we can completely remove gc_mutex everywhere when MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL.
2019-05-17various: Add and update my copyright line based on git history.Paul Sokolovsky
For modules I initially created or made substantial contributions to.
2018-12-20py/gc: Adjust gc_alloc() signature to be able to accept multiple flags.Paul Sokolovsky
The older "bool has_finaliser" gets recast as GC_ALLOC_FLAG_HAS_FINALISER=1 so this is a backwards compatible change to the signature. Since bool gets implicitly converted to 1 this patch doesn't include conversion of all calls.
2018-08-14py/gc: In gc_alloc, reset n_free var right before search for free mem.Damien George
Otherwise there is the possibility that n_free starts out non-zero from the previous iteration, which may have found a few (but not enough) free blocks at the end of the heap. If this is the case, and if the very first blocks that are scanned the second time around (starting at gc_last_free_atb_index) are found to give enough memory (including the blocks at the end of the heap from the previous iteration that left n_free non-zero) then memory will be allocated starting before the location that gc_last_free_atb_index points to, most likely leading to corruption. This serious bug did not manifest itself in the past because a gc_collect always resets gc_last_free_atb_index to point to the start of the GC heap, and the first block there is almost always allocated to a long-lived object (eg entries from sys.path, or mounted filesystem objects), which means that n_free would be reset at the start of the search loop. But with threading enabled with the GIL disabled it is possible to trigger the bug via the following sequence of events: 1. Thread A runs gc_alloc, fails to find enough memory, and has a non-zero n_free at the end of the search. 2. Thread A calls gc_collect and frees a bunch of blocks on the GC heap. 3. Just after gc_collect finishes in thread A, thread B takes gc_mutex and does an allocation, moving gc_last_free_atb_index to point to the interior of the heap, to a place where there is most likely a run of available blocks. 4. Thread A regains gc_mutex and does its second search for free memory, starting with a non-zero n_free. Since it's likely that the first block it searches is available it will allocate memory which overlaps with the memory before gc_last_free_atb_index.
2018-08-02py: Fix compiling with debug enabled and make more use of DEBUG_printf.Damien George
DEBUG_printf and MICROPY_DEBUG_PRINTER is now used instead of normal printf, and a fault is fixed in mp_obj_class_lookup with debugging enabled; see issue #3999. Debugging can now be enabled on all ports including when nan-boxing is used.
2018-06-12py/gc: Add gc_sweep_all() function to run all remaining finalisers.Damien George
This patch adds the gc_sweep_all() function which does a garbage collection without tracing any root pointers, so frees all the memory, and most importantly runs any remaining finalisers. This helps primarily for soft reset: it will close any open files, any open sockets, and help to get the system back to a clean state upon soft reset.
2018-05-21py/gc: When GC threshold is hit don't unnecessarily collect twice.Damien George
Without this, if GC threshold is hit and there is not enough memory left to satisfy the request, gc_collect() will run a second time and the search for memory will happen again and will fail again. Thanks to @adritium for pointing out this issue, see #3786.
2018-05-13py/mpstate.h: Adjust start of root pointer section to exclude non-ptrs.Damien George
This patch moves the start of the root pointer section in mp_state_ctx_t so that it skips entries that are not pointers and don't need scanning. Previously, the start of the root pointer section was at the very beginning of the mp_state_ctx_t struct (which is the beginning of mp_state_thread_t). This was the original assembler version of the NLR code was hard-coded to have the nlr_top pointer at the start of this state structure. But now that the NLR code is partially written in C there is no longer this restriction on the location of nlr_top (and a comment to this effect has been removed in this patch). So now the root pointer section starts part way through the mp_state_thread_t structure, after the entries which are not root pointers. This patch also moves the non-pointer entries for MICROPY_ENABLE_SCHEDULER outside the root pointer section. Moving non-pointer entries out of the root pointer section helps to make the GC more precise and should help to prevent some cases of collectable garbage being kept. This patch also has a measurable improvement in performance of the pystone.py benchmark: on unix x86-64 and stm32 there was an improvement of roughly 0.6% (tested with both gcc 7.3 and gcc 8.1).
2018-02-19py/gc: Update comment now that gc_drain_stack is called gc_mark_subtree.Damien George
2018-02-19py/gc: Make GC stack pointer a local variable.Ayke van Laethem
This saves a bit in code size, and saves some precious .bss RAM: .text .bss minimal CROSS=1: -28 -4 unix (64-bit): -64 -8
2018-02-19py/gc: Rename gc_drain_stack to gc_mark_subtree and pass it first block.Ayke van Laethem
This saves a bit in code size: minimal CROSS=1: -44 unix: -96
2018-02-19py/gc: Reduce code size by specialising VERIFY_MARK_AND_PUSH macro.Ayke van Laethem
This macro is written out explicitly in the two locations that it is used and then the code is optimised, opening possibilities for further optimisations and reducing code size: unix: -48 minimal CROSS=1: -32 stm32: -32
2017-12-11py: Introduce a Python stack for scoped allocation.Damien George
This patch introduces the MICROPY_ENABLE_PYSTACK option (disabled by default) which enables a "Python stack" that allows to allocate and free memory in a scoped, or Last-In-First-Out (LIFO) way, similar to alloca(). A new memory allocation API is introduced along with this Py-stack. It includes both "local" and "nonlocal" LIFO allocation. Local allocation is intended to be equivalent to using alloca(), whereby the same function must free the memory. Nonlocal allocation is where another function may free the memory, so long as it's still LIFO. Follow-up patches will convert all uses of alloca() and VLA to the new scoped allocation API. The old behaviour (using alloca()) will still be available, but when MICROPY_ENABLE_PYSTACK is enabled then alloca() is no longer required or used. The benefits of enabling this option are (or will be once subsequent patches are made to convert alloca()/VLA): - Toolchains without alloca() can use this feature to obtain correct and efficient scoped memory allocation (compared to using the heap instead of alloca(), which is slower). - Even if alloca() is available, enabling the Py-stack gives slightly more efficient use of stack space when calling nested Python functions, due to the way that compilers implement alloca(). - Enabling the Py-stack with the stackless mode allows for even more efficient stack usage, as well as retaining high performance (because the heap is no longer used to build and destroy stackless code states). - With Py-stack and stackless enabled, Python-calling-Python is no longer recursive in the C mp_execute_bytecode function. The micropython.pystack_use() function is included to measure usage of the Python stack.
2017-12-09py/gc: In sweep debug output, print pointer as a pointer.Paul Sokolovsky
Or it will be truncated on a 64-bit platform.
2017-12-09py/gc: Factor out a macro to trace GC mark operations.Paul Sokolovsky
To allow easier override it for custom tracing.
2017-12-08py/gc: Add CLEAR_ON_SWEEP option to debug mis-traced objects.Paul Sokolovsky
Accessing them will crash immediately instead still working for some time, until overwritten by some other data, leading to much less deterministic crashes.
2017-11-29py/gc: In gc_realloc, convert pointer sanity checks to assertions.Damien George
These checks are assumed to be true in all cases where gc_realloc is called with a valid pointer, so no need to waste code space and time checking them in a non-debug build.
2017-10-04all: Remove inclusion of internal py header files.Damien George
Header files that are considered internal to the py core and should not normally be included directly are: py/nlr.h - internal nlr configuration and declarations py/bc0.h - contains bytecode macro definitions py/runtime0.h - contains basic runtime enums Instead, the top-level header files to include are one of: py/obj.h - includes runtime0.h and defines everything to use the mp_obj_t type py/runtime.h - includes mpstate.h and hence nlr.h, obj.h, runtime0.h, and defines everything to use the general runtime support functions Additional, specific headers (eg py/objlist.h) can be included if needed.
2017-08-15py: Add verbose debug compile-time flag MICROPY_DEBUG_VERBOSE.Stefan Naumann
It enables all the DEBUG_printf outputs in the py/ source code.
2017-07-31all: Use the name MicroPython consistently in commentsAlexander Steffen
There were several different spellings of MicroPython present in comments, when there should be only one.
2017-07-12py/gc: Refactor assertions in gc_free function.Damien George
gc_free() expects either NULL or a valid pointer into the heap, so the checks for a valid pointer can be turned into assertions.
2017-04-12py/gc: Execute finaliser code in a protected environment.Damien George
If a finaliser raises an exception then it must not propagate through the GC sweep function. This patch protects against such a thing by running finaliser code via the mp_call_function_1_protected call. This patch also adds scheduler lock/unlock calls around the finaliser execution to further protect against any possible reentrancy issues: the memory manager is already locked when doing a collection, but we also don't want to allow any scheduled code to run, KeyboardInterrupts to interupt the code, nor threads to switch.
2016-08-26py/gc: Add MICROPY_GC_CONSERVATIVE_CLEAR option to always zero memory.Damien George
There can be stray pointers in memory blocks that are not properly zero'd after allocation. This patch adds a new config option to always zero all allocated memory (via gc_alloc and gc_realloc) and hence help to eliminate stray pointers. See issue #2195.
2016-07-21py/gc: Implement GC running by allocation threshold.Paul Sokolovsky
Currently, MicroPython runs GC when it could not allocate a block of memory, which happens when heap is exhausted. However, that policy can't work well with "inifinity" heaps, e.g. backed by a virtual memory - there will be a lot of swap thrashing long before VM will be exhausted. Instead, in such cases "allocation threshold" policy is used: a GC is run after some number of allocations have been made. Details vary, for example, number or total amount of allocations can be used, threshold may be self-adjusting based on GC outcome, etc. This change implements a simple variant of such policy for MicroPython. Amount of allocated memory so far is used for threshold, to make it useful to typical finite-size, and small, heaps as used with MicroPython ports. And such GC policy is indeed useful for such types of heaps too, as it allows to better control fragmentation. For example, if a threshold is set to half size of heap, then for an application which usually makes big number of small allocations, that will (try to) keep half of heap memory in a nice defragmented state for an occasional large allocation. For an application which doesn't exhibit such behavior, there won't be any visible effects, except for GC running more frequently, which however may affect performance. To address this, the GC threshold is configurable, and by default is off so far. It's configured with gc.threshold(amount_in_bytes) call (can be queries without an argument).
2016-07-01py/gc: Calculate (and report) maximum contiguous free block size.Paul Sokolovsky
Just as maximum allocated block size, it's reported in allocation units (not bytes).
2016-06-30py/gc: Be sure to count last allocated block at heap end in stats.Paul Sokolovsky
Previously, if there was chain of allocated blocks ending with the last block of heap, it wasn't included in number of 1/2-block or max block size stats.
2016-06-28py: Don't use gc or qstr mutex when the GIL is enabled.Damien George
There is no need since the GIL already makes gc and qstr operations atomic.