This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Re: RFA: [PATCH]: MIPS enhancements to libgcj...
- From: David Daney <ddaney at avtrex dot com>
- To: java-patches at gcc dot gnu dot org
- Cc: Andrew Haley <aph at redhat dot com>, Eric Christopher <echristo at redhat dot com>, Rainer Orth <ro at TechFak dot Uni-Bielefeld dot DE>,Tom Tromey <tromey at redhat dot com>
- Date: Wed, 22 Oct 2003 09:19:06 -0700
- Subject: Re: RFA: [PATCH]: MIPS enhancements to libgcj...
- References: <3F956E85.5030007@avtrex.com> <16277.37203.360156.386016@cuddles.cambridge.redhat.com>
Andrew Haley wrote:
This is OK. However, I'm not a MIPS expert either. Perhaps you do
need to ask one. But don't let that stop you checking this in.
I agree you do need "memory" clobbers on the barrier instructions, if
"sync" does what I think it does.
Andrew.
O.K.:
Here is a slightly modified version of the patch.
Tested as before.
Changes to previous version are:
I removed --with-libgcj-mips-xgot and --with-broken-dladdr from to level
configure. These are now configured in libjava/configure.host.
sysdeps/mips/locks.h: Reworked so that in theory it should work on more
MIPS processor versions.
Can I check it in?
David Daney.
2003-10-22 David Daney <ddaney@avtrex.com)
* include/mips-signal.h: New file.
* sysdep/dwarf2-backtrace.cc: New file.
* sysdep/mips: New directory.
* sysdep/mips/locks.h: New file.
* Makefile.am(extra_cc_files): New, to allow extra c++ files to be
added to libgcj.
(extra_cc_source_files): Ditto.
* configure.host(disable_dladdr): New shell variable passed to
configure.
(mips*-*-linux*): sysdeps_dir=mips,
can_unwind_signal=yes, disable_dladdr=yes, use -mxgot.
(mipsel*-linux* | mipsisa32el*-linux*): Enable hash synchronization.
* configure.in:(mips*-*-linux*): Use sysdep/dwarf2-backtrace.cc to
generate backtrace, and include/mips-signal.h as SIGNAL_HANDLER
(HAVE_DLADDR): Make it depend on setting of disable_dladdr.
(EXTRA_CC_FILES): New, to support conditional addition of
sysdep/dwarf2-backtrace.cc.
* configure: Regenerated.
* Makefile.in: Regenerated.
* gcj/Makefile.in: Regenerated.
* include/config.h.in: Regenerated.
* include/Makefile.in: Regenerated.
* testsuite/Makefile.in: Regenerated.
Index: Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libjava/Makefile.am,v
retrieving revision 1.332
diff -3 -u -p -r1.332 Makefile.am
--- Makefile.am 12 Oct 2003 13:39:06 -0000 1.332
+++ Makefile.am 22 Oct 2003 16:01:32 -0000
@@ -138,6 +138,7 @@ nat_files = $(nat_source_files:.cc=.lo)
x_nat_files = $(x_nat_source_files:.cc=.lo)
## Objects from C sources in subdirs.
c_files = $(c_source_files:.c=.lo)
+extra_cc_files = $(extra_cc_source_files:.cc=.lo)
## Objects from gtk-related C sources in subdirs.
gtk_c_files = $(gtk_c_source_files:.c=.lo)
## Objects from Java sources in subdirs.
@@ -149,13 +150,13 @@ libgcj_la_SOURCES = prims.cc jni.cc exce
resolve.cc defineclass.cc interpret.cc verify.cc \
$(nat_source_files)
EXTRA_libgcj_la_SOURCES = boehm.cc nogc.cc posix-threads.cc no-threads.cc \
- win32-threads.cc posix.cc win32.cc \
- $(c_source_files) $(java_source_files) $(built_java_source_files)
+ win32-threads.cc posix.cc win32.cc $(c_source_files) \
+ $(extra_cc_source_files) $(java_source_files) $(built_java_source_files)
libgcj_la_DEPENDENCIES = libgcj-@gcc_version@.jar $(javao_files) \
- $(c_files) $(GCOBJS) $(THREADOBJS) $(PLATFORMOBJS) $(LIBLTDL) \
- $(LIBFFI) $(ZLIBS) $(GCLIBS)
+ $(c_files) $(extra_cc_files) $(GCOBJS) $(THREADOBJS) \
+ $(PLATFORMOBJS) $(LIBLTDL) $(LIBFFI) $(ZLIBS) $(GCLIBS)
-libgcj_la_LIBADD = $(javao_files) $(c_files) $(GCOBJS) \
+libgcj_la_LIBADD = $(javao_files) $(c_files) $(extra_cc_files) $(GCOBJS) \
$(THREADOBJS) $(PLATFORMOBJS)
# Include THREADLIBS here to ensure that the correct version of
# certain linuxthread functions get linked:
@@ -418,6 +419,9 @@ $(nat_files) $(x_nat_files): %.lo: %.cc
$(c_files): %.lo: %.c
$(LTCOMPILE) -c -o $@ $<
+$(extra_cc_files): %.lo: %.cc
+ $(LTCXXCOMPILE) -c -o $@ $<
+
$(c_files): java/lang/fdlibm.h java/lang/ieeefp.h java/lang/mprec.h
## FIXME: see above
@@ -2631,6 +2635,8 @@ c_source_files = \
java/lang/e_scalb.c java/lang/s_rint.c java/lang/w_sqrt.c \
java/lang/e_sqrt.c java/lang/s_scalbn.c java/lang/sf_rint.c \
java/lang/k_cos.c java/lang/s_sin.c java/lang/sf_fabs.c
+
+extra_cc_source_files = $(EXTRA_CC_FILES)
#java/awt/natToolkit.cc
Index: configure.host
===================================================================
RCS file: /cvs/gcc/gcc/libjava/configure.host,v
retrieving revision 1.53
diff -3 -u -p -r1.53 configure.host
--- configure.host 10 Sep 2003 18:50:47 -0000 1.53
+++ configure.host 22 Oct 2003 16:01:37 -0000
@@ -28,6 +28,8 @@
# pthread_self calls by caching thread IDs in a hashtable
# can_unwind_signal Set to "yes" if the EH unwinder supports throwing
# from a signal handler.
+# disable_dladdr Set to "yes" if dladdr should not be used
+# (i.e it is broken).
libgcj_flags=
libgcj_cflags=
@@ -39,6 +41,7 @@ enable_hash_synchronization_default=no
sysdeps_dir=generic
slow_pthread_self=
can_unwind_signal=no
+disable_dladdr=
case "${target_optspace}:${host}" in
yes:*)
@@ -212,6 +215,17 @@ EOF
./conftest ./conftest && slow_pthread_self=
rm -f conftest conftest.c
fi
+ ;;
+ mips*-*-linux* )
+ sysdeps_dir=mips
+ can_unwind_signal=yes
+ libgcj_flags="${libgcj_flags} -mxgot"
+ case "${host}" in
+ mipsel*-linux* | mipsisa32el*-linux*)
+ enable_hash_synchronization_default=yes
+ disable_dladdr=yes
+ ;;
+ esac
;;
*-*-darwin*)
enable_hash_synchronization_default=no
Index: configure.in
===================================================================
RCS file: /cvs/gcc/gcc/libjava/configure.in,v
retrieving revision 1.172
diff -3 -u -p -r1.172 configure.in
--- configure.in 22 Sep 2003 16:04:24 -0000 1.172
+++ configure.in 22 Oct 2003 16:01:38 -0000
@@ -232,6 +232,9 @@ AC_ARG_WITH(ecos,
TARGET_ECOS="$with_ecos"
)
+EXTRA_CC_FILES=
+AC_SUBST(EXTRA_CC_FILES)
+
PLATFORMOBJS=
case "$TARGET_ECOS" in
no) case "$host" in
@@ -600,6 +603,13 @@ else
ia64-*-linux*)
# Has broken backtrace()
;;
+ mips*-*-linux*)
+ # Has broken backtrace(), but we supply our own.
+ if test -d sysdep; then true; else mkdir -p sysdep; fi
+ EXTRA_CC_FILES="${EXTRA_CC_FILES} sysdep/dwarf2-backtrace.cc"
+ AC_DEFINE(HAVE_BACKTRACE, 1,
+ [Define if your platform has a working backtrace() function.])
+ ;;
*)
AC_DEFINE(HAVE_BACKTRACE, 1,
[Define if your platform has a working backtrace() function.])
@@ -616,7 +626,13 @@ else
])
AC_CHECK_LIB(dl, dladdr, [
- AC_DEFINE(HAVE_DLADDR, 1, [Define if you have dladdr()])])
+ if test "x${disable_dladdr}" = "xyes"; then
+ #Broken dladdr().
+ true
+ else
+ AC_DEFINE(HAVE_DLADDR, 1, [Define if you have dladdr()])
+ fi
+ ])
if test x"$build" = x"$host"; then
AC_CHECK_FILES(/proc/self/exe, [
AC_DEFINE(HAVE_PROC_SELF_EXE, 1, [Define if you have /proc/self/exe])])
@@ -1106,6 +1122,9 @@ case "${host}" in
;;
*mingw*)
SIGNAL_HANDLER=include/win32-signal.h
+ ;;
+ mips*-*-linux*)
+ SIGNAL_HANDLER=include/mips-signal.h
;;
*)
SIGNAL_HANDLER=include/default-signal.h
Index: include/mips-signal.h
===================================================================
RCS file: include/mips-signal.h
diff -N include/mips-signal.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ include/mips-signal.h 22 Oct 2003 16:01:40 -0000
@@ -0,0 +1,89 @@
+// mips-signal.h - Catch runtime signals and turn them into exceptions
+// on an mips based Linux system.
+
+/* Copyright (C) 1998, 1999, 2001, 2002, 2003 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+/* Adapted from sparc-signal.h and powerpc-signal.h
+ by David Daney <ddaney@avtrex.com> */
+
+#ifndef JAVA_SIGNAL_H
+#define JAVA_SIGNAL_H 1
+
+#include <signal.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+/* #include <asm/ucontext.h> structures we use are here but clash with
+ sys/ucontext.h included by java-signal.h from prims.cc */
+
+#define HANDLE_SEGV 1
+#undef HANDLE_FPE
+
+/* The third parameter to the signal handler points to something with
+ * this structure defined in asm/ucontext.h, but the name clashes with
+ * struct ucontext from sys/ucontext.h so this private copy is used. */
+typedef struct _sig_ucontext {
+ unsigned long uc_flags;
+ struct _sig_ucontext *uc_link;
+ stack_t uc_stack;
+ struct sigcontext uc_mcontext;
+ sigset_t uc_sigmask;
+} sig_ucontext_t;
+
+/* We use kernel_sigaction here because we're calling the kernel
+ directly rather than via glibc. The sigaction structure that the
+ syscall uses is a different shape from the one in userland and not
+ visible to us in a header file so we define it here.
+ Additionally we want a proper prototype for the handler function
+ with the struct sigcontext pointer passed by the kernel as the 2nd
+ argument, which isn't there in userland headers. */
+
+struct kernel_sigaction {
+ unsigned int k_sa_flags;
+ void (*k_sa_handler) (int, siginfo_t *, sig_ucontext_t *);
+ sigset_t k_sa_mask;
+ void (*k_sa_restorer)(void);
+ int k_sa_resv[1]; /* reserved */
+};
+
+
+
+#define SIGNAL_HANDLER(_name) \
+static void _name (int _dummy, siginfo_t *_info, sig_ucontext_t *_arg)
+
+/*
+ * MIPS leaves pc pointing at the faulting instruction, but the
+ * unwinder expects it to point to the following instruction
+ */
+
+#define MAKE_THROW_FRAME(_exception) \
+do \
+{ \
+ _arg->uc_mcontext.sc_pc += 4; \
+ (void)_dummy; \
+ (void)_info; \
+} \
+while (0)
+
+/* For an explanation why we cannot simply use sigaction to
+ install the handlers, see i386-signal.h. */
+
+#define INIT_SEGV \
+do \
+ { \
+ struct kernel_sigaction kact; \
+ kact.k_sa_handler = catch_segv; \
+ kact.k_sa_flags = SA_SIGINFO | SA_NODEFER; \
+ sigemptyset (&kact.k_sa_mask); \
+ syscall (SYS_sigaction, SIGSEGV, &kact, NULL); \
+ } \
+while (0)
+
+
+#endif /* JAVA_SIGNAL_H */
+
Index: sysdep/dwarf2-backtrace.cc
===================================================================
RCS file: sysdep/dwarf2-backtrace.cc
diff -N sysdep/dwarf2-backtrace.cc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sysdep/dwarf2-backtrace.cc 22 Oct 2003 16:01:40 -0000
@@ -0,0 +1,86 @@
+/* dwarf2-backtrac.cc - backtrace implementation driven by the dwarf2
+ exception unwinder. */
+
+/* Copyright (C) 2003 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+/* Written by David Daney <ddaney@avtrex.com> */
+
+/*
+ Although this in theory could be 'C' instead of C++, saying that it
+ is C++ and including jvm.h makes it easier to insure that the proper
+ compiler options are used. There must be unwind tables for
+ backtrace because it is on the stack when _Unwind_Backtrace is
+ called. Compiling as C++ insures this.
+
+*/
+
+#include <config.h>
+
+#include <unwind.h>
+
+#include <jvm.h>
+
+
+extern "C"
+{
+ int backtrace (void **, int);
+}
+
+struct backtrace_state
+{
+ int skip_count;
+ int current_level;
+ int max_level;
+ void **locations;
+};
+
+static _Unwind_Reason_Code
+my_trace_fn (struct _Unwind_Context *uc, void *arg)
+{
+
+ struct backtrace_state *bs = (struct backtrace_state *) arg;
+
+ if (bs->skip_count)
+ {
+ bs->skip_count--;
+ return _URC_NO_REASON;
+ }
+
+ _Unwind_Ptr loc = _Unwind_GetIP (uc);
+
+ if (bs->current_level < bs->max_level)
+ bs->locations[bs->current_level++] = (void *) loc;
+
+ if (bs->current_level >= bs->max_level)
+ return _URC_END_OF_STACK;
+ else
+ return _URC_NO_REASON;
+}
+
+/*
+ * backtrace is defined in (some versions of) libc. This definition
+ * must match so that it can replace the libc version at link time.
+ *
+ * Fill the locations array with at most len back trace locations.
+ *
+ * Returns the number of locations actually filled in.
+ *
+ */
+int
+backtrace (void **locations, int len)
+{
+ struct backtrace_state bs;
+ bs.skip_count = 1; /* Don't log the call to backtrace itself. */
+ bs.current_level = 0;
+ bs.max_level = len;
+ bs.locations = locations;
+
+ _Unwind_Backtrace (my_trace_fn, &bs);
+ return bs.current_level;
+}
--- /dev/null Thu Apr 11 07:25:15 2002
+++ sysdep/mips/locks.h Tue Oct 21 15:16:40 2003
@@ -0,0 +1,109 @@
+// locks.h - Thread synchronization primitives. MIPS implementation.
+
+/* Copyright (C) 2003 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+#ifndef __SYSDEP_LOCKS_H__
+#define __SYSDEP_LOCKS_H__
+
+/* Integer type big enough for object address. */
+typedef unsigned obj_addr_t __attribute__((__mode__(__pointer__)));
+
+
+// Atomically replace *addr by new_val if it was initially equal to old.
+// Return true if the comparison succeeded.
+// Assumed to have acquire semantics, i.e. later memory operations
+// cannot execute before the compare_and_swap finishes.
+inline static bool
+compare_and_swap(volatile obj_addr_t *addr,
+ obj_addr_t old,
+ obj_addr_t new_val)
+{
+ long result;
+ __asm__ __volatile__(".set\tpush\n\t"
+ ".set\tnoreorder\n\t"
+ ".set\tnomacro\n\t"
+ "1:\n\t"
+#if _MIPS_SIM == _ABIO32
+ ".set\tmips2\n\t"
+#endif
+ "ll\t%[result],0(%[addr])\n\t"
+ "bne\t%[result],%[old],2f\n\t"
+ "move\t%[result],$0\n\t" // delay slot
+ "move\t%[result],%[new_val]\n\t"
+ "sc\t%[result],0(%[addr])\n\t"
+ "beq\t%[result],$0,1b\n\t"
+ "nop\n\t" // delay slot
+ "2:\n\t"
+ ".set\tpop"
+ : [result] "=&r" (result)
+ : [addr] "r" (addr), [new_val] "r" (new_val), [old] "r"(old)
+ : "memory");
+ return (bool) result;
+}
+
+// Set *addr to new_val with release semantics, i.e. making sure
+// that prior loads and stores complete before this
+// assignment.
+inline static void
+release_set(volatile obj_addr_t *addr, obj_addr_t new_val)
+{
+ __asm__ __volatile__(".set\tpush\n\t"
+#if _MIPS_SIM == _ABIO32
+ ".set\tmips2\n\t"
+#endif
+ "sync\n\t"
+ ".set\tpop" : : : "memory");
+ *(addr) = new_val;
+}
+
+// Compare_and_swap with release semantics instead of acquire semantics.
+// On many architecture, the operation makes both guarantees, so the
+// implementation can be the same.
+inline static bool
+compare_and_swap_release(volatile obj_addr_t *addr,
+ obj_addr_t old,
+ obj_addr_t new_val)
+{
+ __asm__ __volatile__(".set\tpush\n\t"
+#if _MIPS_SIM == _ABIO32
+ ".set\tmips2\n\t"
+#endif
+ "sync\n\t"
+ ".set\tpop" : : : "memory");
+ return compare_and_swap(addr, old, new_val);
+}
+
+// Ensure that subsequent instructions do not execute on stale
+// data that was loaded from memory before the barrier.
+// On X86, the hardware ensures that reads are properly ordered.
+inline static void
+read_barrier()
+{
+ __asm__ __volatile__(".set\tpush\n\t"
+#if _MIPS_SIM == _ABIO32
+ ".set\tmips2\n\t"
+#endif
+ "sync\n\t"
+ ".set\tpop" : : : "memory");
+}
+
+// Ensure that prior stores to memory are completed with respect to other
+// processors.
+inline static void
+write_barrier()
+{
+ __asm__ __volatile__(".set\tpush\n\t"
+#if _MIPS_SIM == _ABIO32
+ ".set\tmips2\n\t"
+#endif
+ "sync\n\t"
+ ".set\tpop" : : : "memory");
+}
+
+#endif // __SYSDEP_LOCKS_H__