[multiple changes]

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.

From-SVN: r42519
This commit is contained in:
Tom Tromey
2001-05-24 05:40:37 +00:00
parent 865e0a8389
commit 3610e0d548
25 changed files with 1924 additions and 462 deletions
+13 -12
View File
@@ -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:
+31
View File
@@ -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__ */
+8 -3
View File
@@ -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);
+159 -4
View File
@@ -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)
{