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

📄 mm_alloc.c

📁 Apache V2.0.15 Alpha For Linuxhttpd-2_0_15-alpha.tar.Z
💻 C
字号:
/* ==================================================================== * Copyright (c) 1999-2000 Ralf S. Engelschall. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer.  * * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in *    the documentation and/or other materials provided with the *    distribution. * * 3. All advertising materials mentioning features or use of this *    software must display the following acknowledgment: *    "This product includes software developed by *     Ralf S. Engelschall <rse@engelschall.com>." * * 4. Redistributions of any form whatsoever must retain the following *    acknowledgment: *    "This product includes software developed by *     Ralf S. Engelschall <rse@engelschall.com>." * * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL RALF S. ENGELSCHALL OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== *//*****  mm_alloc.c -- Standard Malloc-Style API***/#define MM_PRIVATE#include "mm.h"/* * Create a memory pool */MM *mm_create(size_t usize, const char *file, int flag){    MM *mm = NULL;    void *core;    size_t size;    size_t maxsize;    /* defaults */    maxsize = mm_maxsize();    if (usize == 0)        usize = maxsize;    if (usize > maxsize)        usize = maxsize;    if (usize < MM_ALLOC_MINSIZE)        usize = MM_ALLOC_MINSIZE;    if (flag & MM_ALLOCATE_ENOUGH) {        usize += sizeof(*mm);    }    /* determine size */    size = usize+SIZEOF_mem_pool;    /* get a shared memory area */    if ((core = mm_core_create(size, file)) == NULL)        return NULL;    /* fill in the memory pool structure */    mm = (MM *)core;    mm->mp_size    = size;    mm->mp_offset  = SIZEOF_mem_pool;    /* first element of list of free chunks counts existing chunks */    mm->mp_freechunks.mc_size      = 0;    mm->mp_freechunks.mc_usize     = 0;    mm->mp_freechunks.mc_u.mc_next = NULL;    return mm;}/* * Set permissions on memory pools underlaying disk files */int mm_permission(MM *mm, mode_t mode, uid_t owner, gid_t group){    if (mm == NULL)        return -1;    return mm_core_permission((void *)mm, mode, owner, group);}/* * Destroy a memory pool */void mm_destroy(MM *mm){    if (mm == NULL)        return;    /* wipe out the whole area to be safe */    memset(mm, 0, mm->mp_size);    /* and delete the core area */    (void)mm_core_delete((void *)mm);    return;}/* * Lock a memory pool  */int mm_lock(MM *mm, mm_lock_mode mode){    if (mm == NULL)        return FALSE;    return mm_core_lock((void *)mm, mode);}/* * Unlock a memory pool  */int mm_unlock(MM *mm){    if (mm == NULL)        return FALSE;    return mm_core_unlock((void *)mm);}/* * Display debugging information */void mm_display_info(MM *mm){    mem_chunk *mc;    int nFree;    int nAlloc;    int i;    if (!mm_core_lock((void *)mm, MM_LOCK_RD))        return;    mc = &(mm->mp_freechunks);    nFree   = 0;    while (mc->mc_u.mc_next != NULL) {        mc = mc->mc_u.mc_next;        nFree += mc->mc_size;    }    nAlloc = mm->mp_offset-SIZEOF_mem_pool-nFree;    fprintf(stderr, "Information for MM\n");    fprintf(stderr, "    memory area     = 0x%lx - 0x%lx\n", (unsigned long)mm, (unsigned long)(mm+mm->mp_size));    fprintf(stderr, "    memory size     = %d\n", mm->mp_size);    fprintf(stderr, "    memory offset   = %d\n", mm->mp_offset);    fprintf(stderr, "    bytes spare     = %d\n", mm->mp_size-mm->mp_offset);    fprintf(stderr, "    bytes free      = %d (%d chunk%s)\n",             nFree, mm->mp_freechunks.mc_usize,            mm->mp_freechunks.mc_usize == 1 ? "" : "s");    fprintf(stderr, "    bytes allocated = %d\n", nAlloc);    fprintf(stderr, "    List of free chunks:\n");    if (mm->mp_freechunks.mc_usize > 0) {        mc = &(mm->mp_freechunks);        i = 1;        while (mc->mc_u.mc_next != NULL) {            mc = mc->mc_u.mc_next;            fprintf(stderr, "        chunk #%03d: 0x%lx-0x%lx (%d bytes)\n",                     i++, (unsigned long)mc, (unsigned long)(mc+mc->mc_size), mc->mc_size);        }    }    else {        fprintf(stderr, "        <empty-list>\n");    }    mm_core_unlock((void *)mm);    return;}/* * Insert a chunk to the list of free chunks. Algorithm used is: * Insert in sorted manner to the list and merge with previous * and/or next chunk when possible to form larger chunks out of * smaller ones. */static void mm_insert_chunk(MM *mm, mem_chunk *mcInsert){    mem_chunk *mc;    mem_chunk *mcPrev;    mem_chunk *mcNext;        if (!mm_core_lock((void *)mm, MM_LOCK_RW))        return;    mc = &(mm->mp_freechunks);    while (mc->mc_u.mc_next != NULL && (char *)(mc->mc_u.mc_next) < (char *)mcInsert)        mc = mc->mc_u.mc_next;    mcPrev = mc;    mcNext = mc->mc_u.mc_next;    if ((char *)mcPrev+mcPrev->mc_size == (char *)mcInsert &&             (mcNext != NULL && (char *)mcInsert+mcInsert->mc_size == (char *)mcNext)) {        /* merge with previous and next chunk */        mcPrev->mc_size += mcInsert->mc_size + mcNext->mc_size;        mcPrev->mc_u.mc_next = mcNext->mc_u.mc_next;        mm->mp_freechunks.mc_usize -= 1;    }    else if ((char *)mcPrev+mcPrev->mc_size == (char *)mcInsert) {        /* merge with previous chunk */        mcPrev->mc_size += mcInsert->mc_size;    }    else if (mcNext != NULL && (char *)mcInsert+mcInsert->mc_size == (char *)mcNext) {        /* merge with next chunk */        mcInsert->mc_size += mcNext->mc_size;        mcInsert->mc_u.mc_next = mcNext->mc_u.mc_next;        mcPrev->mc_u.mc_next = mcInsert;    }    else {        /* no merging possible, so insert as new chunk */        mcInsert->mc_u.mc_next = mcNext;        mcPrev->mc_u.mc_next = mcInsert;        mm->mp_freechunks.mc_usize += 1;    }    mm_core_unlock((void *)mm);    return;}/* * Retrieve a chunk from the list of free chunks.  Algorithm used * is: Search for minimal-sized chunk which is larger or equal * than the request size. But when the retrieved chunk is still a * lot larger than the requested size, split out the requested * size to not waste memory. */static mem_chunk *mm_retrieve_chunk(MM *mm, size_t size){    mem_chunk *mc;    mem_chunk **pmcMin;    mem_chunk *mcRes;    size_t sMin;    size_t s;    if (mm->mp_freechunks.mc_usize == 0)        return NULL;    if (!mm_core_lock((void *)mm, MM_LOCK_RW))        return NULL;    /* find best-fitting chunk */    pmcMin = NULL;    sMin = mm->mp_size; /* maximum possible */    mc = &(mm->mp_freechunks);    while (mc->mc_u.mc_next != NULL) {        s = mc->mc_u.mc_next->mc_size;        if (s >= size && s < sMin) {            pmcMin = &(mc->mc_u.mc_next);            sMin = s;            if (s == size)                break;        }        mc = mc->mc_u.mc_next;    }    /* create result chunk */    if (pmcMin == NULL)        mcRes = NULL;    else {        mcRes = *pmcMin;        if (mcRes->mc_size >= (size + min_of(2*size,128))) {            /* split out in part */            s = mcRes->mc_size - size;            mcRes->mc_size = size;            /* add back remaining chunk part as new chunk */            mc = (mem_chunk *)((char *)mcRes + size);            mc->mc_size = s;            mc->mc_u.mc_next = mcRes->mc_u.mc_next;            *pmcMin = mc;        }        else {            /* split out as a whole */            *pmcMin = mcRes->mc_u.mc_next;            mm->mp_freechunks.mc_usize--;        }    }    mm_core_unlock((void *)mm);    return mcRes;}/* * Allocate a chunk of memory */void *mm_malloc(MM *mm, size_t usize){    mem_chunk *mc;    size_t size;    void *vp;    if (mm == NULL || usize == 0)        return NULL;    size = mm_core_align2word(SIZEOF_mem_chunk+usize);    if ((mc = mm_retrieve_chunk(mm, size)) != NULL) {        mc->mc_usize = usize;        return &(mc->mc_u.mc_base.mw_cp);    }    if (!mm_core_lock((void *)mm, MM_LOCK_RW))        return NULL;    if ((mm->mp_size - mm->mp_offset) < size) {        mm_core_unlock((void *)mm);        ERR(MM_ERR_ALLOC, "Out of memory");        errno = ENOMEM;        return NULL;     }    mc = (mem_chunk *)((char *)mm + mm->mp_offset);    mc->mc_size  = size;    mc->mc_usize = usize;    vp = (void *)&(mc->mc_u.mc_base.mw_cp);    mm->mp_offset += size;    mm_core_unlock((void *)mm);    return vp;}/* * Reallocate a chunk of memory */void *mm_realloc(MM *mm, void *ptr, size_t usize){    size_t size;    mem_chunk *mc;    void *vp;    if (mm == NULL || usize == 0)        return NULL;    if (ptr == NULL)        return mm_malloc(mm, usize); /* POSIX.1 semantics */    mc = (mem_chunk *)((char *)ptr - SIZEOF_mem_chunk);    if (usize <= mc->mc_usize) {        mc->mc_usize = usize;        return ptr;    }    size = mm_core_align2word(SIZEOF_mem_chunk+usize);    if (size <= mc->mc_size) {        mc->mc_usize = usize;        return ptr;    }    if ((vp = mm_malloc(mm, usize)) == NULL)        return NULL;    memcpy(vp, ptr, usize);    mm_free(mm, ptr);    return vp;}/* * Free a chunk of memory */void mm_free(MM *mm, void *ptr){    mem_chunk *mc;    if (mm == NULL || ptr == NULL)        return;    mc = (mem_chunk *)((char *)ptr - SIZEOF_mem_chunk);    mm_insert_chunk(mm, mc);    return;}/* * Allocate and initialize a chunk of memory */void *mm_calloc(MM *mm, size_t number, size_t usize){    void *vp;    if (mm == NULL || number*usize == 0)        return NULL;    if ((vp = mm_malloc(mm, number*usize)) == NULL)        return NULL;    memset(vp, 0, number*usize);    return vp;}/* * Duplicate a string */char *mm_strdup(MM *mm, const char *str){    int n;    void *vp;    if (mm == NULL || str == NULL)        return NULL;    n = strlen(str);    if ((vp = mm_malloc(mm, n+1)) == NULL)        return NULL;    memcpy(vp, str, n+1);    return vp;}/* * Determine user size of a memory chunk */size_t mm_sizeof(MM *mm, const void *ptr){    mem_chunk *mc;    if (mm == NULL || ptr == NULL)        return -1;    mc = (mem_chunk *)((char *)ptr - SIZEOF_mem_chunk);    return mc->mc_usize;}/* * Determine maximum size of an allocateable memory pool */size_t mm_maxsize(void){    return (mm_core_maxsegsize()-SIZEOF_mem_pool);}/* * Determine available memory */size_t mm_available(MM *mm){    mem_chunk *mc;    int nFree;    if (!mm_core_lock((void *)mm, MM_LOCK_RD))        return 0;    nFree = mm->mp_size-mm->mp_offset;    mc = &(mm->mp_freechunks);    while (mc->mc_u.mc_next != NULL) {        mc = mc->mc_u.mc_next;        nFree += mc->mc_size;    }    mm_core_unlock((void *)mm);    return nFree;}/* * Return last error string */char *mm_error(void){    return mm_lib_error_get();}/*EOF*/

⌨️ 快捷键说明

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