re PR libgcj/8995 (race cases in interpreter)

2008-09-17  Andrew Haley  <aph@redhat.com>

        PR libgcj/8995:

        * defineclass.cc (_Jv_ClassReader::handleCodeAttribute):
        Initialize thread_count.
        * include/java-interp.h (_Jv_InterpMethod::thread_count): New
        field.
         (_Jv_InterpMethod::rewrite_insn_mutex): New mutex.
        (_Jv_InterpFrame:: _Jv_InterpFrame): Pass frame_type.
        * interpret.cc
        (ThreadCountAdjuster): New class.
        (_Jv_InterpMethod::thread_count): New field.
        (_Jv_InitInterpreter): Initialize rewrite_insn_mutex.
        Increment and decrement thread_count field in methods.
        * interpret-run.cc (REWRITE_INSN): Check thread_count <= 1.
        (REWRITE_INSN): Likewise.
        Declare a ThreadCountAdjuster.
        * java/lang/reflect/natVMProxy.cc (run_proxy): Initialize frame
        type as frame_proxy.

From-SVN: r140593
This commit is contained in:
Andrew Haley
2008-09-23 13:51:58 +00:00
committed by Andrew Haley
parent 5c0466b537
commit f0580031a7
6 changed files with 155 additions and 31 deletions
+84 -2
View File
@@ -175,6 +175,17 @@ class _Jv_InterpMethod : public _Jv_MethodBase
static pc_t breakpoint_insn;
#ifdef DIRECT_THREADED
static insn_slot bp_insn_slot;
public:
// Mutex to prevent a data race between threads when rewriting
// instructions. See interpret-run.cc for an explanation of its use.
static _Jv_Mutex_t rewrite_insn_mutex;
// The count of threads executing this method.
long thread_count;
private:
#else
static unsigned char bp_insn_opcode;
#endif
@@ -455,9 +466,10 @@ public:
jobject obj_ptr;
_Jv_InterpFrame (void *meth, java::lang::Thread *thr, jclass proxyCls = NULL,
pc_t *pc = NULL)
pc_t *pc = NULL,
_Jv_FrameType frame_type = frame_interpreter)
: _Jv_Frame (reinterpret_cast<_Jv_MethodBase *> (meth), thr,
frame_interpreter)
frame_type)
{
next_interp = (_Jv_InterpFrame *) thr->interp_frame;
proxyClass = proxyCls;
@@ -501,6 +513,76 @@ public:
}
};
#ifdef DIRECT_THREADED
// This class increments and decrements the thread_count field in an
// interpreted method. On entry to the interpreter a
// ThreadCountAdjuster is created when increments the thread_count in
// the current method and uses the next_interp field in the frame to
// find the previous method and decrement its thread_count.
class ThreadCountAdjuster
{
// A class used to handle the rewrite_insn_mutex while we're
// adjusting the thread_count in a method. Unlocking the mutex in a
// destructor ensures that it's unlocked even if (for example) a
// segfault occurs in the critical section.
class MutexLock
{
private:
_Jv_Mutex_t *mutex;
public:
MutexLock (_Jv_Mutex_t *m)
{
mutex = m;
_Jv_MutexLock (mutex);
}
~MutexLock ()
{
_Jv_MutexUnlock (mutex);
}
};
_Jv_InterpMethod *method;
_Jv_InterpMethod *next_method;
public:
ThreadCountAdjuster (_Jv_InterpMethod *m, _Jv_InterpFrame *fr)
{
MutexLock lock (&::_Jv_InterpMethod::rewrite_insn_mutex);
method = m;
next_method = NULL;
_Jv_InterpFrame *next_interp = fr->next_interp;
// Record the fact that we're executing this method and that
// we're no longer executing the method that called us.
method->thread_count++;
if (next_interp && next_interp->frame_type == frame_interpreter)
{
next_method
= reinterpret_cast<_Jv_InterpMethod *> (next_interp->meth);
next_method->thread_count--;
}
}
~ThreadCountAdjuster ()
{
MutexLock lock (&::_Jv_InterpMethod::rewrite_insn_mutex);
// We're going to return to the method that called us, so bump its
// thread_count and decrement our own.
method->thread_count--;
if (next_method)
next_method->thread_count++;
}
};
#endif // DIRECT_THREADED
#endif /* INTERPRETER */
#endif /* __JAVA_INTERP_H__ */