diff options
author | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-05-24 05:40:37 +0000 |
---|---|---|
committer | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-05-24 05:40:37 +0000 |
commit | f414d9a71062e37063de088da3de2a9041d9125c (patch) | |
tree | ee7c6e621432b96c0092733f35d1cc29967a2b97 /libjava/include | |
parent | 7683d74127f6ac1c6e927851bdb566aebc46c7cd (diff) | |
download | gcc-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.in | 25 | ||||
-rw-r--r-- | libjava/include/boehm-gc.h | 31 | ||||
-rw-r--r-- | libjava/include/jvm.h | 11 | ||||
-rw-r--r-- | libjava/include/posix-threads.h | 163 |
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) { |