Author: Nicolas Truessel <ntrues...@njsm.de> Branch: quad-color-gc Changeset: r87021:636d1082681c Date: 2016-09-12 11:08 +0200 http://bitbucket.org/pypy/pypy/changeset/636d1082681c/
Log: Update qcgc codebase diff --git a/rpython/translator/c/src/qcgc/allocator.c b/rpython/translator/c/src/qcgc/allocator.c --- a/rpython/translator/c/src/qcgc/allocator.c +++ b/rpython/translator/c/src/qcgc/allocator.c @@ -215,7 +215,7 @@ object_t *qcgc_fit_allocate(size_t bytes) { #if CHECKED - free_list_consistency_check(); + //free_list_consistency_check(); #endif size_t cells = bytes_to_cells(bytes); cell_t *mem; diff --git a/rpython/translator/c/src/qcgc/config.h b/rpython/translator/c/src/qcgc/config.h --- a/rpython/translator/c/src/qcgc/config.h +++ b/rpython/translator/c/src/qcgc/config.h @@ -13,8 +13,7 @@ #define LOG_ALLOCATION 0 // Enable allocation log (warning: // significant performance impact) -#define QCGC_SHADOWSTACK_SIZE 128 // Number of initial entries for - // shadow stack +#define QCGC_SHADOWSTACK_SIZE 163840 // Total shadowstack size #define QCGC_ARENA_BAG_INIT_SIZE 16 // Initial size of the arena bag #define QCGC_ARENA_SIZE_EXP 20 // Between 16 (64kB) and 20 (1MB) #define QCGC_LARGE_ALLOC_THRESHOLD_EXP 14 // Less than QCGC_ARENA_SIZE_EXP @@ -52,3 +51,4 @@ #define MAX(a,b) (((a)>(b))?(a):(b)) #define MIN(a,b) (((a)<(b))?(a):(b)) +#define UNUSED(x) (void)(x) diff --git a/rpython/translator/c/src/qcgc/gc_state.h b/rpython/translator/c/src/qcgc/gc_state.h --- a/rpython/translator/c/src/qcgc/gc_state.h +++ b/rpython/translator/c/src/qcgc/gc_state.h @@ -25,7 +25,8 @@ * Global state of the garbage collector */ struct qcgc_state { - shadow_stack_t *shadow_stack; + object_t **shadow_stack; + object_t **shadow_stack_base; shadow_stack_t *prebuilt_objects; weakref_bag_t *weakrefs; gray_stack_t *gp_gray_stack; diff --git a/rpython/translator/c/src/qcgc/qcgc.c b/rpython/translator/c/src/qcgc/qcgc.c --- a/rpython/translator/c/src/qcgc/qcgc.c +++ b/rpython/translator/c/src/qcgc/qcgc.c @@ -5,10 +5,12 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <sys/mman.h> #include "allocator.h" +#include "event_logger.h" #include "hugeblocktable.h" -#include "event_logger.h" +#include "signal_handler.h" #define env_or_fallback(var, env_name, fallback) while(0) { \ char *env_val = getenv(env_name); \ @@ -28,9 +30,11 @@ static size_t incmark_threshold = QCGC_INCMARK_THRESHOLD; QCGC_STATIC void update_weakrefs(void); +QCGC_STATIC void initialize_shadowstack(void); +QCGC_STATIC void destroy_shadowstack(void); void qcgc_initialize(void) { - qcgc_state.shadow_stack = qcgc_shadow_stack_create(QCGC_SHADOWSTACK_SIZE); + initialize_shadowstack(); qcgc_state.prebuilt_objects = qcgc_shadow_stack_create(16); // XXX qcgc_state.weakrefs = qcgc_weakref_bag_create(16); // XXX qcgc_state.gp_gray_stack = qcgc_gray_stack_create(16); // XXX @@ -47,13 +51,15 @@ env_or_fallback(major_collection_threshold, "QCGC_MAJOR_COLLECTION", QCGC_MAJOR_COLLECTION_THRESHOLD); env_or_fallback(incmark_threshold, "QCGC_INCMARK", QCGC_INCMARK_THRESHOLD); + + setup_signal_handler(); } void qcgc_destroy(void) { qcgc_event_logger_destroy(); qcgc_hbtable_destroy(); qcgc_allocator_destroy(); - free(qcgc_state.shadow_stack); + destroy_shadowstack(); free(qcgc_state.prebuilt_objects); free(qcgc_state.weakrefs); free(qcgc_state.gp_gray_stack); @@ -67,14 +73,14 @@ qcgc_state.phase = GC_MARK; qcgc_push_object(object); } - qcgc_state.shadow_stack = - qcgc_shadow_stack_push(qcgc_state.shadow_stack, object); + + *qcgc_state.shadow_stack = object; + qcgc_state.shadow_stack++; } object_t *qcgc_shadowstack_pop(void) { - object_t *result = qcgc_shadow_stack_top(qcgc_state.shadow_stack); - qcgc_state.shadow_stack = qcgc_shadow_stack_pop(qcgc_state.shadow_stack); - return result; + qcgc_state.shadow_stack--; + return *qcgc_state.shadow_stack; } /******************************************************************************* @@ -225,8 +231,10 @@ // If we do this for the first time, push all roots. // All further changes to the roots (new additions) will be added // by qcgc_shadowstack_push - for (size_t i = 0; i < qcgc_state.shadow_stack->count; i++) { - qcgc_push_object(qcgc_state.shadow_stack->items[i]); + for (object_t **it = qcgc_state.shadow_stack_base; + it < qcgc_state.shadow_stack; + it++) { + qcgc_push_object(*it); } // If we do this for the first time, push all prebuilt objects. @@ -483,3 +491,28 @@ } } } + +QCGC_STATIC void *trap_page_addr(object_t **shadow_stack) { + object_t **shadow_stack_end = shadow_stack + QCGC_SHADOWSTACK_SIZE; + char *in_trap_page = (((char *)shadow_stack_end) + 4095); + void *rounded_trap_page = (void *)(((uintptr_t)in_trap_page) & (~4095)); + return rounded_trap_page; +} + +QCGC_STATIC void initialize_shadowstack(void) { + size_t stack_size = QCGC_SHADOWSTACK_SIZE * sizeof(object_t *); + // allocate stack + size for alignement + trap page + object_t **stack = (object_t **) malloc(stack_size + 8192); + assert(stack != NULL); + mprotect(trap_page_addr(stack), 4096, PROT_NONE); + + qcgc_state.shadow_stack = stack; + qcgc_state.shadow_stack_base = stack; +} + +QCGC_STATIC void destroy_shadowstack(void) { + mprotect(trap_page_addr(qcgc_state.shadow_stack_base), 4096, PROT_READ | + PROT_WRITE); + + free(qcgc_state.shadow_stack_base); +} diff --git a/rpython/translator/c/src/qcgc/signal_handler.c b/rpython/translator/c/src/qcgc/signal_handler.c new file mode 100644 --- /dev/null +++ b/rpython/translator/c/src/qcgc/signal_handler.c @@ -0,0 +1,61 @@ +#include "signal_handler.h" + +#include <signal.h> +#include <stdbool.h> +#include <stdlib.h> +#include <stdio.h> + +#include "arena.h" +#include "allocator.h" +#include "gc_state.h" + +QCGC_STATIC void handle_error(int signo, siginfo_t *siginfo, void *context); +QCGC_STATIC bool is_stack_overflow(void *addr); +QCGC_STATIC bool is_in_arena(void *addr); + +void setup_signal_handler(void) { + struct sigaction sa; + + sa.sa_handler = NULL; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_SIGINFO | SA_NODEFER; + sa.sa_sigaction = &handle_error; + + if (sigaction(SIGSEGV, &sa, NULL) < 0) { + perror("sigaction"); + abort(); + } +} + +QCGC_STATIC void handle_error(int signo, siginfo_t *siginfo, void *context) { + UNUSED(signo); + UNUSED(context); + + if (is_stack_overflow(siginfo->si_addr)) { + fprintf(stderr, "Stack overflow: Too many root objects\n"); + } else if (is_in_arena(siginfo->si_addr)) { + fprintf(stderr, "Internal segmentation fault: accessing %p\n", + siginfo->si_addr); + } else { + fprintf(stderr, "External segmentation fault: accessing %p\n", + siginfo->si_addr); + } + exit(EXIT_FAILURE); +} + +QCGC_STATIC bool is_stack_overflow(void *addr) { + void *shadow_stack_end = (void *)(qcgc_state.shadow_stack_base + + QCGC_SHADOWSTACK_SIZE); + return (addr >= shadow_stack_end && addr < shadow_stack_end + 8192); +} + +QCGC_STATIC bool is_in_arena(void *addr) { + arena_t *arena = qcgc_arena_addr((cell_t *) addr); + size_t count = qcgc_allocator_state.arenas->count; + for (size_t i = 0; i < count; i++) { + if (arena == qcgc_allocator_state.arenas->items[i]) { + return true; + } + } + return false; +} diff --git a/rpython/translator/c/src/qcgc/signal_handler.h b/rpython/translator/c/src/qcgc/signal_handler.h new file mode 100644 --- /dev/null +++ b/rpython/translator/c/src/qcgc/signal_handler.h @@ -0,0 +1,5 @@ +#pragma once + +#include "config.h" + +void setup_signal_handler(void); _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit