objsync.c

来自「This is a resource based on j2me embedde」· C语言 代码 · 共 1,810 行 · 第 1/5 页

C
1,810
字号
static voidCVMreplenishFreeListsBlocking(CVMExecEnv *ee){    /* NOTE: We need to attempt scavenging first before allocating a new       ObjMon because scavenging is the only mechanism by which these       monitors get reused.  Otherwise, we will end up allocating as       many monitors as memory will allow, and unused monitors that could       have been reused will remain unused because the scavenger won't be       called until we run out of memory. */    if (ee->objLocksFreeUnlocked == NULL) {        /* NOTE: ee->objLocksOwned, and ee->objLocksFreeOwned may be changed            by CVMsyncMonitorScavenge().  Do not cache these values. */        CVMsyncMonitorScavenge(ee, CVM_FALSE);        if (CVMglobals.objLocksFree != NULL) {            /* It appears that after scavenging, we have replenished the global               free list.  So try to replenish the thread specific free list               for CVMObjMonitors by tapping into the global free list.                NOTE: This is not guaranteed to succeed because some other                 thread might come along and consume the monitor our scavenger                 has just freed. */            CVMsysMutexLock(ee, &CVMglobals.syncLock);            CVMreplenishFreeListsNonBlocking(ee);            CVMsysMutexUnlock(ee, &CVMglobals.syncLock);        }        /* If after scavenging, we still aren't able to fill the need, then           it's time to allocate a new one: */        if (ee->objLocksFreeUnlocked == NULL) {            CVMObjMonitor *mon;            mon = (CVMObjMonitor *)calloc(1, sizeof (CVMObjMonitor));            if (mon != NULL) {                if (CVMobjMonitorInit(ee, mon, NULL, 0)) {                    ee->objLocksFreeUnlocked = mon;                    CVMassert(CVMobjMonitorOwner(mon) == NULL);                } else {                    free(mon);                }            }        }    }}/* Purpose: Replenish the thread specific CVMOwnedMonitor free list either by            scavenging for it or creating a new one.  */static voidCVMreplenishLockRecordUnsafe(CVMExecEnv *ee){    CVMassert(CVMD_isgcUnsafe(ee));    /* We attempt to create a new CVMOwnedMonitor first because it is unlikely       that scavenging will turn up any unused CVMOwnedMonitors.  See full       comments at the top of the file for details. */    {	CVMOwnedMonitor *o;	CVMD_gcSafeExec(ee, {	    o = (CVMOwnedMonitor *)calloc(1, sizeof (CVMOwnedMonitor));	    if (o != NULL) {		CVMownedMonitorInit(o, ee);	    }	});	if (o != NULL) {	    o->next = ee->objLocksFreeOwned;	    ee->objLocksFreeOwned = o;	}    }    /* Scavenge for unused CVMOwnedMonitors if necessary: */    if (ee->objLocksFreeOwned == NULL) {        /* We call CVMmonitorScavengeFast() here instead of           CVMsyncMonitorScavenge() because we only need to replenish our           supply of CVMOwnedMonitors and not CVMObjMonitors.  Since           CVMsyncMonitorScavenge() is significantly more costly to run and           does not get us any additional benefit to help satisfy our needs,           calling CVMmonitorScavengeFast() instead is a preferred choice.           NOTE: ee->objLocksOwned, and ee->objLocksFreeOwned may be changed             by CVMmonitorScavengeFast().  Do not cache these values.        */        CVMmonitorScavengeFast(ee);    }    if (ee->objLocksFreeOwned == NULL && ee->threadExiting) {	CVMOwnedMonitor *o = ee->objLocksReservedOwned;	/* If this fails, increase CVM_RESERVED_OWNMON_COUNT below */	CVMassert(o != NULL);	ee->objLocksReservedOwned = o->next;	ee->objLocksFreeOwned = o;	o->next = NULL;    }}/* Pin an (inflated) object monitor.  It will remain inflated until *//* it is unpinned. */static voidCVMobjMonitorPin(CVMExecEnv *ee, CVMObjMonitor *mon){    CVMassert(ee->objLocksPinnedCount < CVM_PINNED_OBJMON_COUNT);    ee->objLocksPinned[ee->objLocksPinnedCount++] = mon;}/* Unpin all monitors that were pinned by this thread. */static voidCVMobjMonitorUnpinAll(CVMExecEnv *ee){#ifdef CVM_DEBUG_ASSERTS    int i;    int n = ee->objLocksPinnedCount;    for (i = 0; i < n; ++i) {	ee->objLocksPinned[i] = NULL;    }#endif    CVMtraceExec(CVM_DEBUGFLAG(TRACE_MISC), {	CVMconsolePrintf("Unpinned %d monitors\n", ee->objLocksPinnedCount);    });    ee->objLocksPinnedCount = 0;}/* Mark pinned monitors as busy */static voidCVMobjMonitorMarkPinnedAsBusy(CVMExecEnv *ee){    int i;    for (i = 0; i < ee->objLocksPinnedCount; ++i) {	CVMassert(ee->objLocksPinned[i]->obj != NULL);#ifdef CVM_DEBUG_ASSERTS	{	    int state = ee->objLocksPinned[i]->state & ~CVM_OBJMON_BUSY;	    CVMassert(state == CVM_OBJMON_BOUND || state == CVM_OBJMON_OWNED);	}#endif	ee->objLocksPinned[i]->state |= CVM_OBJMON_BUSY;    }}/* Clear the busy flag from pinned monitors.  Undoes what *//* CVMobjMonitorMarkPinnedAsBusy() did. */static voidCVMobjMonitorMarkPinnedAsUnbusy(CVMExecEnv *ee){    int i;    for (i = 0; i < ee->objLocksPinnedCount; ++i) {	ee->objLocksPinned[i]->state &= ~CVM_OBJMON_BUSY;    }}/* Unpin any unreferenced monitors.  They can never be *//* inflated or synchronized on again. */static voidCVMobjMonitorUnpinUnreferenced(CVMExecEnv *ee){    int i = 0;    while (i < ee->objLocksPinnedCount) {	if (ee->objLocksPinned[i]->obj == NULL) {#if 0	    /* There should be a way to determine if the monitor is on */	    /* the unbound list. */	    CVMassert(ee->objLocksPinned[i]->state == CVM_OBJMON_UNBOUND);#endif	    ee->objLocksPinned[i] =		ee->objLocksPinned[--ee->objLocksPinnedCount];	    CVMtraceMisc(("Unpinned unreferenced monitor\n"));	    continue;	}	++i;    }}static CVMObjMonitor *CVMobjectInflate(CVMExecEnv *ee, CVMObjectICell* indirectObj){    CVMObjMonitor *mon, *omon;    CVMObjMonitor **fromListPtr;    /*      * bits can hold a native pointer (see CVMobjectVariousWord())     * therefore the type has to be CVMAddr which is 4 byte on     * 32 bit platforms and 8 byte on 64 bit platforms     */    CVMAddr bits;    /* See if another thread already beat us to inflating the monitor: */    {	CVMObject *obj = CVMID_icellDirect(ee, indirectObj);	if (CVMobjMonitorState(obj) == CVM_LOCKSTATE_MONITOR) {	    CVMObjMonitor *mon = CVMobjMonitor(obj);	    CVMassert(mon->obj == obj);#ifdef CVM_THREAD_BOOST	    if (mon->boost) {	        /* Another thread beat us to inflating this monitor.  If we		   own it, then we'll need to claim actual ownership of the		   monitor and unboost our thread priority because we didn't		   inflate it ourselves.  CVMunboost() will check for monitor		   ownership before unboosting.  If we don't own it, then		   CVMunboost() will do nothing. */		CVMunboost(ee, mon);	    }#endif	    return mon;	}    }    /* %comment l008 */    /* See notes above on "Synchronization between various Monitor Methods": */    CVMD_gcSafeExec(ee, {	CVMsysMutexLock(ee, &CVMglobals.syncLock);    });    {	CVMObject *obj = CVMID_icellDirect(ee, indirectObj);	bits = obj->hdr.various32;    }    /* While acquiring the syncLock above, another thread could have beaten us       to inflating the monitor.  Check if this is the case: */    if (CVMhdrBitsSync(bits) == CVM_LOCKSTATE_MONITOR) {        /* If we're here, the another thread did beat us to it: */	CVMObjMonitor *mon = (CVMObjMonitor *)CVMhdrBitsPtr(bits);	CVMassert(mon->state != CVM_OBJMON_FREE);#ifdef CVM_DEBUG	CVMassert(mon->magic == CVM_OBJMON_MAGIC);#endif	CVMassert(mon->obj == CVMID_icellDirect(ee, indirectObj));#ifdef CVM_THREAD_BOOST        /* Another thread beat us to inflating this monitor.  If we own it,	   then we'll need to claim actual ownership of the monitor and	   unboost our thread priority because we didn't inflate it ourselves.	   CVMunboost() will check for monitor ownership before unboosting.	   If we don't own it, then CVMunboost() will do nothing. */	if (mon->boost) {	    CVMunboost(ee, mon);	}#endif#ifdef CVM_AGGRESSIVE_REPLENISH	/* replenish free lists */	goto done;#else	CVMsysMutexUnlock(ee, &CVMglobals.syncLock);	return mon;#endif    }    /* If we get here, then we know for sure that no other thread has inflated       the monitor yet.  And only we have the right to inflate it because we       hold the syncLock. */    /* In the following, we'll be doing one of the these change of states:        1. unlocked --> monitor (heavy/deterministic), or        2. locked (fast) --> monitor (heavy/deterministic)    */    /* Get a heavy CVMObjMonitor from the free list: */    {	fromListPtr = &ee->objLocksFreeUnlocked;	mon = *fromListPtr;        if (mon == NULL) {            /* Failed because no CVMObjMonitor was available: */            CVMsysMutexUnlock(ee, &CVMglobals.syncLock);            return NULL;        }        CVMassert(CVMprofiledMonitorGetOwner(&mon->mon) == NULL);    }    omon = mon;    CVMassert(mon->state == CVM_OBJMON_FREE);    mon->state = CVM_OBJMON_BOUND;    {	CVMObject *obj = CVMID_icellDirect(ee, indirectObj);#if CVM_FASTLOCK_TYPE != CVM_FASTLOCK_NONE        CVMUint32 reentryCount = 1;	/*  	 * obits can hold a native pointer	 * therefore the type has to be CVMAddr which is 4 byte on	 * 32 bit platforms and 8 byte on 64 bit platforms	 */	CVMAddr obits;#if CVM_FASTLOCK_TYPE == CVM_FASTLOCK_ATOMICOPS        /* Write CVM_LOCKSTATE_LOCKED to the obj's header bits to lock out any           fast lock or monitor inflation attempts by any other threads: */	obits = CVMatomicSwap(&(obj)->hdr.various32, CVM_LOCKSTATE_LOCKED);        if (CVMhdrBitsSync(obits) == CVM_LOCKSTATE_LOCKED) {            CVMOwnedMonitor *o = (CVMOwnedMonitor *)CVMhdrBitsPtr(obits);            /* We need to use a CVMatomicSwap() here because the owner thread               may already have attained its CVMOwnedMonitor corrently.  Hence,               the above atomic swap of obj->hdr.various32 doesn't prevent a               fastReentryTryLock() that's already in progress.  However,               by doing an atomic swap on the reentry count, we can guarantee               that we get the last reentryCount of the owner thread before we               prevent it from doing anymore re-entries by swapping a               CVM_INVALID_REENTRY_COUNT value into the reentryCount. */            reentryCount = CVMatomicSwap(&o->count, CVM_INVALID_REENTRY_COUNT);        }#elif CVM_FASTLOCK_TYPE == CVM_FASTLOCK_MICROLOCK        /* Acquire the microlock to lock out any fast lock or monitor inflation           attempts by any other threads: */	CVMobjectMicroLock(ee, obj);        obits = CVMobjectVariousWord(obj);	if (CVMhdrBitsSync(obits) == CVM_LOCKSTATE_LOCKED) {	    CVMOwnedMonitor *o = (CVMOwnedMonitor *)CVMhdrBitsPtr(obits);	    reentryCount = o->count;#ifdef CVM_DEBUG	    o->count = CVM_INVALID_REENTRY_COUNT;#endif	}        /* Set the object's various word to a fake CVMOwnedMonitor record that           is not owned by any thread (i.e. the owner field is NULL) to           prevent any fast lock or unlock operations on this object while           we're inflating.  After that, we can unlock the microlock. */        CVMobjectVariousWord(obj) = (CVMAddr)(&rendezvousOwnedRec) |                                     CVM_LOCKSTATE_LOCKED;        CVMobjectMicroUnlock(ee, obj);#endif        /* If there is already a fast lock on the object, ... */	if (CVMhdrBitsSync(obits) == CVM_LOCKSTATE_LOCKED) {	    CVMOwnedMonitor *o = (CVMOwnedMonitor *)CVMhdrBitsPtr(obits);	    CVMExecEnv *owner = o->owner;#ifdef CVM_DEBUG	    CVMassert(o->magic == CVM_OWNEDMON_MAGIC);#endif	    CVMassert(o->type == CVM_OWNEDMON_FAST);	    if (owner != ee) {		/* set mutex ownership */                CVMprofiledMonitorGetCount(&mon->mon) = reentryCount;                CVMprofiledMonitorGetOwner(&mon->mon) = owner;#ifdef CVM_THREAD_BOOST#ifdef CVM_DEBUG		mon->boostThread = owner;#endif		/* Request priority boosting on owner thread so that it can		   claim actual ownership of this monitor: */		CVMassert(!mon->boost);		mon->boost = CVM_TRUE;#else /* !CVM_THREAD_BOOST */                CVMprofiledMonitorSetMutexOwner(&mon->mon, ee, owner);#ifdef CVM_DEBUG_ASSERTS		{                    CVMBool success = CVMprofiledMonitorTryEnter(&mon->mon, ee);		    CVMassert(!success);		}#endif /* CVM_DEBUG */#endif /* !CVM_THREAD_BOOST */	    } else {                CVMBool success = CVMprofiledMonitorTryEnter(&mon->mon, ee);		CVMassert(success); (void) success;                CVMassert(CVMprofiledMonitorGetCount(&mon->mon) == 1);                CVMprofiledMonitorGetCount(&mon->mon) = reentryCount;	    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?