summaryrefslogtreecommitdiff
path: root/mach_dep.c
diff options
context:
space:
mode:
authorIlya Kurdyukov <ilyakurdyukov@altlinux.org>2021-07-02 12:00:00 +0700
committerIvan Maidanski <ivmai@mail.ru>2022-01-12 09:59:55 +0300
commit9ddbbae8e860c779d7fa548daceb1130916059ff (patch)
tree272389e85cd443134e6351672ae3a5f4474f7899 /mach_dep.c
parent7ef3eca8a709ce679664e280a44a828fb7caba5e (diff)
downloadbdwgc-9ddbbae8e860c779d7fa548daceb1130916059ff.tar.gz
Support Elbrus 2000 (Linux/e2k)
(a port of altlinux libgc-e2k.patch (8ed786c)) Issue #411 (bdwgc). * include/gc/gc.h [__GNUC__ && !__INTEL_COMPILER && __e2k__] (GC_reachable_here): Specify "r" contraint for ptr. * include/gc/gc.h [__e2k__] (GC_stack_base): Declare reg_base field. * include/private/gc_priv.h [E2K] (GC_push_all_register_sections, GC_save_regs_in_stack, GC_get_procedure_stack): Declare. * include/private/gc_priv.h [E2K && __ptr64__] (LOAD_TAGGED_VALUE): Define macro. * include/private/gc_priv.h (LOAD_WORD_OR_CONTINUE): Likewise. * include/private/gcconfig.h [LINUX && __e2k__] (E2K, mach_type_known): Likewise. * include/private/gcconfig.h [E2K] (MACH_TYPE, CPP_WORDSZ, ALIGNMENT, HBLKSIZE): Likewise. * include/private/gcconfig.h [E2K && LINUX] (DATASTART): Likewise. * mach_dep.c [E2K] (VA_SIZE, E2K_PSHTP_SIZE, get_stack_index): Likewise. * include/private/gcconfig.h [GC_GNUC_PREREQ(2,8)] (HAVE_BUILTIN_UNWIND_INIT): Do not define if E2K. * include/private/gcconfig.h [E2K && LINUX] (__dso_handle): Declare extern variable. * include/private/pthread_support.h [E2K] (GC_Thread_Rep): Declare backing_store_end and backing_store_ptr fields. * mach_dep.c [E2K]: Include errno.h, sys/syscall.h, asm/e2k_syswork.h. * mach_dep.c [E2K] (e2k_rwap_lo_fields, e2k_rwap_hi_fields): Declare struct. * mach_dep.c [E2K] (e2k_rwap_lo_u, e2k_rwap_hi_u): Declare union. * mach_dep.c [E2K] (GC_get_procedure_stack, GC_save_regs_in_stack): Implement. * mach_dep.c [E2K] (GC_with_callee_saves_pushed): Call GC_save_regs_in_stack() (not saving the result). * mark.c (GC_mark_from, GC_push_all_eager): Use LOAD_WORD_OR_CONTINUE() instead of direct dereference of current_p. * mark.c [!SMALL_CONFIG] (GC_mark_from): Do not prefetch if E2K. * mark_rts.c [E2K] (GC_push_all_register_sections): Implement but ignore traced_stack_sect (add TODO item). * mark_rts.c [!THREADS && E2K] (GC_push_current_stack): Call GC_get_procedure_stack() and GC_push_all_register_sections(). * misc.c [E2K] (GC_call_with_stack_base): Initialize reg_base to 0. * misc.c [!THREADS && E2K] (GC_do_blocking_inner, GC_get_my_stackbottom): Likewise. * os_dep.c [((HAVE_PTHREAD_ATTR_GET_NP || HAVE_PTHREAD_GETATTR_NP) && THREADS || !HAVE_GET_STACK_BASE) && E2K] (GC_get_stack_base): Likewise. * pthread_support.c [E2K] (GC_get_my_stackbottom): Likewise. * pthread_stop_world.c [E2K] (GC_suspend_handler): Call GC_with_callee_saves_pushed(). * pthread_stop_world.c [E2K] (GC_store_stack_ptr): Call GC_save_regs_in_stack() and GC_get_procedure_stack(). * pthread_stop_world.c [E2K] (GC_suspend_handler_inner): Call free(me->backing_store_end) before return. * pthread_stop_world.c [E2K] (GC_push_all_stacks): Declare bs_lo, bs_hi, stack_size local variables; call GC_save_regs_in_stack() and GC_get_procedure_stack() (and free() at the end) for self thread; call GC_push_all_register_sections(). * pthread_support.c [E2K] (GC_do_blocking_inner): Call GC_save_regs_in_stack(); add FIXME.
Diffstat (limited to 'mach_dep.c')
-rw-r--r--mach_dep.c105
1 files changed, 103 insertions, 2 deletions
diff --git a/mach_dep.c b/mach_dep.c
index 1824a500..e6815919 100644
--- a/mach_dep.c
+++ b/mach_dep.c
@@ -26,6 +26,104 @@
# endif
#endif
+#ifdef E2K
+# include <errno.h>
+# include <sys/syscall.h>
+
+# include <asm/e2k_syswork.h>
+
+# define VA_SIZE 48
+# define E2K_PSHTP_SIZE 12
+
+ struct e2k_rwap_lo_fields {
+ word base : VA_SIZE; /* [VA_SIZE-1:0] */
+ };
+
+ union e2k_rwap_lo_u {
+ struct e2k_rwap_lo_fields fields;
+ word w;
+ };
+
+ struct e2k_rwap_hi_fields {
+ word curptr : 32; /* [31:0] */
+ };
+
+ union e2k_rwap_hi_u {
+ struct e2k_rwap_hi_fields fields;
+ word w;
+ };
+
+# define get_stack_index(ps_ptr) \
+ do { \
+ union e2k_rwap_lo_u psp_lo; \
+ union e2k_rwap_hi_u psp_hi; \
+ signed_word pshtp; \
+ char tmp = 0; \
+ char val = 0; \
+ \
+ __asm__ __volatile__ ( \
+ "1:\n\t" \
+ "ldb [%[tmp] + 0x0] 0x7, %[val]\n\t" \
+ "rrd %%pshtp, %[pshtp]\n\t" \
+ "rrd %%psp.lo, %[psp_lo]\n\t" \
+ "rrd %%psp.hi, %[psp_hi]\n\t" \
+ "stb [%[tmp] + 0x0] 0x2, %[val]\n\t" \
+ "ibranch 1b ? %%MLOCK\n" \
+ : [val] "=&r" (val), \
+ [psp_lo] "=&r" (psp_lo.w), \
+ [psp_hi] "=&r" (psp_hi.w), \
+ [pshtp] "=&r" (pshtp) \
+ : [tmp] "r" (&tmp)); \
+ *(ps_ptr) = psp_lo.fields.base + psp_hi.fields.curptr \
+ + 2 * ((word)((pshtp << (64 - E2K_PSHTP_SIZE)) \
+ >> (64 - E2K_PSHTP_SIZE))); \
+ } while (0)
+
+ GC_INNER size_t GC_get_procedure_stack(ptr_t *buf_ptr) {
+ word ps;
+ ptr_t buf = NULL;
+ word buf_sz = 0;
+ word new_sz = 0;
+
+ get_stack_index(&ps);
+ for (;;) {
+ int res = syscall(__NR_access_hw_stacks, E2K_READ_PROCEDURE_STACK,
+ &ps, buf, buf_sz, &new_sz);
+
+ if (res != -1) break;
+ if (ENOMEM == errno && buf_sz != new_sz) {
+ /* FIXME: use GC_scratch_alloc to support malloc redirection? */
+ free(buf);
+ buf = malloc((size_t)new_sz);
+ if (NULL == buf)
+ ABORT_ARG1("Could not allocate memory for procedure stack",
+ ", %lu bytes requested", (unsigned long)new_sz);
+ if (0 == buf_sz) {
+ buf_sz = new_sz;
+ continue; /* skip get_stack_index() once */
+ }
+ buf_sz = new_sz;
+ } else if (errno != EAGAIN) {
+ ABORT_ARG1("Cannot read procedure stack", ": errno= %d", errno);
+ }
+ get_stack_index(&ps);
+ }
+
+ if (buf_sz != new_sz)
+ ABORT_ARG2("Buffer size mismatch while reading procedure stack",
+ ": buf_sz= %lu, new_sz= %lu",
+ (unsigned long)buf_sz, (unsigned long)new_sz);
+ GC_ASSERT(buf != NULL);
+ *buf_ptr = buf;
+ return (size_t)buf_sz;
+ }
+
+ ptr_t GC_save_regs_in_stack(void) {
+ __asm__ __volatile__ ("flushr");
+ return NULL;
+ }
+#endif /* E2K */
+
#if defined(MACOS) && defined(__MWERKS__)
#if defined(POWERPC)
@@ -286,11 +384,14 @@ GC_INNER void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *),
ABORT("feenableexcept failed");
# endif
# endif /* GETCONTEXT_FPU_EXCMASK_BUG */
-# if defined(SPARC) || defined(IA64)
+# if defined(E2K) || defined(IA64) || defined(SPARC)
/* On a register window machine, we need to save register */
/* contents on the stack for this to work. This may already be */
/* subsumed by the getcontext() call. */
- GC_save_regs_ret_val = GC_save_regs_in_stack();
+# if defined(IA64) || defined(SPARC)
+ GC_save_regs_ret_val =
+# endif
+ GC_save_regs_in_stack();
# endif
if (NULL == context) /* getcontext failed */
# endif /* !NO_GETCONTEXT */