From 51fcc9a75992ad77d5a83d004e86b4e2b0ba446e Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Thu, 14 Jul 2022 09:05:35 +0300 Subject: [PATCH] Do not use assembly in GC_get_procedure_stack (E2K) (a cherry-pick of commits d3f5bdc3e, 41d41c309 from 'master') Issue #411 (bdwgc). Use E2K_GET_PROCEDURE_STACK_SIZE and E2K_READ_PROCEDURE_STACK_EX sub-functions (of access_hw_stacks syscall) instead of the legacy E2K_READ_PROCEDURE_STACK one which required computation of ps_index manually. Check the stack size right before reading the stack (to avoid EINVAL). * mach_dep.c [E2K] (VA_SIZE, E2K_PSHTP_SIZE, VLIW_CMD_BRACES_PREFIX, get_stack_index): Remove macro. * mach_dep.c [E2K] (GC_get_procedure_stack): Initialize new_sz only if buf is null; define stack_ofs local variable instead of ps; add assertion that new_sz is non-zero and multiple of word size; use E2K_GET_PROCEDURE_STACK_SIZE sub-function instead of E2K_READ_PROCEDURE_STACK to get H/W procedure stack size (call E2K_GET_PROCEDURE_STACK_SIZE sub-function right before E2K_READ_PROCEDURE_STACK_EX one to check that the procedure stack size has not changed since the previous call of GC_get_procedure_stack(NULL,0)); do not use get_stack_index(); use E2K_READ_PROCEDURE_STACK_EX sub-function (with stack_ofs=0) instead of E2K_READ_PROCEDURE_STACK to read H/W procedure stack from the given stack_ofs; print new_sz (in addition to errno) in case of error and not EAGAIN; add comment. * mach_dep.c [E2K && LOG_E2K_ALLOCS] (GC_get_procedure_stack): Remove code. * mach_dep.c [E2K && THREADS] (GC_alloc_and_get_procedure_stack): Add TODO item. --- mach_dep.c | 82 +++++++++++++++--------------------------------------- 1 file changed, 22 insertions(+), 60 deletions(-) diff --git a/mach_dep.c b/mach_dep.c index 343add383..99c01a5fa 100644 --- a/mach_dep.c +++ b/mach_dep.c @@ -32,69 +32,33 @@ # include # include -# define VA_SIZE 48 -# define E2K_PSHTP_SIZE 12 - -# if defined(__clang__) -# define VLIW_CMD_BRACES_PREFIX "%" /* a workaround for clang-9 */ -# else -# define VLIW_CMD_BRACES_PREFIX /* empty */ -# endif - -# define get_stack_index(ps_ptr) \ - do { \ - word psp_lo, psp_hi; \ - signed_word pshtp; \ - char tmp = 0, val; \ - \ - __asm__ __volatile__ ( \ - "1:\n\t" \ - "ldb %4, 0, %0, mas = 7\n\t" \ - "rrd %%pshtp, %1\n\t" \ - "rrd %%psp.lo, %2\n\t" \ - "rrd %%psp.hi, %3\n\t" \ - VLIW_CMD_BRACES_PREFIX "{\n\t" \ - " stb %4, 0, %0, mas = 2\n\t" \ - " rbranch 1b\n\t" \ - VLIW_CMD_BRACES_PREFIX "}" \ - : "=&r" (val), "=&r" (pshtp), \ - "=&r" (psp_lo), "=&r" (psp_hi) \ - : "r" (&tmp)); \ - *(ps_ptr) = (psp_lo & ((1UL<> (63-E2K_PSHTP_SIZE)); \ - } while (0) - GC_INNER size_t GC_get_procedure_stack(ptr_t buf, size_t buf_sz) { - word ps; - word new_sz = 0; + word new_sz; GC_ASSERT(0 == buf_sz || buf != NULL); for (;;) { - get_stack_index(&ps); - if (syscall(__NR_access_hw_stacks, E2K_READ_PROCEDURE_STACK, - &ps, buf, buf_sz, &new_sz) != -1) - break; - - if (ENOMEM == errno && (word)buf_sz < new_sz) { -# ifdef LOG_E2K_ALLOCS - if (buf_sz > 0) /* probably may happen */ - GC_log_printf("GC_get_procedure_stack():" - " buffer size/requested %lu/%lu bytes, GC #%lu\n", - (unsigned long)buf_sz, (unsigned long)new_sz, - (unsigned long)GC_gc_no); -# endif - return (size_t)new_sz; /* buffer not enough */ - } else if (errno != EAGAIN) { - ABORT_ARG1("Cannot read procedure stack", ": errno= %d", errno); + word stack_ofs; + + new_sz = 0; + if (syscall(__NR_access_hw_stacks, E2K_GET_PROCEDURE_STACK_SIZE, + NULL, NULL, 0, &new_sz) == -1) { + if (errno != EAGAIN) + ABORT_ARG1("Cannot get size of procedure stack", + ": errno= %d", errno); + continue; } + GC_ASSERT(new_sz > 0 && new_sz % sizeof(word) == 0); + if (new_sz > buf_sz) + break; + /* Immediately read the stack right after checking its size. */ + stack_ofs = 0; + if (syscall(__NR_access_hw_stacks, E2K_READ_PROCEDURE_STACK_EX, + &stack_ofs, buf, new_sz, NULL) != -1) + break; + if (errno != EAGAIN) + ABORT_ARG2("Cannot read procedure stack", + ": new_sz= %lu, errno= %d", (unsigned long)new_sz, errno); } - - if ((word)buf_sz < new_sz) - ABORT_ARG2("Buffer overflow while reading procedure stack", - ": buf_sz= %lu, new_sz= %lu", - (unsigned long)buf_sz, (unsigned long)new_sz); return (size_t)new_sz; } @@ -124,6 +88,7 @@ # ifdef THREADS GC_INNER size_t GC_alloc_and_get_procedure_stack(ptr_t *pbuf) { + /* TODO: support saving from non-zero ofs in stack */ ptr_t buf = NULL; size_t new_sz, buf_sz; @@ -142,9 +107,6 @@ return new_sz; } # endif /* THREADS */ - -# undef VLIW_CMD_BRACES_PREFIX -# undef get_stack_index #endif /* E2K */ #if defined(MACOS) && defined(__MWERKS__)