summaryrefslogtreecommitdiff
path: root/libjava/include
diff options
context:
space:
mode:
authortromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>2001-05-24 05:40:37 +0000
committertromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>2001-05-24 05:40:37 +0000
commitf414d9a71062e37063de088da3de2a9041d9125c (patch)
treeee7c6e621432b96c0092733f35d1cc29967a2b97 /libjava/include
parent7683d74127f6ac1c6e927851bdb566aebc46c7cd (diff)
downloadgcc-f414d9a71062e37063de088da3de2a9041d9125c.tar.gz
2001-05-23 Tom Tromey <tromey@redhat.com>
* posix-threads.cc (_Jv_self_cache): Renamed from self_cache. * gcj/Makefile.in: Rebuilt. * gcj/Makefile.am (gcj_HEADERS): Added libgcj-config.h. * gcj/javaprims.h: Include gcj/libgcj-config.h. * gcj/libgcj-config.h.in: New file. * libgcj.spec.in (*jc1): Added @HASH_SYNC_SPEC@. * configure: Rebuilt. * configure.in: Enable hash synchronization by default on some platforms. (HASH_SYNC_SPEC): New subst. (AC_CONFIG_HEADER): Added gcj/libgcj-config.h. Correctly use `test -z' instead of `test -n' in a couple places. (JV_HASH_SYNCHRONIZATION): Use AC_DEFINE; don't add to LIBGCJ_CXXFLAGS. * configure.host (enable_java_net_default): Initialize. (enable_hash_synchronization_default): New variable. 2001-05-23 Hans Boehm <Hans_Boehm@hp.com> * boehm.cc (_Jv_MarkObj): Don't mark sync_info when hash synchronization in use. (_Jv_MarkArray): Likewise. (_Jv_AllocBytes): Don't check return result. (handle_out_of_memory): New function. (_Jv_InitGC): Set GC_oom_fn. (trace_one_vtable): New global. (_Jv_AllocTraceOne): New function. * configure.in: Added --enable-hash-synchronization. * defineclass.cc, prims.cc, resolve.cc, java/lang/natString.cc, java/net/natInetAddress.cc: Remove _Jv_AllocBytesChecked. * nogc.cc (_Jv_AllocObj): Throw out-of-memory. (_Jv_AllocArray): Likewise. (_Jv_AllocBytes): Likewise. (_Jv_AllocPtrFreeObject): New function. (_Jv_AllocTraceOne): Likewise. * posix-threads.cc (_Jv_ThreadRegister): Handle slow pthread_self(). (self_cache): New global. (_Jv_ThreadSelf_out_of_line): New function. * prims.cc (_Jv_AllocBytesChecked): Removed. (_Jv_ThrowNoMemory): New function. (_Jv_AllocObject): Don't check for null return from allocator. (_Jv_NewObjectArray): Likewise. (_Jv_AllocPtrFreeObject): New function. (_Jv_NewPrimArray): Allocate pointer-free object if possible. * include/javaprims.h (_Jv_AllocPtrFreeObject): Declare. (_Jv_MonitorEnter, _Jv_MonitorExit): Don't return value. * include/boehm-gc.h (_Jv_AllocObj): Define. (_Jv_AllocPtrFreeObj): Define. * include/jvm.h (_Jv_AllocPtrFreeObj): Declare. (_Jv_ThrowNoMemory): Declare. (_Jv_AllocTraceOne): Declare. (_Jv_AllocBytesChecked): Removed. * include/posix-threads.h (_Jv_MutexInit, _Jv_MutexLock, _Jv_MutexUnlock): Handle LOCK_DEBUG. (_Jv_ThreadSelf): Handle case where system pthread_self() is slow. * java/lang/Class.h (Class): Declare _Jv_AllocPtrFreeObj as friend. * java/lang/Object.h (sync_info): Conditional upon presence of hash synchronization. * java/lang/natObject.cc: Much new code to handle thin locks and hash synchronization. * java/lang/natString.cc (_Jv_AllocString): Allocate pointer-free object if possible. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@42519 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava/include')
-rw-r--r--libjava/include/Makefile.in25
-rw-r--r--libjava/include/boehm-gc.h31
-rw-r--r--libjava/include/jvm.h11
-rw-r--r--libjava/include/posix-threads.h163
4 files changed, 211 insertions, 19 deletions
diff --git a/libjava/include/Makefile.in b/libjava/include/Makefile.in
index 541fa325bd3..a911f316b77 100644
--- a/libjava/include/Makefile.in
+++ b/libjava/include/Makefile.in
@@ -85,6 +85,7 @@ GCLIBS = @GCLIBS@
GCOBJS = @GCOBJS@
GCSPEC = @GCSPEC@
GCTESTSPEC = @GCTESTSPEC@
+HASH_SYNC_SPEC = @HASH_SYNC_SPEC@
INCLTDL = @INCLTDL@
JC1GCSPEC = @JC1GCSPEC@
LIBDATASTARTSPEC = @LIBDATASTARTSPEC@
@@ -124,11 +125,11 @@ AUTOMAKE_OPTIONS = foreign
include_HEADERS = jni.h jvmpi.h
mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
-CONFIG_HEADER = config.h
+CONFIG_HEADER = config.h ../gcj/libgcj-config.h
CONFIG_CLEAN_FILES =
HEADERS = $(include_HEADERS)
-DIST_COMMON = ./stamp-h.in Makefile.am Makefile.in config.h.in
+DIST_COMMON = ./stamp-h1.in Makefile.am Makefile.in config.h.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
@@ -145,24 +146,24 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-config.h: stamp-h
+config.h: stamp-h1
@if test ! -f $@; then \
- rm -f stamp-h; \
- $(MAKE) stamp-h; \
+ rm -f stamp-h1; \
+ $(MAKE) stamp-h1; \
else :; fi
-stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES= CONFIG_HEADERS=include/config.h \
$(SHELL) ./config.status
- @echo timestamp > stamp-h 2> /dev/null
-$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@$(srcdir)/stamp-h.in
+ @echo timestamp > stamp-h1 2> /dev/null
+$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@$(srcdir)/stamp-h1.in
@if test ! -f $@; then \
- rm -f $(srcdir)/stamp-h.in; \
- $(MAKE) $(srcdir)/stamp-h.in; \
+ rm -f $(srcdir)/stamp-h1.in; \
+ $(MAKE) $(srcdir)/stamp-h1.in; \
else :; fi
-$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4)
+$(srcdir)/stamp-h1.in: $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOHEADER)
- @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null
+ @echo timestamp > $(srcdir)/stamp-h1.in 2> /dev/null
mostlyclean-hdr:
diff --git a/libjava/include/boehm-gc.h b/libjava/include/boehm-gc.h
index fa4e8d04633..cd421a44358 100644
--- a/libjava/include/boehm-gc.h
+++ b/libjava/include/boehm-gc.h
@@ -21,4 +21,35 @@ extern "C"
JV_MARKARRAY_DECL;
};
+// Enough stuff to inline _Jv_AllocObj. Ugly.
+#include <gcj/javaprims.h>
+#include <java/lang/Class.h>
+#include <string.h>
+
+extern "C" void * GC_gcj_malloc(size_t, void *);
+extern "C" void * GC_malloc_atomic(size_t);
+
+inline void *
+_Jv_AllocObj (jsize size, jclass klass)
+{
+ // This should call GC_GCJ_MALLOC, but that would involve
+ // including gc.h.
+ return GC_gcj_malloc (size, klass->vtable);
+}
+
+inline void *
+_Jv_AllocPtrFreeObj (jsize size, jclass klass)
+{
+#ifdef JV_HASH_SYNCHRONIZATION
+ void * obj = GC_malloc_atomic(size);
+ *((_Jv_VTable **) obj) = klass->vtable;
+#else
+ void * obj = GC_gcj_malloc(size, klass->vtable);
+#endif
+ return obj;
+}
+
+// _Jv_AllocBytes (jsize size) should go here, too. But clients don't
+// usually include this header.
+
#endif /* __JV_BOEHM_GC__ */
diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h
index 50af7569fb2..9088df1a414 100644
--- a/libjava/include/jvm.h
+++ b/libjava/include/jvm.h
@@ -107,10 +107,18 @@ typedef void _Jv_FinalizerFunc (jobject);
/* Allocate space for a new Java object. */
void *_Jv_AllocObj (jsize size, jclass cl) __attribute__((__malloc__));
+/* Allocate space for a potentially uninitialized pointer-free object.
+ Interesting only with JV_HASH_SYNCHRONIZATION. */
+void *_Jv_AllocPtrFreeObj (jsize size, jclass cl) __attribute__((__malloc__));
/* Allocate space for an array of Java objects. */
void *_Jv_AllocArray (jsize size, jclass cl) __attribute__((__malloc__));
/* Allocate space that is known to be pointer-free. */
void *_Jv_AllocBytes (jsize size) __attribute__((__malloc__));
+/* Explicitly throw an out-of-memory exception. */
+void _Jv_ThrowNoMemory();
+/* Allocate an object with a single pointer. The first word is reserved
+ for the GC, and the second word is the traced pointer. */
+void *_Jv_AllocTraceOne (jsize size /* incl. reserved slot */);
/* Initialize the GC. */
void _Jv_InitGC (void);
/* Register a finalizer. */
@@ -157,9 +165,6 @@ void _Jv_SetInitialHeapSize (const char *arg);
_Jv_GCSetMaximumHeapSize. */
void _Jv_SetMaximumHeapSize (const char *arg);
-/* Allocate some unscanned bytes. Throw exception if out of memory. */
-void *_Jv_AllocBytesChecked (jsize size) __attribute__((__malloc__));
-
extern "C" void JvRunMain (jclass klass, int argc, const char **argv);
void _Jv_RunMain (const char* name, int argc, const char **argv, bool is_jar);
diff --git a/libjava/include/posix-threads.h b/libjava/include/posix-threads.h
index ad09bedd45a..e033209d088 100644
--- a/libjava/include/posix-threads.h
+++ b/libjava/include/posix-threads.h
@@ -1,7 +1,7 @@
// -*- c++ -*-
// posix-threads.h - Defines for using POSIX threads.
-/* Copyright (C) 1998, 1999 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2001 Free Software Foundation
This file is part of libgcj.
@@ -106,10 +106,21 @@ _Jv_CondInit (_Jv_ConditionVariable_t *cv)
// Mutexes.
//
+#ifdef LOCK_DEBUG
+# include <stdio.h>
+#endif
+
inline void
_Jv_MutexInit (_Jv_Mutex_t *mu)
{
+# ifdef LOCK_DEBUG /* Assumes Linuxthreads */
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
+ pthread_mutex_init (&mu->mutex, &attr);
+# else
pthread_mutex_init (&mu->mutex, 0);
+# endif
mu->count = 0;
mu->owner = 0;
@@ -125,7 +136,16 @@ _Jv_MutexLock (_Jv_Mutex_t *mu)
}
else
{
- pthread_mutex_lock (&mu->mutex);
+# ifdef LOCK_DEBUG
+ int result = pthread_mutex_lock (&mu->mutex);
+ if (0 != result)
+ {
+ fprintf(stderr, "Pthread_mutex_lock returned %d\n", result);
+ for (;;) {}
+ }
+# else
+ pthread_mutex_lock (&mu->mutex);
+# endif
mu->count = 1;
mu->owner = self;
}
@@ -136,14 +156,29 @@ inline int
_Jv_MutexUnlock (_Jv_Mutex_t *mu)
{
if (_Jv_PthreadCheckMonitor (mu))
- return 1;
+ {
+# ifdef LOCK_DEBUG
+ fprintf(stderr, "_Jv_MutexUnlock: Not owner\n");
+ for (;;) {}
+# endif
+ return 1;
+ }
mu->count--;
if (mu->count == 0)
{
mu->owner = 0;
- pthread_mutex_unlock (&mu->mutex);
+# ifdef LOCK_DEBUG
+ int result = pthread_mutex_unlock (&mu->mutex);
+ if (0 != result)
+ {
+ fprintf(stderr, "Pthread_mutex_unlock returned %d\n", result);
+ for (;;) {}
+ }
+# else
+ pthread_mutex_unlock (&mu->mutex);
+# endif
}
return 0;
}
@@ -179,6 +214,126 @@ _Jv_ThreadCurrent (void)
return (java::lang::Thread *) pthread_getspecific (_Jv_ThreadKey);
}
+#ifdef JV_HASH_SYNCHRONIZATION
+// Should be specialized to just load the "current thread" register
+// on platforms that support it. Speed is of the essence. The value
+// of the descriptor is not, so long as there is a one-to-one correspondence
+// to threads.
+
+
+#ifdef __i386__
+
+#define SLOW_PTHREAD_SELF
+ // Add a cache for pthread_self() if we don't have the thread
+ // pointer in a register.
+
+#endif /* __i386__ */
+
+#ifdef __ia64__
+
+typedef size_t _Jv_ThreadId_t;
+
+register size_t _Jv_self __asm__("r13");
+ // For linux_threads this is really a pointer to its thread data
+ // structure. We treat it as opaque. That should also work
+ // on other operating systems that follow the ABI standard.
+
+// This should become the prototype for machines that maintain a thread
+// pointer in a register.
+inline _Jv_ThreadId_t
+_Jv_ThreadSelf (void)
+{
+ return _Jv_self;
+}
+
+#define JV_SELF_DEFINED
+
+#endif /* __ia64__ */
+
+#if defined(SLOW_PTHREAD_SELF)
+
+typedef pthread_t _Jv_ThreadId_t;
+
+// E.g. on X86 Linux, pthread_self() is too slow for our purpose.
+// Instead we maintain a cache based on the current sp value.
+// This is similar to what's done for thread local allocation in the
+// GC, only far simpler.
+// This code should probably go away when Linux/X86 starts using a
+// segment register to hold the thread id.
+# define LOG_THREAD_SPACING 12
+ // If two thread pointer values are closer than
+ // 1 << LOG_THREAD_SPACING, we assume they belong
+ // to the same thread.
+# define SELF_CACHE_SIZE 1024
+# define SC_INDEX(sp) (((unsigned long)(sp) >> 19) & (SELF_CACHE_SIZE-1))
+ // Mapping from sp value to cache index.
+ // Note that this is not in any real sense a hash
+ // function, since we need to be able to clear
+ // all possibly matching slots on thread startup.
+ // Thus all entries that might correspond to
+ // a given thread are intentionally contiguous.
+ // Works well with anything that allocates at least
+ // 512KB stacks.
+# define SC_CLEAR_MIN (-16) // When starting a new thread, we clear
+# define SC_CLEAR_MAX 0 // all self cache entries between
+ // SC_INDEX(sp)+SC_CLEAR_MIN and
+ // SC_INDEX(sp)+SC_CLEAR_MAX to ensure
+ // we never see stale values. The
+ // current values assume a downward
+ // growing stack of size <= 7.5 MB.
+# define BAD_HIGH_SP_VALUE ((size_t)(-1))
+
+extern volatile
+struct self_cache_entry {
+ size_t high_sp_bits; // sp value >> LOG_THREAD_SPACING
+ pthread_t self; // Corresponding thread
+} _Jv_self_cache[];
+
+void _Jv_Self_Cache_Init();
+
+_Jv_ThreadId_t
+_Jv_ThreadSelf_out_of_line(volatile self_cache_entry *sce,
+ size_t high_sp_bits);
+
+inline _Jv_ThreadId_t
+_Jv_ThreadSelf (void)
+{
+ int dummy;
+ size_t sp = (size_t)(&dummy);
+ unsigned h = SC_INDEX(sp);
+ volatile self_cache_entry *sce = _Jv_self_cache + h;
+ pthread_t candidate_self = sce -> self; // Read must precede following one.
+ // Read barrier goes here, if needed.
+ if (sce -> high_sp_bits == sp >> LOG_THREAD_SPACING)
+ {
+ // The sce -> self value we read must be valid. An intervening
+ // cache replacement by another thread would have first replaced
+ // high_sp_bits by something else, and it can't possibly change
+ // back without our intervention.
+ return candidate_self;
+ }
+ else
+ return _Jv_ThreadSelf_out_of_line(sce, sp >> LOG_THREAD_SPACING);
+}
+
+#define JV_SELF_DEFINED
+
+#endif /* SLOW_PTHREAD_SELF */
+
+#ifndef JV_SELF_DEFINED /* If all else fails, call pthread_self directly */
+
+typedef pthread_t _Jv_ThreadId_t;
+
+inline _Jv_ThreadId_t
+_Jv_ThreadSelf (void)
+{
+ return pthread_self();
+}
+
+#endif /* !JV_SELF_DEFINED */
+
+#endif /* JV_HASH_SYNCHRONIZATION */
+
inline _Jv_Thread_t *
_Jv_ThreadCurrentData (void)
{