Skip to content

REVIEW ONLY: first steps making GC reentrant #913

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
318 changes: 244 additions & 74 deletions py/gc.c

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions py/gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,12 @@ void gc_init(void *start, void *end);

// These lock/unlock functions can be nested.
// They can be used to prevent the GC from allocating/freeing.
void gc_lock(void);
void gc_unlock(void);
bool gc_is_locked(void);
void gc_disable(void);
void gc_enable(void);

// A given port must implement gc_collect by using the other collect functions.
void gc_collect(void);
void gc_collect_start(void);
bool gc_collect_start(void); // returns true if collection can proceed
void gc_collect_root(void **ptrs, mp_uint_t len);
void gc_collect_end(void);

Expand Down
12 changes: 6 additions & 6 deletions py/modgc.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,19 @@ MP_DEFINE_CONST_FUN_OBJ_0(gc_collect_obj, py_gc_collect);

/// \function disable()
/// Disable the garbage collector.
STATIC mp_obj_t gc_disable(void) {
gc_lock();
STATIC mp_obj_t mod_gc_disable(void) {
gc_disable();
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_0(gc_disable_obj, gc_disable);
MP_DEFINE_CONST_FUN_OBJ_0(gc_disable_obj, mod_gc_disable);

/// \function enable()
/// Enable the garbage collector.
STATIC mp_obj_t gc_enable(void) {
gc_unlock();
STATIC mp_obj_t mod_gc_enable(void) {
gc_enable();
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_0(gc_enable_obj, gc_enable);
MP_DEFINE_CONST_FUN_OBJ_0(gc_enable_obj, mod_gc_enable);

/// \function mem_free()
/// Return the number of bytes of available heap RAM.
Expand Down
3 changes: 2 additions & 1 deletion py/objexcept.c
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,8 @@ void mp_obj_exception_clear_traceback(mp_obj_t self_in) {
void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, mp_uint_t line, qstr block) {
GET_NATIVE_EXCEPTION(self, self_in);

#if MICROPY_ENABLE_GC
#if 0 && MICROPY_ENABLE_GC
// TODO
if (gc_is_locked()) {
if (self->traceback == MP_OBJ_NULL) {
// We can't allocate any memory, and no memory has been
Expand Down
13 changes: 2 additions & 11 deletions py/runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -1208,17 +1208,8 @@ mp_obj_t mp_parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t parse_i

void *m_malloc_fail(size_t num_bytes) {
DEBUG_printf("memory allocation failed, allocating " UINT_FMT " bytes\n", num_bytes);
if (0) {
// dummy
#if MICROPY_ENABLE_GC
} else if (gc_is_locked()) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_MemoryError,
"memory allocation failed, heap is locked"));
#endif
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError,
"memory allocation failed, allocating " UINT_FMT " bytes", num_bytes));
}
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError,
"memory allocation failed, allocating " UINT_FMT " bytes", num_bytes));
}

NORETURN void mp_not_implemented(const char *msg) {
Expand Down
4 changes: 0 additions & 4 deletions stmhal/extint.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,9 +361,6 @@ void Handle_EXTI_Irq(uint32_t line) {
if (line < EXTI_NUM_VECTORS) {
extint_vector_t *v = &extint_vector[line];
if (v->callback_obj != mp_const_none) {
// When executing code within a handler we must lock the GC to prevent
// any memory allocations. We must also catch any exceptions.
gc_lock();
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
mp_call_function_1(v->callback_obj, MP_OBJ_NEW_SMALL_INT(line));
Expand All @@ -375,7 +372,6 @@ void Handle_EXTI_Irq(uint32_t line) {
printf("Uncaught exception in ExtInt interrupt handler line %lu\n", line);
mp_obj_print_exception((mp_obj_t)nlr.ret_val);
}
gc_unlock();
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion stmhal/gccollect.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ void gc_collect(void) {
uint32_t start = HAL_GetTick();

// start the GC
gc_collect_start();
if (!gc_collect_start()) {
// gc is already running
return;
}

// We need to scan everything in RAM that can hold a pointer.
// The data segment is used, but should not contain pointers, so we just scan the bss.
Expand Down
4 changes: 0 additions & 4 deletions stmhal/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -1229,9 +1229,6 @@ STATIC void timer_handle_irq_channel(pyb_timer_obj_t *tim, uint8_t channel, mp_o

// execute callback if it's set
if (callback != mp_const_none) {
// When executing code within a handler we must lock the GC to prevent
// any memory allocations. We must also catch any exceptions.
gc_lock();
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
mp_call_function_1(callback, tim);
Expand All @@ -1247,7 +1244,6 @@ STATIC void timer_handle_irq_channel(pyb_timer_obj_t *tim, uint8_t channel, mp_o
}
mp_obj_print_exception((mp_obj_t)nlr.ret_val);
}
gc_unlock();
}
}
}
Expand Down
6 changes: 5 additions & 1 deletion unix/gccollect.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,11 @@ void gc_helper_get_regs(regs_t arr) {
void gc_collect(void) {
//gc_dump_info();

gc_collect_start();
if (!gc_collect_start()) {
// gc is already running
return;
}

// this traces the .bss section
#if defined( __CYGWIN__ )
#define BSS_START __bss_start__
Expand Down
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy