📄 mpralloc.c
字号:
/* * Rallocate a block */void *mprReallocBlock(MPR_LOC_DEC(ctx, loc), void *ptr, uint size){ MprBlk *bp, *newbp, *firstChild, *cp; MprApp *app; void *newPtr; mprAssert(VALID_BLK(ctx)); mprAssert(size > 0); if (ptr == 0) { return mprAllocBlock(MPR_LOC_PASS(ctx, loc), size); } mprAssert(VALID_BLK(ptr)); bp = GET_HDR(ptr); mprAssert(bp); mprAssert(VALID_HDR(bp)); CHECK_HDR(bp); if (size < bp->size) { return ptr; } newPtr = mprAllocBlock(MPR_LOC_PASS(ctx, loc), size); if (newPtr == 0) { bp->flags &= ~ALLOC_FLAGS_FREE; free(bp); return 0; } newbp = GET_HDR(newPtr); mprAssert(newbp->size >= size); memcpy((char*) newbp + HDR_SIZE, (char*) bp + HDR_SIZE, bp->size); mprAssert(newbp->size >= size); /* * Fix the next / prev pointers */ app = bp->app; mprLock(app->allocLock); newbp->next->prev = newbp; newbp->prev->next = newbp; /* * Need to fix the parent pointer of all children */ if ((firstChild = newbp->children) != 0) { cp = firstChild; do { cp->parent = newbp; cp = cp->next; } while (cp != firstChild); } /* * May need to set the children pointer of our parent */ if (newbp->parent->children == bp) { newbp->parent->children = newbp; } /* * Free the original block */ mprFree(ptr); mprUnlock(app->allocLock); return GET_PTR(newbp);}/******************************************************************************//* * Allocate a block from a slab */void *mprSlabAllocBlock(MPR_LOC_DEC(ctx, loc), uint size, uint inc){#if NO_SLAB return mprAllocBlock(MPR_LOC_PASS(ctx, loc), size);#else MprBlk *parent, *bp; MprSlabBlock *sb; MprApp *app; MprSlab *slab; int slabIndex; if (ctx == 0) { mprAssert(ctx); return 0; } mprAssert(size > 0); mprAssert(VALID_BLK(ctx)); parent = GET_HDR(ctx); mprAssert(VALID_HDR(parent)); CHECK_HDR(parent); size = SLAB_ALIGN(size); app = parent->app; mprAssert(app); slabIndex = GET_SLAB(size); if (slabIndex < 0 || slabIndex >= MPR_MAX_SLAB) { return mprAllocBlock(MPR_LOC_PASS(ctx, loc), size); } /* * Dequeue a block from the slab. "sb" will point to the user data * portion of the block (i.e. after the MprBlk header). Slabs must be * allocated off the "slabs" context to ensure they don't get freed * until after all other blocks are freed. */ mprLock(app->allocLock); slab = &app->alloc.slabs[slabIndex]; if ((sb = slab->next) == 0) { if (growSlab(MPR_LOC_ARGS(parent->app->alloc.slabs), slab, size, inc) < 0) { mprUnlock(app->allocLock); return 0; } sb = slab->next; } mprAssert(sb); /* * Dequeue the block */ slab->next = sb->next;#if BLD_FEATURE_ALLOC_STATS{ MprSlabStats *slabStats; /* * Update the slab stats */ slabStats = &slab->stats; slabStats->totalAllocCount++; slabStats->freeCount--; slabStats->allocCount++; if (slabStats->allocCount > slabStats->peakAllocCount) { slabStats->peakAllocCount = slabStats->allocCount; }}#endif /* BLD_FEATURE_ALLOC_STATS */ bp = GET_HDR(sb);#if BLD_DEBUG && !BREW if (bp == stopAlloc) { mprBreakpoint(MPR_LOC, "breakOnAddr"); }#endif bp->size = size; bp->flags = ALLOC_MAGIC | ALLOC_FLAGS_SLAB_BLOCK; bp->destructor = 0; bp->parent = parent; if (parent->children == 0) { parent->children = bp; bp->next = bp->prev = bp; } else { /* * Append to the end of the list. Preserve alloc order */ bp->next = parent->children; bp->prev = parent->children->prev; parent->children->prev->next = bp; parent->children->prev = bp; } bp->children = 0; bp->app = app;#if BLD_FEATURE_ALLOC_LEAK_TRACK bp->location = loc;#endif mprUnlock(app->allocLock); return GET_PTR(bp);#endif}/******************************************************************************//* * Return a block back to its slab */static void slabFree(MprBlk *bp){ MprSlab *slab; MprApp *app; void *ptr; int slabIndex; mprAssert(VALID_HDR(bp)); slabIndex = GET_SLAB(bp->size); mprAssert(0 <= slabIndex && slabIndex < MPR_MAX_SLAB); if (0 <= slabIndex && slabIndex < MPR_MAX_SLAB) { mprLock(bp->app->allocLock); slab = &bp->app->alloc.slabs[slabIndex]; app = bp->app;#if BLD_DEBUG memset(bp, 0xfc, bp->size + HDR_SIZE);#endif ptr = GET_PTR(bp); ((MprSlabBlock*) ptr)->next = slab->next; slab->next = ((MprSlabBlock*) ptr);#if BLD_FEATURE_ALLOC_STATS{ MprSlabStats *slabStats; slabStats = &slab->stats; slabStats->freeCount++; slabStats->allocCount--; if (slabStats->freeCount >= slabStats->peakFreeCount) { slabStats->peakFreeCount = slabStats->freeCount; }}#endif mprUnlock(app->allocLock); }}/******************************************************************************//* * Grow the slab and return the next free block * Must be called locked. */static int growSlab(MPR_LOC_DEC(ctx, loc), MprSlab *slab, uint size, uint inc){ MprBlk *bp; MprSlabBlock *sb; int i, chunkSize, len; mprAssert(VALID_BLK(ctx)); mprAssert(slab); mprAssert(size > 0); /* * Take the maximum requested by anyone */ slab->preAllocateIncr = max(slab->preAllocateIncr, inc); /* * We allocate an array of blocks each of user "size" bytes. */ chunkSize = HDR_SIZE + size; len = chunkSize * slab->preAllocateIncr; bp = mprAllocBlock(MPR_LOC_PASS(ctx, loc), len);#if BLD_DEBUG memset(bp, 0xf1, len);#endif if (bp == 0) { mprAssert(0); return MPR_ERR_MEMORY; } bp->flags |= ALLOC_FLAGS_IS_SLAB; /* * We store the slab information in the user data portion */ sb = (MprSlabBlock*) GET_PTR(bp); sb = (MprSlabBlock*) ((char*) sb + len - chunkSize); for (i = slab->preAllocateIncr - 1; i >= 0; i--) { sb->next = slab->next; slab->next = sb; sb = (MprSlabBlock*) ((char*) sb - chunkSize); }#if BLD_FEATURE_ALLOC_STATS{ MprSlabStats *stats; stats = &slab->stats; stats->freeCount += slab->preAllocateIncr; if (stats->freeCount > stats->peakFreeCount) { stats->peakFreeCount = stats->freeCount; }}#endif return 0;}/******************************************************************************//* * Set the pre-allocate amount */int mprSetSlabPreAllocate(MprCtx ctx, int slabIndex, int preAllocateIncr){ MprApp *app; MprSlab *slab; mprAssert(VALID_BLK(ctx)); mprAssert(0 <= slabIndex && slabIndex < MPR_MAX_SLAB); mprAssert(preAllocateIncr > 0); if (0 <= slabIndex && slabIndex < MPR_MAX_SLAB) { app = mprGetApp(ctx); slab = &app->alloc.slabs[slabIndex]; slab->preAllocateIncr = preAllocateIncr; } else { return MPR_ERR_BAD_ARGS; } return 0;}/******************************************************************************/void *mprSlabAllocZeroedBlock(MPR_LOC_DEC(ctx, loc), uint size, uint inc){ void *newBlock; mprAssert(VALID_BLK(ctx)); mprAssert(size > 0); newBlock = mprSlabAllocBlock(MPR_LOC_PASS(ctx, loc), size, inc); if (newBlock) { memset(newBlock, 0, size); } return newBlock;}/******************************************************************************//* * Internal strdup function. Will use the slab allocator for small strings */char *mprStrdupInternal(MPR_LOC_DEC(ctx, loc), const char *str){ char *newp; int len; mprAssert(VALID_BLK(ctx)); if (str == 0) { str = ""; } len = strlen(str) + 1; if (len < MPR_SLAB_STR_MAX) { newp = mprSlabAllocBlock(MPR_LOC_PASS(ctx, loc), MPR_SLAB_STR_MAX, MPR_SLAB_STR_INC); } else { newp = mprAllocBlock(MPR_LOC_PASS(ctx, loc), len); } if (newp) { memcpy(newp, str, len); } return newp;}/******************************************************************************//* * Internal strndup function. Will use the slab allocator for small strings */char *mprStrndupInternal(MPR_LOC_DEC(ctx, loc), const char *str, uint size){ char *newp; uint len; mprAssert(VALID_BLK(ctx)); if (str == 0) { str = ""; } len = strlen(str) + 1; len = min(len, size); if (len < MPR_SLAB_STR_MAX) { newp = mprSlabAllocBlock(MPR_LOC_PASS(ctx, loc), MPR_SLAB_STR_MAX, MPR_SLAB_STR_INC); } else { newp = mprAllocBlock(MPR_LOC_PASS(ctx, loc), len); } if (newp) { memcpy(newp, str, len); } return newp;}/******************************************************************************//* * Internal memcpy function. Will use the slab allocator for small strings */void *mprMemdupInternal(MPR_LOC_DEC(ctx, loc), const void *ptr, uint size){ char *newp; mprAssert(VALID_BLK(ctx)); if (size < MPR_SLAB_STR_MAX) { newp = mprSlabAllocBlock(MPR_LOC_PASS(ctx, loc), MPR_SLAB_STR_MAX, MPR_SLAB_STR_INC); } else { newp = mprAllocBlock(MPR_LOC_PASS(ctx, loc), size); } if (newp) { memcpy(newp, ptr, size); } return newp;}/******************************************************************************//* * Steal a block from one context and insert in another */int mprStealAllocBlock(MPR_LOC_DEC(ctx, loc), const void *ptr){ MprBlk *bp, *parent; if (ptr == 0) { return 0; } mprAssert(VALID_BLK(ctx)); mprAssert(VALID_BLK(ptr)); bp = GET_HDR(ptr);#if BLD_DEBUG && !BREW if (bp == stopAlloc) { mprBreakpoint(MPR_LOC, "breakOnAddr"); }#endif mprAssert(bp); mprAssert(VALID_HDR(bp)); mprAssert(ptr != mprGetAllocParent(ptr)); CHECK_HDR(bp); mprAssert(bp->prev); mprAssert(bp->prev->next); mprAssert(bp->next); mprAssert(bp->next->prev); parent = bp->parent; mprAssert(VALID_HDR(parent)); mprLock(bp->app->allocLock); if (parent->children == bp) { if (bp->next == bp) { parent->children = 0; } else { parent->children = bp->next; } } bp->prev->next = bp->next; bp->next->prev = bp->prev; parent = GET_HDR(ctx); mprAssert(VALID_HDR(parent)); bp->parent = parent; if (parent->children == 0) { parent->children = bp; bp->next = bp->prev = bp; } else { bp->next = parent->children; bp->prev = parent->children->prev; parent->children->prev->next = bp; parent->children->prev = bp; }#if BLD_FEATURE_ALLOC_LEAK_TRACK bp->location = loc;#endif VALIDATE_BLOCK(GET_PTR(bp)); mprUnlock(bp->app->allocLock); return 0;}/******************************************************************************/void mprSetRequiredAlloc(MprCtx ptr, bool recurse){ MprBlk *bp, *firstChild, *cp; bp = GET_HDR(ptr); bp->flags |= ALLOC_FLAGS_REQUIRED; if (recurse && (firstChild = bp->children) != 0) { cp = firstChild; do { mprSetRequiredAlloc(GET_PTR(cp), recurse); cp = cp->next; } while (cp != firstChild); }}/******************************************************************************//* * Monitor stack usage. Return true if the stack has grown */int mprStackCheck(MprCtx ptr){ MprApp *app; int size; mprAssert(VALID_BLK(ptr)); app = mprGetApp(ptr); size = (int) app->stackStart - (int) &app; if (size < 0) { app->maxStack -= size; app->stackStart = (void*) &app; size = 0; } if ((uint) size > app->maxStack) { app->maxStack = size; return 1; } return 0;}/******************************************************************************//* * Return the stack size */int mprStackSize(MprCtx ptr){ MprApp *app; mprAssert(VALID_BLK(ptr)); app = mprGetApp(ptr); return app->maxStack;}/******************************************************************************/static int mprAllocException(MPR_LOC_DEC(ctx, loc), uint size, bool granted){ MprApp *app; MprAlloc *alloc; int rc; mprAssert(VALID_BLK(ctx)); app = mprGetApp(ctx); alloc = &app->alloc; if (alloc->cback == 0) { return 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -