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 + -
显示快捷键?