⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prmsgc.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 5 页
字号:
}static void NotifyFinalizer(void){    if (!PR_CLIST_IS_EMPTY(&_pr_finalQueue)) {    PR_ASSERT( GC_IS_LOCKED() );    PR_Notify(_pr_gcData.lock);    }}void _PR_CreateFinalizer(PRThreadScope scope){    if (!_pr_gcData.finalizer) {    _pr_gcData.finalizer = PR_CreateThreadGCAble(PR_SYSTEM_THREAD,                                        FinalizerLoop, 0,                                        PR_PRIORITY_LOW, scope,                                        PR_UNJOINABLE_THREAD, 0);        if (_pr_gcData.finalizer == NULL)        /* We are doomed if we can't start the finalizer */        PR_Abort();    }}void pr_FinalizeOnExit(void){#ifdef DEBUG_warren    OutputDebugString("### Doing finalize-on-exit pass\n");#endif    PR_ForceFinalize();#ifdef DEBUG_warren    OutputDebugString("### Finalize-on-exit complete. Dumping object left to memory.out\n");    PR_DumpMemorySummary();    PR_DumpMemory(PR_TRUE);#endif}PR_IMPLEMENT(void) PR_ForceFinalize(){    LOCK_GC();    NotifyFinalizer();    while (!PR_CLIST_IS_EMPTY(&_pr_finalQueue)) {    PR_ASSERT( GC_IS_LOCKED() );    (void) PR_Wait(_pr_gcData.lock, PR_INTERVAL_NO_TIMEOUT);    }    UNLOCK_GC();    /* XXX I don't know how to make it wait (yet) */}/************************************************************************/typedef struct GCWeakStr {    PRCList links;    PRWord *object;} GCWeak;/*** Find pointer to GCWeak struct from the list linkaged embedded in it*/#define WeakPtr(_qp) \    ((GCWeak*) ((char*) (_qp) - offsetof(GCWeak,links)))PRCList _pr_weakLinks = PR_INIT_STATIC_CLIST(&_pr_weakLinks);PRCList _pr_freeWeakLinks = PR_INIT_STATIC_CLIST(&_pr_freeWeakLinks);#define WEAK_FREELIST_ISEMPTY() (_pr_freeWeakLinks.next == &_pr_freeWeakLinks)/* * Keep objects referred to by weak free list alive until they can be * freed */static void PR_CALLBACK ScanWeakFreeList(void *notused) {#ifdef XP_MAC#pragma unused (notused)#endif    PRCList *qp = _pr_freeWeakLinks.next;    while (qp != &_pr_freeWeakLinks) {    GCWeak *wp = WeakPtr(qp);    qp = qp->next;    ProcessRootPointer(wp->object);    }}/* * Empty the list of weak objects. Note that we can't call malloc/free * under the cover of the GC's lock (we might deadlock), so transfer the * list of free objects to a local list under the cover of the lock, then * release the lock and free up the memory. */static void EmptyWeakFreeList(void) {    if (!WEAK_FREELIST_ISEMPTY()) {    PRCList *qp, freeLinks;    PR_INIT_CLIST(&freeLinks);    /*     * Transfer list of free weak links from the global list to a     * local list.     */    LOCK_GC();    qp = _pr_freeWeakLinks.next;    while (qp != &_pr_freeWeakLinks) {        GCWeak *wp = WeakPtr(qp);        qp = qp->next;        PR_REMOVE_LINK(&wp->links);        PR_APPEND_LINK(&wp->links, &freeLinks);    }    UNLOCK_GC();    /* Free up storage now */    qp = freeLinks.next;    while (qp != &freeLinks) {        GCWeak *wp = WeakPtr(qp);        qp = qp->next;        PR_DELETE(wp);    }    }}/* * Allocate a new weak node in the weak objects list */static GCWeak *AllocWeakNode(void){    EmptyWeakFreeList();    return PR_NEWZAP(GCWeak);}static void FreeWeakNode(GCWeak *node){    PR_DELETE(node);}/* * Check the weak links for validity. Note that the list of weak links is * itself weak (otherwise we would keep the objects with weak links in * them alive forever). As we scan the list check the weak link object * itself and if it's not marked then remove it from the weak link list */static void CheckWeakLinks(void) {    PRCList *qp;    GCWeak *wp;    PRWord *p, h, tix, **weakPtrAddress;    CollectorType *ct;    PRUint32 offset;    qp = _pr_weakLinks.next;    while (qp != &_pr_weakLinks) {    wp = WeakPtr(qp);    qp = qp->next;    if ((p = wp->object) != 0) {        h = p[0];        /* Grab header word */        if ((h & MARK_BIT) == 0) {        /*         * The object that has a weak link is no longer being         * referenced; remove it from the chain and let it get         * swept away by the GC. Transfer it to the list of         * free weak links for later freeing.         */        PR_REMOVE_LINK(&wp->links);        PR_APPEND_LINK(&wp->links, &_pr_freeWeakLinks);        collectorCleanupNeeded = 1;        continue;        }        	    /* Examine a live object that contains weak links */        tix = GET_TYPEIX(h);        ct = &_pr_collectorTypes[tix];        PR_ASSERT((ct->flags != 0) && (ct->gctype.getWeakLinkOffset != 0));        if (0 == ct->gctype.getWeakLinkOffset) {        /* Heap is probably corrupted */        continue;        }        /* Get offset into the object of where the weak pointer is */        offset = (*ct->gctype.getWeakLinkOffset)(p + 1);        /* Check the weak pointer */        weakPtrAddress = (PRWord**)((char*)(p + 1) + offset);        p = *weakPtrAddress;        if (p != 0) {        h = p[-1];    /* Grab header word for pointed to object */        if (h & MARK_BIT) {            /* Object can't be dead */            continue;        }        /* Break weak link to an object that is about to be swept */        *weakPtrAddress = 0;        }    }    }}/************************************************************************//*** Perform a complete garbage collection*/extern GCLockHook *_pr_GCLockHook;static void dogc(void){    RootFinder *rf;    GCLockHook* lhook;    GCScanQ scanQ;    GCSeg *sp, *esp;    PRInt64 start, end, diff;#if defined(GCMETER) || defined(GCTIMINGHOOK)    start = PR_Now();#endif    /*    ** Stop all of the other threads. This also promises to capture the    ** register state of each and every thread    */    /*     ** Get all the locks that will be need during GC after SuspendAll. We     ** cannot make any locking/library calls after SuspendAll.    */    if (_pr_GCLockHook) {        for (lhook = _pr_GCLockHook->next; lhook != _pr_GCLockHook;           lhook = lhook->next) {          (*lhook->func)(PR_GCBEGIN, lhook->arg);        }    }    PR_SuspendAll();#ifdef GCMETER    /* Reset meter info */    if (_pr_gcMeter & _GC_METER_STATS) {        fprintf(stderr,                "[GCSTATS: busy:%ld skipped:%ld, alloced:%ld+wasted:%ld+free:%ld = total:%ld]\n",                (long) _pr_gcData.busyMemory,                (long) meter.skippedFreeChunks,                (long) meter.allocBytes,                (long) meter.wastedBytes,                (long) _pr_gcData.freeMemory,                (long) _pr_gcData.allocMemory);    }            memset(&meter, 0, sizeof(meter));#endif    PR_LOG(_pr_msgc_lm, PR_LOG_ALWAYS, ("begin mark phase; busy=%d free=%d total=%d",                     _pr_gcData.busyMemory, _pr_gcData.freeMemory,                     _pr_gcData.allocMemory));    if (_pr_beginGCHook) {    (*_pr_beginGCHook)(_pr_beginGCHookArg);    }    /*    ** Initialize scanQ to all zero's so that root finder doesn't walk    ** over it...    */    memset(&scanQ, 0, sizeof(scanQ));    pScanQ = &scanQ;    /******************************************/    /* MARK PHASE */    EmptyFreelists();    /* Find root's */    PR_LOG(_pr_msgc_lm, PR_LOG_WARNING,           ("begin mark phase; busy=%d free=%d total=%d",        _pr_gcData.busyMemory, _pr_gcData.freeMemory,            _pr_gcData.allocMemory));    METER(_pr_scanDepth = 0);    rf = _pr_rootFinders;    while (rf) {    _GCTRACE(GC_ROOTS, ("finding roots in %s", rf->name));    (*rf->func)(rf->arg);    rf = rf->next;    }    _GCTRACE(GC_ROOTS, ("done finding roots"));    /* Scan remaining object's that need scanning */    ScanScanQ(&scanQ);    PR_ASSERT(pScanQ == &scanQ);    PR_ASSERT(scanQ.queued == 0);    METER({    if (_pr_scanDepth > _pr_maxScanDepth) {        _pr_maxScanDepth = _pr_scanDepth;    }    });    /******************************************/    /* FINALIZATION PHASE */    METER(_pr_scanDepth = 0);    PrepareFinalize();    /* Scan any resurrected objects found during finalization */    ScanScanQ(&scanQ);    PR_ASSERT(pScanQ == &scanQ);    PR_ASSERT(scanQ.queued == 0);    METER({    if (_pr_scanDepth > _pr_maxScanDepth) {        _pr_maxScanDepth = _pr_scanDepth;    }    });    pScanQ = 0;    /******************************************/    /* SWEEP PHASE */    /*    ** Sweep each segment clean. While we are at it, figure out which    ** segment has the most free space and make that the current segment.    */    CheckWeakLinks();    _GCTRACE(GC_SWEEP, ("begin sweep phase"));    _pr_gcData.freeMemory = 0;    _pr_gcData.busyMemory = 0;    sp = segs;    esp = sp + nsegs;    while (sp < esp) {        if (SweepSegment(sp)) {            /*            ** Segment is now free and has been replaced with a different            ** segment object.            */            esp--;            continue;        }        sp++;    }#if defined(GCMETER) || defined(GCTIMINGHOOK)    end = PR_Now();#endif#ifdef GCMETER    LL_SUB(diff, end, start);    PR_LOG(GC, PR_LOG_ALWAYS,	   ("done; busy=%d free=%d chunks=%d total=%d time=%lldms",	    _pr_gcData.busyMemory, _pr_gcData.freeMemory,	    meter.numFreeChunks, _pr_gcData.allocMemory, diff));    if (_pr_gcMeter & _GC_METER_FREE_LIST) {        PRIntn bin;        fprintf(stderr, "Freelist bins:\n");        for (bin = 0; bin < NUM_BINS; bin++) {            GCFreeChunk *cp = bins[bin];            while (cp != NULL) {                fprintf(stderr, "%3d: %p %8ld\n",                        bin, cp, (long) cp->chunkSize);                cp = cp->next;            }        }    }#endif    if (_pr_endGCHook) {    (*_pr_endGCHook)(_pr_endGCHookArg);    }    /* clear the running total of the bytes allocated via BigAlloc() */    bigAllocBytes = 0;    /* And resume multi-threading */    PR_ResumeAll();    if (_pr_GCLockHook) {        for (lhook = _pr_GCLockHook->prev; lhook != _pr_GCLockHook;           lhook = lhook->prev) {          (*lhook->func)(PR_GCEND, lhook->arg);        }    }    /* Kick finalizer */    NotifyFinalizer();#ifdef GCTIMINGHOOK    if (_pr_gcData.gcTimingHook) {	PRInt32 time;	LL_SUB(diff, end, start);	LL_L2I(time, diff);	_pr_gcData.gcTimingHook(time);    }#endif}PR_IMPLEMENT(void) PR_GC(void){    LOCK_GC();    dogc();    UNLOCK_GC();    EmptyWeakFreeList();}/******************************************************************************* * Heap Walker ******************************************************************************//*** This is yet another disgusting copy of the body of ProcessRootPointer** (the other being ProcessRootBlock), but we're not leveraging a single** function in their cases in interest of performance (avoiding the function** call).*/static PRInt32 PR_CALLBACKpr_ConservativeWalkPointer(void* ptr, PRWalkFun walkRootPointer, void* data){  PRWord *p0, *p, *segBase;  GCSeg* sp;  p0 = (PRWord*) ptr;  /*  ** XXX:    ** Until Win16 maintains lowSeg and highSeg correctly,  ** (ie. lowSeg=MIN(all segs) and highSeg = MAX(all segs))  ** Allways scan through the segment list  */#if !defined(WIN16)  if (p0 < _pr_gcData.lowSeg) return 0;                  /* below gc heap */  if (p0 >= _pr_gcData.highSeg) return 0;                /* above gc heap */#endif  /* NOTE: inline expansion of InHeap */  /* Find segment */  sp = lastInHeap;  if (!sp || !IN_SEGMENT(sp,p0)) {    GCSeg *esp;    sp = segs;    esp = segs + nsegs;    for (; sp < esp; sp++) {      if (IN_SEGMENT(sp, p0)) {	lastInHeap = sp;	goto find_object;      }    }    return 0;  }  find_object:    /* NOTE: Inline expansion of FindObject */    /* Align p to it's proper boundary before we start fiddling with it */    p = (PRWord*) ((PRWord)p0 & ~(BYTES_PER_WORD-1L));    segBase = (PRWord *) sp->base;    do {        if (IS_HBIT(sp, p)) {            goto winner;        }        p--;    } while (p >= segBase);    /*    ** We have a pointer into the heap, but it has no header    ** bit. This means that somehow the very first object in the heap    ** doesn't have a header. This is impossible so when debugging    ** lets abort.    */#ifdef DEBUG    PR_Abort();#endif    return 0; winner:    return walkRootPointer(p, data);}static PRInt32 PR_CALLBACKpr_ConservativeWalkBlock(void **base, PRInt32 count,			 PRWalkFun walkRootPointer, void* data){    PRWord *p0;    while (--count >= 0) {	PRInt32 status;        p0 = (PRWord*) *base++;	status = pr_ConservativeWalkPointer(p0, walkRootPointer, data);	if (status) return status;    }    return 0;}

⌨️ 快捷键说明

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