[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:
+13
-12
@@ -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:
|
||||
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user