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

📄 prmalloc.c

📁 Netscape NSPR库源码
💻 C
📖 第 1 页 / 共 2 页
字号:
    if (p && page_dir[((u_long)p >> malloc_pageshift) - malloc_origo]       != MALLOC_FREE) {	wrterror("allocated non-free page on free-list\n");    }#endif /* EXTRA_SANITY */    size >>= malloc_pageshift;    /* Map new pages */    if (!p)	p = map_pages(size,1);    if (p) {	/* Mark the pages in the directory */	index = ((u_long)p >> malloc_pageshift) - malloc_origo;	page_dir[index] = MALLOC_FIRST;	for (i=1;i<size;i++)	    page_dir[index+i] = MALLOC_FOLLOW;    }    if (delay_free) {	if (!px) 	    px = (struct pgfree*)delay_free;	else	    _PR_UnlockedFree(delay_free);    }    return p;}/* * Allocate a page of fragments */static intmalloc_make_chunks(int bits){    struct  pginfo *bp;    void *pp;    int i,k,l;    /* Allocate a new bucket */    pp = malloc_pages(malloc_pagesize);    if (!pp)	return 0;    l = sizeof *bp - sizeof(u_long);    l += sizeof(u_long) *	(((malloc_pagesize >> bits)+MALLOC_BITS-1) / MALLOC_BITS);    if ((1<<(bits)) <= l+l) {	bp = (struct  pginfo *)pp;    } else {	bp = (struct  pginfo *)_PR_UnlockedMalloc(l);    }    if (!bp)	return 0;    bp->size = (1<<bits);    bp->shift = bits;    bp->total = bp->free = malloc_pagesize >> bits;    bp->next = page_dir[bits];    bp->page = (char*)pp;    i = set_pgdir(pp,bp);    if (!i)	return 0;    /* We can safely assume that there is nobody in this chain */    page_dir[bits] = bp;    /* set all valid bits in the bits */    k = bp->total;    i = 0;/*    for(;k-i >= MALLOC_BITS; i += MALLOC_BITS)	bp->bits[i / MALLOC_BITS] = ~0;*/    for(; i < k; i++)	set_bit(bp,i);    if (bp != pp)	return 1;    /* We may have used the first ones already */    for(i=0;l > 0;i++) {	clr_bit(bp,i);	bp->free--;	bp->total--;	l -= (1 << bits);    }    return 1;}/* * Allocate a fragment */static void *malloc_bytes(size_t size){    size_t s;    int j;    struct  pginfo *bp;    int k;    u_long *lp, bf;    /* Don't bother with anything less than this */    if (size < malloc_minsize) {	size = malloc_minsize;    }    /* Find the right bucket */    j = 1;    s = size - 1;    while (s >>= 1) {        j++;    }    /* If it's empty, make a page more of that size chunks */    if (!page_dir[j] && !malloc_make_chunks(j))	return 0;    /* Find first word of bitmap which isn't empty */    bp = page_dir[j];    for (lp = bp->bits; !*lp; lp++)	;    /* Find that bit */    bf = *lp;    k = 0;    while ((bf & 1) == 0) {	bf >>= 1;	k++;    }    *lp ^= 1L<<k;                       /* clear it */    bp->free--;    if (!bp->free) {	page_dir[j] = bp->next;	bp->next = 0;    }    k += (lp - bp->bits)*MALLOC_BITS;    return bp->page + (k << bp->shift);}void *_PR_UnlockedMalloc(size_t size){    void *result;    /* Round up to a multiple of 8 bytes */    if (size & 7) {	size = size + 8 - (size & 7);    }    if (!initialized)	malloc_init();#ifdef SANITY    if (suicide)	PR_Abort();#endif    if (size <= malloc_maxsize)	result =  malloc_bytes(size);    else	result =  malloc_pages(size);#ifdef SANITY    if (malloc_abort && !result)	wrterror("malloc() returns NULL\n");#endif    TRACE(("%6d M %p %d\n",malloc_event++,result,size));    return result;}void *_PR_UnlockedMemalign(size_t alignment, size_t size){    void *result;    /*     * alignment has to be a power of 2     */    if ((size <= alignment) && (alignment <= malloc_maxsize))		size = alignment;	    else           	size += alignment - 1;	    /* Round up to a multiple of 8 bytes */    if (size & 7) {	size = size + 8 - (size & 7);    }    if (!initialized)	malloc_init();#ifdef SANITY    if (suicide)	abort();#endif    if (size <= malloc_maxsize)	result =  malloc_bytes(size);    else	result =  malloc_pages(size);#ifdef SANITY    if (malloc_abort && !result)	wrterror("malloc() returns NULL\n");#endif    TRACE(("%6d A %p %d\n",malloc_event++,result,size));    if ((u_long)result & (alignment - 1))    	return ((void *)(((u_long)result + alignment)  & ~(alignment - 1)));    else    	return result;}void *_PR_UnlockedCalloc(size_t n, size_t nelem){    void *p;    /* Compute total size and then round up to a double word amount */    n *= nelem;    if (n & 7) {	n = n + 8 - (n & 7);    }    /* Get the memory */    p = _PR_UnlockedMalloc(n);    if (p) {	/* Zero it */	memset(p, 0, n);    }    return p;}/* * Change an allocation's size */void *_PR_UnlockedRealloc(void *ptr, size_t size){    void *p;    u_long osize,page,index,tmp_index;    struct pginfo **mp;    if (!initialized)	malloc_init();#ifdef SANITY    if (suicide)	PR_Abort();#endif    /* used as free() */    TRACE(("%6d R %p %d\n",malloc_event++, ptr, size));    if (ptr && !size) {	_PR_UnlockedFree(ptr);	return _PR_UnlockedMalloc (1);    }    /* used as malloc() */    if (!ptr) {	p = _PR_UnlockedMalloc(size);	return p;    }    /* Find the page directory entry for the page in question */    page = (u_long)ptr >> malloc_pageshift;    index = page - malloc_origo;    /*     * check if memory was allocated by memalign     */    tmp_index = index;    while (page_dir[tmp_index] == MALLOC_FOLLOW)	tmp_index--;    if (tmp_index != index) {	/*	 * memalign-allocated memory	 */	index = tmp_index;	page = index + malloc_origo;				ptr = (void *) (page << malloc_pageshift);    }    TRACE(("%6d R2 %p %d\n",malloc_event++, ptr, size));    /* make sure it makes sense in some fashion */    if (index < malloc_pageshift || index > last_index) {#ifdef SANITY	wrtwarning("junk pointer passed to realloc()\n");#endif	return 0;    }    /* find the size of that allocation, and see if we need to relocate */    mp = &page_dir[index];    if (*mp == MALLOC_FIRST) {	osize = malloc_pagesize;	while (mp[1] == MALLOC_FOLLOW) {	    osize += malloc_pagesize;	    mp++;	}        if (!malloc_realloc && 		size < osize && 		size > malloc_maxsize &&	    size > (osize - malloc_pagesize)) {	    return ptr;	}    } else if (*mp >= MALLOC_MAGIC) {	osize = (*mp)->size;	if (!malloc_realloc &&		size < osize && 	    (size > (*mp)->size/2 || (*mp)->size == malloc_minsize)) {	    return ptr;	}    } else {#ifdef SANITY	wrterror("realloc() of wrong page.\n");#endif    }    /* try to reallocate */    p = _PR_UnlockedMalloc(size);    if (p) {	/* copy the lesser of the two sizes */	if (osize < size)	    memcpy(p,ptr,osize);	else	    memcpy(p,ptr,size);	_PR_UnlockedFree(ptr);    }#ifdef DEBUG    else if (malloc_abort)	wrterror("realloc() returns NULL\n");#endif    return p;}/* * Free a sequence of pages */static voidfree_pages(char *ptr, u_long page, int index, struct pginfo *info){    int i;    struct pgfree *pf,*pt;    u_long l;    char *tail;    TRACE(("%6d FP %p %d\n",malloc_event++, ptr, page));    /* Is it free already ? */    if (info == MALLOC_FREE) {#ifdef SANITY	wrtwarning("freeing free page at %p.\n", ptr);#endif	return;    }#ifdef SANITY    /* Is it not the right place to begin ? */    if (info != MALLOC_FIRST)	wrterror("freeing wrong page.\n");    /* Is this really a pointer to a page ? */    if ((u_long)ptr & malloc_pagemask)	wrterror("freeing messed up page pointer.\n");#endif    /* Count how many pages it is anyway */    page_dir[index] = MALLOC_FREE;    for (i = 1; page_dir[index+i] == MALLOC_FOLLOW; i++)	page_dir[index + i] = MALLOC_FREE;    l = i << malloc_pageshift;    tail = ptr+l;    /* add to free-list */    if (!px)	px = (struct pgfree*)_PR_UnlockedMalloc(sizeof *pt);    /* XXX check success */    px->page = ptr;    px->end =  tail;    px->size = l;    if (!free_list.next) {	px->next = free_list.next;	px->prev = &free_list;	free_list.next = px;	pf = px;	px = 0;    } else {	tail = ptr+l;	for(pf = free_list.next; pf->next && pf->end < ptr; pf = pf->next)	    ;	for(; pf; pf = pf->next) {	    if (pf->end == ptr ) {		/* append to entry */		pf->end += l;		pf->size += l;		if (pf->next && pf->end == pf->next->page ) {		    pt = pf->next;		    pf->end = pt->end;		    pf->size += pt->size;		    pf->next = pt->next;		    if (pf->next)			pf->next->prev = pf;		    _PR_UnlockedFree(pt);		}	    } else if (pf->page == tail) {		/* prepend to entry */		pf->size += l;		pf->page = ptr;	    } else if (pf->page > ptr) {		px->next = pf;		px->prev = pf->prev;		pf->prev = px;		px->prev->next = px;		pf = px;		px = 0;	    } else if (!pf->next) {		px->next = 0;		px->prev = pf;		pf->next = px;		pf = px;		px = 0;	    } else {		continue;	    }	    break;	}    }    if (!pf->next &&      pf->size > malloc_cache &&      pf->end == malloc_brk &&      malloc_brk == (void*)sbrk(0)) {	pf->end = pf->page + malloc_cache;	pf->size = malloc_cache;	TRACE(("%6d U %p %d\n",malloc_event++,pf->end,pf->end - pf->page));	brk(pf->end);	malloc_brk = pf->end;	/* Find the page directory entry for the page in question */	page = (u_long)pf->end >> malloc_pageshift;	index = page - malloc_origo;	/* Now update the directory */	for(i=index;i <= last_index;)	    page_dir[i++] = MALLOC_NOT_MINE;	last_index = index - 1;    }}/* * Free a chunk, and possibly the page it's on, if the page becomes empty. */static voidfree_bytes(void *ptr, u_long page, int index, struct pginfo *info){    int i;    struct pginfo **mp;    void *vp;    /* Make sure that pointer is multiplum of chunk-size */#ifdef SANITY    if ((u_long)ptr & (info->size - 1))	wrterror("freeing messed up chunk pointer\n");#endif    /* Find the chunk number on the page */    i = ((u_long)ptr & malloc_pagemask) >> info->shift;    /* See if it's free already */    if (tst_bit(info,i)) {#ifdef SANITY	wrtwarning("freeing free chunk at %p\n", ptr);#endif	return;    }    /* Mark it free */    set_bit(info,i);    info->free++;    /* If the page was full before, we need to put it on the queue now */    if (info->free == 1) {	mp = page_dir + info->shift;	while (*mp && (*mp)->next && (*mp)->next->page < info->page)	    mp = &(*mp)->next;	info->next = *mp;	*mp = info;	return;    }    /* If this page isn't empty, don't do anything. */    if (info->free != info->total)	return;    /* We may want to keep at least one page of each size chunks around.  */    mp = page_dir + info->shift;    if (0 && (*mp == info) && !info->next)	return;    /* Find & remove this page in the queue */    while (*mp != info) {	mp = &((*mp)->next);#ifdef EXTRA_SANITY	if (!*mp) {		TRACE(("%6d !q %p\n",malloc_event++,info));		wrterror("Not on queue\n");	}#endif    }    *mp = info->next;    /* Free the page & the info structure if need be */    set_pgdir(info->page,MALLOC_FIRST);    if((void*)info->page == (void*)info) {	_PR_UnlockedFree(info->page);    } else {	vp = info->page;	_PR_UnlockedFree(info);	_PR_UnlockedFree(vp);    }}void _PR_UnlockedFree(void *ptr){    u_long page;    struct pginfo *info;    int index, tmp_index;    TRACE(("%6d F %p\n",malloc_event++,ptr));    /* This is legal */    if (!ptr)	return;#ifdef SANITY    /* There wouldn't be anything to free */    if (!initialized) {	wrtwarning("free() called before malloc() ever got called\n");	return;    }#endif#ifdef SANITY    if (suicide)	PR_Abort();#endif    /* Find the page directory entry for the page in question */    page = (u_long)ptr >> malloc_pageshift;    index = page - malloc_origo;    /*     * check if memory was allocated by memalign     */    tmp_index = index;    while (page_dir[tmp_index] == MALLOC_FOLLOW)	tmp_index--;    if (tmp_index != index) {	/*	 * memalign-allocated memory	 */	index = tmp_index;	page = index + malloc_origo;				ptr = (void *) (page << malloc_pageshift);    }    /* make sure it makes sense in some fashion */    if (index < malloc_pageshift) {#ifdef SANITY	wrtwarning("junk pointer %p (low) passed to free()\n", ptr);#endif	return;    }    if (index > last_index) {#ifdef SANITY	wrtwarning("junk pointer %p (high) passed to free()\n", ptr);#endif	return;    }    /* handle as page-allocation or chunk allocation */    info = page_dir[index];    if (info < MALLOC_MAGIC)        free_pages((char*)ptr, page, index, info);    else 	free_bytes(ptr,page,index,info);    return;}#endif /* _PR_OVERRIDE_MALLOC */

⌨️ 快捷键说明

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