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

📄 gmem.c

📁 彩信MMS的全部代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (C) Obigo AB, 2002-2005.
 * All rights reserved.
 *
 * This software is covered by the license agreement between
 * the end user and Obigo AB, and may be 
 * used and copied only in accordance with the terms of the 
 * said agreement.
 *
 * Obigo AB assumes no responsibility or 
 * liability for any errors or inaccuracies in this software, 
 * or any consequential, incidental or indirect damage arising
 * out of the use of the software.
 *
 */





























#include "cansilib.h"   
#include "cmntypes.h"   
#include "cmnconf.h"    
#include "aapicmn.h"    
#include "gmem.h"       

#ifdef USE_G_MALLOC


#define SIZE_S                 unsigned short
#define SIZE_L                 unsigned long
#define CHUNKHEADERSIZE        4
#define MINCHUNKSIZE           8
#define OFFSET_T               unsigned short
#define MALLOC_ALIGN_MASK      3
#define MINBLOCKSIZE           24








#define NUM_FREE_LISTS 10


typedef unsigned char *Ptr; 

typedef struct
{
    SIZE_S   prevSize;  
    SIZE_S   size;      
    OFFSET_T fwd;       
    OFFSET_T bck;
} MemChunk;

typedef struct
{
    int         isInitiated;  
    Ptr         base;
    MemChunk    *first;
    MemChunk    *last;
    MemChunk    *freelists[NUM_FREE_LISTS];
    jmp_buf     jmpbuf;
    int         inside;
#if CMN_LOG_INTERNAL & CMN_LOG_MEMORY
    int         lognum;
    MallocStats stat;
#endif 
} MemClient;












#if CMN_LOG_INTERNAL & CMN_LOG_MEMORY
#define MEM_MAX(a, b) ((a) > (b) ? (a) : (b))
#endif 


#define chunk2mem(p)    ((void*)((Ptr)(p) + CHUNKHEADERSIZE))
#define mem2chunk(mem)  ((MemChunk *)((Ptr)(mem) - CHUNKHEADERSIZE))






#define chunksize(p)        (((p)->size & ~0x01) << 1)
#define prevsize(p)         (((p)->prevSize & ~0x01) << 1)
#define set_size(p, sz)     \
  (((MemChunk *)(p))->size = (SIZE_S)((((sz) >> 1) & ~0x01) | \
                                     (((MemChunk *)(p))->size & 0x01)))
#define set_prevsize(p, sz) \
  (((MemChunk *)(p))->prevSize = (SIZE_S)((((sz) >> 1) & ~0x01) |\
                     (((MemChunk *)(p))->prevSize & 0x01)))

#define set_hd1(p, v)   ((p)->prevSize = (SIZE_S)(v))
#define set_hd2(p, v)   ((p)->size = (SIZE_S)(v))


#define prevchunk(p)    ((MemChunk *)(((Ptr)(p)) - prevsize(p)))
#define nextchunk(p)    ((MemChunk *)(((Ptr)(p)) + chunksize(p)))


#define chunk_isfree(p) ((((MemChunk *)(p))->size & 0x01) == 0)
#define chunk_inuse(p) ((((MemChunk *)(p))->size & 0x01) == 1)
#define set_inuse(p)    (((MemChunk *)(p))->size |= 0x01)
#define clear_inuse(p)  (((MemChunk *)(p))->size &= ~0x01)


#define chunk_has_gcbit(p) ((((MemChunk *)(p))->prevSize & 0x01) == 1)
#define set_gcbit(p)       (((MemChunk *)(p))->prevSize |= 0x01)
#define clear_gcbit(p)     (((MemChunk *)(p))->prevSize &= ~0x01)






#define offset2ptr(o)   ((MemChunk *)(memClients[id].base + ((o) << 2)))
#define ptr2offset(p)   ((OFFSET_T)((((Ptr)(p)) - (Ptr)memClients[id].base) >> 2))

#define forward(p)      (offset2ptr(((MemChunk *)(p))->fwd))
#define back(p)         (offset2ptr(((MemChunk *)(p))->bck))

#define set_fwd(p, q)   (((MemChunk *)(p))->fwd = ptr2offset(q))
#define set_bck(p, q)   (((MemChunk *)(p))->bck = ptr2offset(q))





#define remove_from_list(p)  do { \
  MemChunk *fwd = forward(p); \
  MemChunk *bck = back(p); \
  fwd->bck = (p)->bck; \
  bck->fwd = (p)->fwd; \
} while (0)

#define add_to_list(l, p) do { \
  (p)->fwd = (l)->fwd; \
  set_bck(p, l); \
  set_bck(forward(l), p); \
  set_fwd(l, p); \
} while (0)

#define append_to_list(l, p) do { \
  set_fwd(p, l); \
  set_bck(p, back(l)); \
  set_fwd(back(l), p); \
  set_bck(l, p); \
} while (0)




#define request2size(req) \
 (((SIZE_L)((req) + CHUNKHEADERSIZE + MALLOC_ALIGN_MASK) < \
  (SIZE_L)(MINCHUNKSIZE + MALLOC_ALIGN_MASK)) ? MINCHUNKSIZE : \
  (SIZE_L)(((req) + CHUNKHEADERSIZE + MALLOC_ALIGN_MASK) & ~(MALLOC_ALIGN_MASK)))







static MemClient memClients[CMN_CLIENT_NUMBER];






static SIZE_L   maxsizes[NUM_FREE_LISTS] = 
{
  16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 0x20000
};


static void gMemFreeChunk(CmnClientId id, MemPtr mem);
static short listIdx(SIZE_L n);

#if CMN_LOG_INTERNAL & CMN_LOG_MEMORY
    static void checkAllocatedChunk(CmnClientId id, MemChunk *p);
    static void gMemPrintUsage(CmnClientId id, const char *filename, int lineno);
#endif 



#ifdef _MSC_VER
  #pragma warning(disable: 4127)
#endif




int  gMemGetInside(CmnClientId id)
{
    return memClients[id].inside;
} 







jmp_buf *gMemGetJmpBuf(CmnClientId id)
{
    return &memClients[id].jmpbuf;
} 




void gMemSetInside(CmnClientId id, int inside)
{
    memClients[id].inside = inside;
} 








#if CMN_LOG_INTERNAL & CMN_LOG_MEMORY
MemPtr gMemAlloc(CmnClientId id, MemSize size, const char *filename, int lineno)
#else
MemPtr gMemAlloc(CmnClientId id, MemSize size)
#endif 
{
    void *p = gMemGcMalloc( id, size);

#if CMN_LOG_INTERNAL & CMN_LOG_MEMORY
    {
        const char *s = strrchr(filename, '\\');

        gMemPrintUsage(id,filename,lineno);

        if (s == NULL)
        {
            s = filename;
        }
        else
        {
            ++s;
        } 
        
        CMN_LOG_I(("MEM: + %#08x %6d %6d %6d %s (%d)\n",
            p, ++memClients[id].lognum, size, id, s, lineno));
    }
#endif 

    if ((p == NULL) && memClients[id].inside) 
    {
        longjmp( memClients[id].jmpbuf, 1);
    } 
    
    return p;
} 




#if CMN_LOG_INTERNAL & CMN_LOG_MEMORY
void gMemFree(CmnClientId id, MemPtr p, const char *filename, int lineno)
#else
void gMemFree(CmnClientId id, MemPtr p)
#endif 
{
#if CMN_LOG_INTERNAL & CMN_LOG_MEMORY
    if (p != NULL) 
    {
        const char *s = strrchr(filename, '\\');
        
        if (s == NULL)
        {
            s = filename;
        }
        else
        {
            s += 1;
        }
        
        CMN_LOG_I(("MEM: - %#08x %6d        %6d %s (%d)\n",
            p, ++memClients[id].lognum, id, s, lineno));
    }
#endif 

    gMemFreeChunk(id, p);

#if CMN_LOG_INTERNAL & CMN_LOG_MEMORY
    gMemPrintUsage(id,filename,lineno);
#endif 
}





void gMemTerminate(CmnClientId id)
{
    


    gMemGc(id);
} 





static short listIdx(SIZE_L n)
{
    short i;
    
    for (i = 0;  i < NUM_FREE_LISTS - 1 && maxsizes[i] <= n; i++)
        ;
    
    return i;
} 







short gMemInit(CmnClientId id, MemPtr mem, MemSize memsize)
{
    MemChunk *p;
    SIZE_L   size;
    short    i;

    if (memClients[id].isInitiated)
    {
        return 0;
    } 

    memset( &memClients[id], 0, sizeof(memClients[id]));
    
    
    memsize &= ~MALLOC_ALIGN_MASK;
    if ((mem == NULL) || (memsize < MINBLOCKSIZE) || (memsize > (1 << 17)))
    {
        unsigned j;

        CMN_LOG_I(("%s(%d): Failed to initialize internal memory pool.\n",
            __FILE__, __LINE__));

        j = 1 << 17;
        if (j == 0 || memsize > j)
        {
            CMN_LOG_I(("%s(%d): Internal memory pool larger than what can "
                "be handled (%u).\n", __FILE__, __LINE__, j));
        } 

        return -1;
    }
    memClients[id].base = mem;
    
    


    for (i = 0; i < NUM_FREE_LISTS; i++) 
    {
        p = (MemChunk *)((Ptr)memClients[id].base + i * MINCHUNKSIZE);
        set_hd1(p, 0);
        set_hd2(p, (MINCHUNKSIZE >> 1) | 0x01);
        p->fwd = ptr2offset(p);
        p->bck = ptr2offset(p);
        memClients[id].freelists[i] = p;
    }
    
    

    memClients[id].first = (MemChunk *)((Ptr)memClients[id].base + 
        NUM_FREE_LISTS * MINCHUNKSIZE);
    set_hd1(memClients[id].first, MINCHUNKSIZE >> 1);
    size = memsize - ((NUM_FREE_LISTS + 1) * MINCHUNKSIZE);
    set_hd2(memClients[id].first, size >> 1);
    add_to_list(memClients[id].freelists[listIdx(size)], memClients[id].first);
    
    

    memClients[id].last = (MemChunk *)(memClients[id].base + memsize - MINCHUNKSIZE);
    set_hd1(memClients[id].last, size >> 1);
    set_hd2(memClients[id].last, (MINCHUNKSIZE >> 1) | 0x01);
    
    memClients[id].isInitiated = 1;

    return 0;
} 














MemPtr gMemMalloc(CmnClientId id, MemSize size)
{
    MemChunk *p = 0;
    MemChunk *ptmp = 0;
    SIZE_L   nb;
    SIZE_L   sz = 250000;
    SIZE_L   remsize;
    short    i;
#if CMN_LOG_INTERNAL & CMN_LOG_MEMORY
    int      tmp_traverse_count  = 0;
#endif 
    
    

    nb = request2size(size);
    
    
    for (i = listIdx(nb); i < NUM_FREE_LISTS; i++) 
    {
        MemChunk *freelist = memClients[id].freelists[i];
        
        
        for (ptmp = forward(freelist); ptmp != NULL && ptmp != freelist;
            ptmp = forward(ptmp)) 
        {
            SIZE_L tmpsz = chunksize(ptmp);
            
#if CMN_LOG_INTERNAL & CMN_LOG_MEMORY
            ++tmp_traverse_count;
#endif 
            if (tmpsz == nb) 
            { 
                p = ptmp;
                sz = tmpsz;
                goto found;
            }
            else if (tmpsz > nb) 
            { 
                if (tmpsz < sz) 
                {   
                    p = ptmp;
                    sz = tmpsz;
                }
            }
        } 
        if (p != 0)
        {
            goto found;
        }
    } 
    
    return 0;
    
found:
    
    remove_from_list(p);
    remsize = sz - nb;
    
    if (remsize >= MINCHUNKSIZE)
    {
        
        MemChunk *q;
        MemChunk *next;
        MemChunk *l;
        
        sz = nb;
        
        q = (MemChunk *)((Ptr)p + sz);
        set_hd2(q, remsize >> 1);
        set_hd1(q, nb >> 1);
        next = nextchunk(q);
        set_prevsize(next, remsize);
        
        l = memClients[id].freelists[listIdx(remsize)];
        add_to_list(l, q);
    } 

    set_hd2(p, (sz >> 1) | 0x01);
    clear_gcbit(p);

⌨️ 快捷键说明

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