diff options
| author | buzbee <buzbee@google.com> | 2011-03-28 18:12:30 -0700 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-03-28 18:12:30 -0700 |
| commit | 9d755ce64ea9714b2c01473b7f4c21747a5f39c1 (patch) | |
| tree | 1d4a47680518dbadfeabb853eec7e53ef09b2ee7 /vm/interp | |
| parent | edb595d5ee6d5b2eddf9b897efc4ccbf56ee6c12 (diff) | |
| parent | 94d65255849ce9f195c971f726e8b09449ba4d14 (diff) | |
| download | android_dalvik-9d755ce64ea9714b2c01473b7f4c21747a5f39c1.tar.gz android_dalvik-9d755ce64ea9714b2c01473b7f4c21747a5f39c1.tar.bz2 android_dalvik-9d755ce64ea9714b2c01473b7f4c21747a5f39c1.zip | |
Merge "Add safepoint callback for gc" into dalvik-dev
Diffstat (limited to 'vm/interp')
| -rw-r--r-- | vm/interp/Interp.c | 63 | ||||
| -rw-r--r-- | vm/interp/Interp.h | 16 | ||||
| -rw-r--r-- | vm/interp/InterpState.h | 5 |
3 files changed, 77 insertions, 7 deletions
diff --git a/vm/interp/Interp.c b/vm/interp/Interp.c index 9df0d230e..98f478ee8 100644 --- a/vm/interp/Interp.c +++ b/vm/interp/Interp.c @@ -1552,6 +1552,35 @@ void dvmUpdateAllInterpBreak(int newBreak, int newMode, bool enable) } /* + * Arm a safepoint callback for a thread. If funct is null, + * clear any pending callback. + * TODO: only gc is currently using this feature, and will have + * at most a single outstanding callback request. Until we need + * something more capable and flexible, enforce this limit. + */ +void dvmArmSafePointCallback(Thread* thread, SafePointCallback funct, + void* arg) +{ + dvmLockMutex(&thread->callbackMutex); + if ((funct == NULL) || (thread->callback == NULL)) { + thread->callback = funct; + thread->callbackArg = arg; + dvmUpdateInterpBreak(thread, kInterpSafePointCallback, + kSubModeNormal, (funct != NULL)); + } else { + // Already armed. Different? + if ((funct != thread->callback) || + (arg != thread->callbackArg)) { + // Yes - report failure and die + LOGE("ArmSafePointCallback failed, thread %d", thread->threadId); + dvmUnlockMutex(&thread->callbackMutex); + dvmAbort(); + } + } + dvmUnlockMutex(&thread->callbackMutex); +} + +/* * One-time initialization at thread creation. Here we initialize * useful constants. */ @@ -1604,7 +1633,7 @@ void dvmInitInterpreterState(Thread* self) * count profiling, JIT trace building, etc. Dalvik PC has been exported * prior to call, but Thread copy of dPC & fp are not current. */ -void dvmCheckBefore(const u2 *pc, const u4 *fp, Thread* self) +void dvmCheckBefore(const u2 *pc, u4 *fp, Thread* self) { const Method* method = self->interpSave.method; assert(self->interpBreak.ctl.breakFlags != 0); @@ -1637,14 +1666,38 @@ void dvmCheckBefore(const u2 *pc, const u4 *fp, Thread* self) } #endif - /* Suspend pending? */ - if (self->interpBreak.ctl.suspendCount) { + /* Safe point handling */ + if (self->interpBreak.ctl.suspendCount || + (self->interpBreak.ctl.breakFlags & kInterpSafePointCallback)) { // Are we are a safe point? int flags; flags = dexGetFlagsFromOpcode(dexOpcodeFromCodeUnit(*pc)); if (flags & VERIFY_GC_INST_MASK) { - dvmExportPC(pc, fp); - dvmCheckSuspendPending(self); + // Yes, at a safe point. Pending callback? + if (self->interpBreak.ctl.breakFlags & kInterpSafePointCallback) { + SafePointCallback callback; + void* arg; + // Get consistent funct/arg pair + dvmLockMutex(&self->callbackMutex); + callback = self->callback; + arg = self->callbackArg; + dvmUnlockMutex(&self->callbackMutex); + // Update Thread structure + self->interpSave.pc = pc; + self->interpSave.fp = fp; + if (callback != NULL) { + // Do the callback + if (!callback(self,arg)) { + // disarm + dvmArmSafePointCallback(self, NULL, NULL); + } + } + } + // Need to suspend? + if (self->interpBreak.ctl.suspendCount) { + dvmExportPC(pc, fp); + dvmCheckSuspendPending(self); + } } } diff --git a/vm/interp/Interp.h b/vm/interp/Interp.h index 9e059f923..b6919af15 100644 --- a/vm/interp/Interp.h +++ b/vm/interp/Interp.h @@ -79,7 +79,7 @@ void dvmFlushBreakpoints(ClassObject* clazz); */ void dvmUpdateDebugger(const Method* method, const u2* pc, const u4* fp, bool methodEntry, Thread* self); -void dvmCheckBefore(const u2 *dPC, const u4 *fp, Thread* self); +void dvmCheckBefore(const u2 *dPC, u4 *fp, Thread* self); void dvmReportExceptionThrow(Thread* self, const Method* curMethod, const u2* pc, void* fp); void dvmReportPreNativeInvoke(const u2* pc, Thread* self, @@ -101,6 +101,20 @@ void dvmAddToSuspendCounts(Thread* thread, int delta, int dbgDelta); */ void dvmUpdateAllInterpBreak(int newBreak, int newMode, bool enable); +/* + * Register a callback to occur at the next safe point for a single thread. + * If funct is NULL, the previous registration is cancelled. + * + * The callback prototype is: + * bool funct(Thread* thread, void* arg) + * + * If funct returns false, the callback will be disarmed. If true, + * it will stay in effect. + */ +void dvmArmSafePointCallback(Thread* thread, SafePointCallback funct, + void* arg); + + #ifndef DVM_NO_ASM_INTERP extern void* dvmAsmInstructionStart[]; extern void* dvmAsmAltInstructionStart[]; diff --git a/vm/interp/InterpState.h b/vm/interp/InterpState.h index 2294a8132..6f8647682 100644 --- a/vm/interp/InterpState.h +++ b/vm/interp/InterpState.h @@ -71,11 +71,14 @@ typedef enum InterpBreakFlags { kInterpDebugBreak = 0x04, kInterpEmulatorTraceBreak = 0x08, kInterpSingleStep = 0x10, + kInterpSafePointCallback = 0x20, #if defined(WITH_JIT) - kInterpJitBreak = 0x20, + kInterpJitBreak = 0x40, #endif } InterpBreakFlags; +typedef bool (*SafePointCallback)(struct Thread* thread, void* arg); + /* * Identify which break and submode flags should be local * to an interpreter activation. |
