aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--boehm-gc/ChangeLog6
-rw-r--r--boehm-gc/config.h4
-rw-r--r--boehm-gc/gc_priv.h24
-rw-r--r--boehm-gc/misc.c3
-rw-r--r--boehm-gc/os_dep.c78
5 files changed, 111 insertions, 4 deletions
diff --git a/boehm-gc/ChangeLog b/boehm-gc/ChangeLog
index 279a2f3..af461ba 100644
--- a/boehm-gc/ChangeLog
+++ b/boehm-gc/ChangeLog
@@ -1,5 +1,11 @@
1999-06-21 Tom Tromey <tromey@cygnus.com>
+ Alpha patch from Jeff Sturm:
+ * os_dep.c (GC_init_linuxalpha): New function.
+ * misc.c: Initialize for alpha linux.
+ * gc_priv.h (GC_test_and_set): Define for alpha.
+ * config.h: Don't assume __data_start on alpha.
+
* Makefile.in: Rebuilt.
* Makefile.am (libgcjgc_la_LDFLAGS): Use -version-info, not
-release.
diff --git a/boehm-gc/config.h b/boehm-gc/config.h
index 6aaf503..89110a6b 100644
--- a/boehm-gc/config.h
+++ b/boehm-gc/config.h
@@ -844,8 +844,8 @@
# define CPP_WORDSZ 64
# define STACKBOTTOM ((ptr_t) 0x120000000)
# ifdef __ELF__
- extern int __data_start;
-# define DATASTART &__data_start
+# define DATASTART GC_data_start
+# define USE_PROC
# define DYNAMIC_LOADING
# else
# define DATASTART ((ptr_t) 0x140000000)
diff --git a/boehm-gc/gc_priv.h b/boehm-gc/gc_priv.h
index 888e46e..cc8b147 100644
--- a/boehm-gc/gc_priv.h
+++ b/boehm-gc/gc_priv.h
@@ -442,10 +442,32 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
: "0"(1), "m"(*(addr)));
return oldval;
}
+ inline static void GC_clear(volatile unsigned int *addr) {
+ *(addr) = 0;
+ }
+# elif defined(__alpha__)
+ inline static int GC_test_and_set(volatile unsigned int *addr) {
+ long oldval, temp;
+
+ __asm__ __volatile__(
+ "1:\tldl_l %0,%3\n"
+ "\tbne %0,2f\n"
+ "\tor $31,1,%1\n"
+ "\tstl_c %1,%2\n"
+ "\tbeq %1,1b\n"
+ "2:\tmb\n"
+ : "=&r"(oldval), "=&r"(temp), "=m"(*(addr))
+ : "m"(*(addr))
+ : "memory");
+ return (int)oldval;
+ }
+ inline static void GC_clear(volatile unsigned int *addr) {
+ __asm__ __volatile__("mb": : :"memory");
+ *(addr) = 0;
+ }
# else
-- > Need implementation of GC_test_and_set()
# endif
-# define GC_clear(addr) (*(addr) = 0)
extern volatile unsigned int GC_allocate_lock;
/* This is not a mutex because mutexes that obey the (optional) */
diff --git a/boehm-gc/misc.c b/boehm-gc/misc.c
index 72c87b0..70f583f9 100644
--- a/boehm-gc/misc.c
+++ b/boehm-gc/misc.c
@@ -436,6 +436,9 @@ void GC_init_inner()
# if defined(LINUX) && defined(POWERPC)
GC_init_linuxppc();
# endif
+# if defined(LINUX) && defined(ALPHA)
+ GC_init_linuxalpha();
+# endif
# ifdef SOLARIS_THREADS
GC_thr_init();
/* We need dirty bits in order to find live stack sections. */
diff --git a/boehm-gc/os_dep.c b/boehm-gc/os_dep.c
index f05e94d..29cf8ff 100644
--- a/boehm-gc/os_dep.c
+++ b/boehm-gc/os_dep.c
@@ -68,7 +68,7 @@
# define NEED_FIND_LIMIT
# endif
-# if defined(LINUX) && defined(POWERPC)
+# if defined(LINUX) && (defined(POWERPC) || defined(ALPHA))
# define NEED_FIND_LIMIT
# endif
@@ -148,6 +148,82 @@
}
#endif
+#if defined(LINUX) && defined(ALPHA)
+ ptr_t GC_data_start;
+
+ void GC_init_linuxalpha()
+ {
+# ifdef USE_PROC
+ FILE *fp = fopen("/proc/self/maps", "r");
+
+ if (fp) {
+ extern void *_etext;
+ ptr_t stacktop = 0, stackbottom = 0;
+ ptr_t textstart = 0, textend = 0;
+ ptr_t datastart = 0, dataend = 0;
+ ptr_t bssstart = 0, bssend = 0;
+
+ while (!feof(fp)) {
+ ptr_t start, end, offset;
+ unsigned short major, minor;
+ char r, w, x, p;
+ unsigned int inode;
+
+ int n = fscanf(fp, "%lx-%lx %c%c%c%c %lx %hx:%hx %d",
+ &start, &end, &r, &w, &x, &p, &offset, &major, &minor, &inode);
+ if (n < 10) break;
+
+ /*
+ * If local variable lies within segment, it is stack.
+ * Else if segment lies below _end and is executable,
+ * it is text. Otherwise, if segment start lies between
+ * _etext and _end and segment is writable and is mapped
+ * to the executable image it is data, otherwise bss.
+ */
+ if (start < (ptr_t)&fp && end > (ptr_t)&fp && w == 'w') {
+ stacktop = start;
+ stackbottom = end;
+ } else if (start < (ptr_t)&_end && w == '-' && x == 'x') {
+ textstart = start;
+ textend = end;
+ } else if (start >= (ptr_t)&_etext &&
+ start < (ptr_t)&_end && w == 'w') {
+ if (inode > 0) {
+ datastart = start;
+ dataend = end;
+ } else {
+ bssstart = start;
+ bssend = end;
+ }
+ }
+
+ //printf("%016lx-%016lx %c%c%c%c %016lx %02hx:%02hx %d\n",
+ // start, end, r, w, x, p, offset, major, minor, inode);
+
+ while (fgetc(fp) != '\n') ;
+ }
+ fclose(fp);
+
+ //fprintf(stderr, "text: %lx-%lx\n", textstart, textend);
+ //fprintf(stderr, "data: %lx-%lx\n", datastart, dataend);
+ //fprintf(stderr, "bss: %lx-%lx\n", bssstart, bssend);
+ //fprintf(stderr, "stack: %lx-%lx\n", stacktop, stackbottom);
+
+ GC_data_start = datastart;
+ } else {
+# endif
+ extern ptr_t GC_find_limit();
+ extern int _edata;
+ /* This may need to be environ, without the underscore, for */
+ /* some versions. */
+ GC_data_start = GC_find_limit((ptr_t)&_edata, FALSE);
+# ifdef USE_PROC
+ }
+# endif
+ //fprintf(stderr, "GC_data_start = %p\n", GC_data_start);
+ }
+#endif
+
# ifdef ECOS
# ifndef ECOS_GC_MEMORY_SIZE