objsync.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 1,810 行 · 第 1/5 页
C
1,810 行
/* Attach the CVMObjMonitor to the CVMOwnedMonitor: */ mon->bits = o->u.fast.bits; mon->obj = obj;#ifdef CVM_DEBUG mon->owner = o;#endif o->type = CVM_OWNEDMON_HEAVY; o->object = mon->obj; o->u.heavy.mon = mon; mon->state = CVM_OBJMON_OWNED; CVMassert(CVMprofiledMonitorGetOwner(&mon->mon) == o->owner); /* Else if the object has not been locked yet, ... */ } else if (CVMhdrBitsSync(obits) == CVM_LOCKSTATE_UNLOCKED) { CVMassert(CVMprofiledMonitorGetOwner(&mon->mon) == NULL); mon->bits = obits; mon->obj = obj;#ifdef CVM_DEBUG mon->owner = NULL;#endif } else /* CVM_LOCKSTATE_MONITOR */ { CVMassert(CVM_FALSE); /* We should never get here. */ }#else /* !FAST */#ifdef CVM_DEBUG CVMassert(mon->magic == CVM_OBJMON_MAGIC);#endif { /* * Scalar variables intended to hold pointer values * have to be of the type CVMAddr which is 4 byte on * 32 bit platforms and 8 byte on 64 bit platforms. */ CVMAddr bits = CVMobjectVariousWord(obj); CVMassert(CVMhdrBitsSync(bits) == CVM_LOCKSTATE_UNLOCKED); mon->bits = bits; } mon->obj = obj;#endif CVMobjMonitorSet(obj, mon, CVM_LOCKSTATE_MONITOR); } /* From a free list or object header? */ if (omon == mon) { *fromListPtr = mon->next; mon->next = CVMglobals.objLocksBound; CVMglobals.objLocksBound = mon; }#ifdef CVM_AGGRESSIVE_REPLENISHdone:#endif CVMassert(CVMobjMonitor(CVMID_icellDirect(ee, indirectObj)) == mon); CVMassert(mon->state != CVM_OBJMON_FREE); /* This is like a reference count, needed if count==0 */ ee->objLockCurrent = mon; /* And another sort of reference count */ if (ee->threadExiting) { CVMobjMonitorPin(ee, mon); CVMtraceExec(CVM_DEBUGFLAG(TRACE_MISC), { CVMD_gcSafeExec(ee, { CVMobjectGetHashSafe(ee, indirectObj); CVMconsolePrintf("Inflating %I\n", indirectObj); }); }); } /* %comment l010 */ CVMD_gcSafeExec(ee, { CVMreplenishFreeListsNonBlocking(ee); CVMsysMutexUnlock(ee, &CVMglobals.syncLock); CVMreplenishFreeListsBlocking(ee); }); ee->objLockCurrent = NULL; return mon;}CVMObjMonitor *CVMobjectInflatePermanently(CVMExecEnv *ee, CVMObjectICell* indirectObj){ CVMObjMonitor* mon = CVMobjectInflate(ee, indirectObj); if (mon != NULL) { mon->sticky = CVM_TRUE; } return mon;}/* Returns: CVM_TRUE if successful. CVM_FALSE if we're out of memory, and hence not able to lock the monitor. */static CVMBoolCVMfastLock(CVMExecEnv* ee, CVMObjectICell* indirectObj){ CVMObjMonitor *mon; CVMassert(CVMD_isgcUnsafe(ee)); /* %comment l011 */ CVMtraceFastLock(("fastLock(%x,%x)\n", ee, CVMID_icellDirect(ee, indirectObj))); if (ee->objLocksFreeOwned == NULL) { /* becomes safe */ CVMreplenishLockRecordUnsafe(ee); if (ee->objLocksFreeOwned == NULL) { /* out of memory */ return CVM_FALSE; }#if CVM_FASTLOCK_TYPE != CVM_FASTLOCK_NONE /* NOTE: If we got here, it could be because this thread tried to acquire more locks than there are CVMOwnedMonitor records in the ee's free list to satisfy the attempts. Now that we've replenished the supply of CVMOwnedMonitors, let's try that TryLock() again. Doing this may actually save us the time and resources for inflating the monitor. Also note that if we had entered CVMfastLock() because the object had already been locked by another thread (and not because of a scarcity of CVMOwnedMonitors, then we would have bypassed this whole attempt at the first 'if' above. */ { CVMObject *directObj = CVMID_icellDirect(ee, indirectObj); if (CVMobjectTryLock(ee, directObj) == CVM_TRUE) { return CVM_TRUE; } }#endif /* CVM_FASTLOCK_TYPE != CVM_FASTLOCK_NONE */ } mon = CVMobjectInflate(ee, indirectObj); if (mon == NULL) { /* out of memory */ return CVM_FALSE; } { CVMassert(mon->state != CVM_OBJMON_FREE); /* %comment l012 */ CVMmonEnter(ee, mon); CVMassert(mon->state != CVM_OBJMON_FREE);#ifdef CVM_DEBUG CVMassert(mon->magic == CVM_OBJMON_MAGIC);#endif CVMassert(mon->obj == CVMID_icellDirect(ee, indirectObj)); /* We could have gotten here because of several possibilities: 1. This thread has entered this monitor several times using the fast lock mechanism. Thereafter, contention occurs which triggers inflation of the monitor. The inflation code would have attached the inflated CVMObjMonitor to the CVMOwnedMonitor that was previously tracking the reentry count for this monitor. In this case, we can expect the reentry count to not be 1. In the least, it will be 2 (once from the original fast lock, and once from the CVMprofiledMonitorEnterUnsafe() above) if not more depending on how many fast lock reentries have taken place before we got here. 2. While attempting to do a fast lock for the first time on this object, another thread was calling CVMobjectSetHashBitsIfNeeded() on the same object. This caused the fast lock to fail and ended up here even though this thread didn't already have a lock on this object. In this case, the CVMprofiledMonitorEnterUnsafe() above would be the first lock on the monitor, and a CVMOwnedMonitor record hasn't been attached to the CVMObjMonitor yet. This is why we need to attach the CVMObjMonitor to a CVMOwnedMonitor if the reentry count is 1. */ if (CVMprofiledMonitorGetCount(&mon->mon) == 1) { CVMmonitorAttachObjMonitor2OwnedMonitor(ee, mon); } else { CVMassert(mon->state == CVM_OBJMON_OWNED); } }#ifdef CVM_JVMTI if (CVMjvmtiIsInDebugMode()) { CVMjvmtiAddLockInfo(ee, mon, NULL, CVM_TRUE); }#endif return CVM_TRUE;}/* Returns: CVM_TRUE if successful. CVM_FALSE if the current thread if not the owner of the specified lock, and hence not able to unlock the monitor. *//* Note: This function is ONLY to be executed under GC unsafe conditions, hence we don't have to worry about GC compacting memory and changing the value of pointers. */static CVMBoolCVMprivateUnlock(CVMExecEnv *ee, CVMObjMonitor *mon){ CVMUint32 count = CVMprofiledMonitorGetCount(&mon->mon); CVMassert(mon->state != CVM_OBJMON_FREE);#ifdef CVM_DEBUG CVMassert(mon->magic == CVM_OBJMON_MAGIC);#endif if (ee->objLocksOwned == NULL) { /* Fail because this ee (i.e thread) does not own the lock on this monitor. Hence it is not allowed to unlock it. */ return CVM_FALSE; } if (count > 0 && CVMprofiledMonitorGetOwner(&mon->mon) == ee) { CVMassert(mon->state == CVM_OBJMON_OWNED);#ifdef CVM_JVMTI if (CVMjvmtiIsInDebugMode()) { CVMjvmtiRemoveLockInfo(ee, mon, NULL); }#endif if (count == 1) { CVMOwnedMonitor **prev = &ee->objLocksOwned; CVMOwnedMonitor *o = ee->objLocksOwned; /* Assume the most frequent case i.e. the last monitor locked is the one being unlocked and the appropriate CVMOwnedMonitor is the first on the owned list. If this turns out to be untrue, then we'll have to search for the appropriate CVMOwnedMonitor: */ if (o->u.heavy.mon != mon) { /* We use a do-while loop here instead of a while loop because we've already eliminated the first element in the list as a candidate and will not have to check it again. */ do { prev = &o->next; o = o->next; } while ((o != NULL) && (o->u.heavy.mon != mon)); /* If we've successfully found the appropriate CVMOwnedMonitor, the ptr should not be NULL: */ CVMassert (o != NULL); } /* By now, we should have attained the appropriate CVMOwnedMonitor as pointed to by the o pointer. */ CVMassert(o->owner == ee); CVMassert(o->type == CVM_OWNEDMON_HEAVY); /* NOTE: The operation of moving the released CVMOwnedMonitor from the owned list to the free list is thread safe because the possible thread contentions are handled as follows: 1. GC, who may want to compact memory, is held off because this function is GC unsafe. 2. Other threads who may want to inflate the monitor won't be contending because the monitor has already been inflated. */ mon->state = CVM_OBJMON_BOUND; /* Remove the released CVMOwnedMonitor from the ee's owned list: */ *prev = o->next; /* Detach the CVMOwnedMonitor from the CVMObjMonitor: */ o->type = CVM_OWNEDMON_FAST;#ifdef CVM_DEBUG o->state = CVM_OWNEDMON_FREE; o->u.fast.bits = 0; o->object = NULL; mon->owner = NULL;#endif /* Add the released CVMOwnedMonitor back to the ee's free list: */ o->next = ee->objLocksFreeOwned; ee->objLocksFreeOwned = o; } CVMmonExit(ee, mon); return CVM_TRUE; } return CVM_FALSE;}#if defined(CVMJIT_SIMPLE_SYNC_METHODS) && \ (CVM_FASTLOCK_TYPE == CVM_FASTLOCK_ATOMICOPS)/* * Simple Sync helper function for unlocking in Simple Sync methods * when there is contention on the lock. It is only needed for * CVM_FASTLOCK_ATOMICOPS since CVM_FASTLOCK_MICROLOCK will never * allow for contention on the unlcok in Simple Sync methods. */extern voidCVMsimpleSyncUnlock(CVMExecEnv *ee, CVMObject* obj){ CVMObjMonitor *mon;#if 0 CVMconsolePrintf("CVMsimpleSyncUnlock ee=0x%x threadID=%-7d obj=0x%x\n", ee, ee->threadID, obj); CVMdebugPrintf(("sync mb: %C.%M\n", CVMmbClassBlock(ee->currentSimpleSyncMB), ee->currentSimpleSyncMB)); CVMdebugPrintf(("caller: %C.%M\n", CVMmbClassBlock(ee->currentMB), ee->currentMB));#endif CVMassert(CVMID_icellIsNull(CVMsyncICell(ee))); CVMID_icellSetDirect(ee, CVMsyncICell(ee), obj); CVMD_gcSafeExec(ee, { /* CVMgcRunGC(ee); */ /* for debugging */ /* Wait for any inflation on this monitor to complete: */ CVMsysMutexLock(ee, &CVMglobals.syncLock); }); /* refresh obj since we become gcSafe */ obj = CVMID_icellDirect(ee, CVMsyncICell(ee)); CVMID_icellSetNull(CVMsyncICell(ee)); /* The monitor must have been inflated because we'll only get here if there was contention on this simple lock: */ CVMassert(CVMhdrBitsSync(CVMobjectVariousWord(obj)) == CVM_LOCKSTATE_MONITOR); mon = CVMobjMonitor(obj);#ifdef CVM_DEBUG CVMassert(mon->magic == CVM_OBJMON_MAGIC);#endif CVMassert(mon->state == CVM_OBJMON_OWNED); CVMassert(CVMprofiledMonitorGetCount(&mon->mon) == 1); CVMassert(CVMprofiledMonitorGetOwner(&mon->mon) == ee); { CVMOwnedMonitor *o = &ee->simpleSyncReservedOwnedMonitor;#ifdef CVM_DEBUG CVMassert(o == mon->owner);#endif CVMassert(o->u.heavy.mon == mon); CVMassert(o->owner == ee); CVMassert(o->type == CVM_OWNEDMON_HEAVY);#ifdef CVM_DEBUG CVMassert(o->state == CVM_OWNEDMON_OWNED);#endif CVMassert(o->count == CVM_INVALID_REENTRY_COUNT); mon->state = CVM_OBJMON_BOUND; /* Detach the CVMOwnedMonitor from the CVMObjMonitor: */ o->type = CVM_OWNEDMON_FAST; o->count = 1;#ifdef CVM_DEBUG#if 0 /* The state should always remain CVM_OWNEDMON_OWNED */ o->state = CVM_OWNEDMON_FREE;#endif o->u.fast.bits = 0; o->object = NULL; mon->owner = NULL;#endif } CVMmonExit(ee, mon); CVMsysMutexUnlock(ee, &CVMglobals.syncLock);}#endif /* CVMJIT_SIMPLE_SYNC_METHODS *//* Returns: CVM_TRUE if successful. CVM_FALSE if the current thread if not
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?