/*
** Carve a piece off of the end of the mem3.iMaster free chunk.
** Return a pointer to the new allocation.  Or, if the master chunk
** is not large enough, return 0.
*/
static void *memsys3FromMaster(u32 nBlock){
  assert( sqlite4_mutex_held(mem3.mutex) );
  assert( mem3.szMaster>=nBlock );
  if( nBlock>=mem3.szMaster-1 ){
    /* Use the entire master */
    void *p = memsys3Checkout(mem3.iMaster, mem3.szMaster);
    mem3.iMaster = 0;
    mem3.szMaster = 0;
    mem3.mnMaster = 0;
    return p;
  }else{
    /* Split the master block.  Return the tail. */
    u32 newi, x;
    newi = mem3.iMaster + mem3.szMaster - nBlock;
    assert( newi > mem3.iMaster+1 );
    mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = nBlock;
    mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x |= 2;
    mem3.aPool[newi-1].u.hdr.size4x = nBlock*4 + 1;
    mem3.szMaster -= nBlock;
    mem3.aPool[newi-1].u.hdr.prevSize = mem3.szMaster;
    x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
    mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
    if( mem3.szMaster < mem3.mnMaster ){
      mem3.mnMaster = mem3.szMaster;
    }
    return (void*)&mem3.aPool[newi];
  }
}
示例#2
0
//从iMaster开始的大chunk上切下nBlock的chunk供用户使用,返回该空间的地址。
static void *memsys3FromMaster(u32 nBlock) {
    assert( sqlite3_mutex_held(mem3.mutex) );
    assert( mem3.szMaster>=nBlock );  //主要块的大小若小于nBlock,则终止程序
    if( nBlock>=mem3.szMaster-1 ) {  //若nBlock等于该主要块大小,则使用整个主chunk
        /* Use the entire master */
        void *p = memsys3Checkout(mem3.iMaster, mem3.szMaster);
        mem3.iMaster = 0;
        mem3.szMaster = 0;
        mem3.mnMaster = 0;
        return p;
    } else {      //若nBlock小于主chunk大小,则分裂master free chunk,返回尾部地址
        /* Split the master block.  Return the tail. */
        u32 newi, x;
        newi = mem3.iMaster + mem3.szMaster - nBlock; //将多出来的空间赋给newi
        assert( newi > mem3.iMaster+1 ); //除去nBlock大小外的空间小于等于mem3.iMaster,则终止
        mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = nBlock;//分裂出的chunk
        mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x |= 2;  //置前一块为已使用
        mem3.aPool[newi-1].u.hdr.size4x = nBlock*4 + 1;
        mem3.szMaster -= nBlock;       //当前chunk大小为nBlock
        mem3.aPool[newi-1].u.hdr.prevSize = mem3.szMaster; //剩余部分的前一块大小也即为nBlock
        x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
        mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
        if( mem3.szMaster < mem3.mnMaster ) { //若当前chunk空间小于块中的最小空间,则将最小空间大小赋值为当前块空间大小
            mem3.mnMaster = mem3.szMaster;
        }
        return (void*)&mem3.aPool[newi];  //返回新空间地址
    }
}
示例#3
0
文件: mem3.c 项目: soubok/libset
/*
** Carve a piece off of the end of the mem.iMaster free chunk.
** Return a pointer to the new allocation.  Or, if the master chunk
** is not large enough, return 0.
*/
static void *memsys3FromMaster(int nBlock){
  assert( sqlite3_mutex_held(mem.mutex) );
  assert( mem.szMaster>=nBlock );
  if( nBlock>=mem.szMaster-1 ){
    /* Use the entire master */
    void *p = memsys3Checkout(mem.iMaster, mem.szMaster);
    mem.iMaster = 0;
    mem.szMaster = 0;
    mem.mnMaster = 0;
    return p;
  }else{
    /* Split the master block.  Return the tail. */
    int newi;
    newi = mem.iMaster + mem.szMaster - nBlock;
    assert( newi > mem.iMaster+1 );
    mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.prevSize = -nBlock;
    mem.aPool[newi-1].u.hdr.size = -nBlock;
    mem.szMaster -= nBlock;
    mem.aPool[newi-1].u.hdr.prevSize = mem.szMaster;
    mem.aPool[mem.iMaster-1].u.hdr.size = mem.szMaster;
    if( mem.szMaster < mem.mnMaster ){
      mem.mnMaster = mem.szMaster;
    }
    return (void*)&mem.aPool[newi];
  }
}
/*
** Return a block of memory of at least nBytes in size.
** Return NULL if unable.
**
** This function assumes that the necessary mutexes, if any, are
** already held by the caller. Hence "Unsafe".
*/
static void *memsys3MallocUnsafe(int nByte){
  u32 i;
  u32 nBlock;
  u32 toFree;

  assert( sqlite4_mutex_held(mem3.mutex) );
  assert( sizeof(Mem3Block)==8 );
  if( nByte<=12 ){
    nBlock = 2;
  }else{
    nBlock = (nByte + 11)/8;
  }
  assert( nBlock>=2 );

  /* STEP 1:
  ** Look for an entry of the correct size in either the small
  ** chunk table or in the large chunk hash table.  This is
  ** successful most of the time (about 9 times out of 10).
  */
  if( nBlock <= MX_SMALL ){
    i = mem3.aiSmall[nBlock-2];
    if( i>0 ){
      memsys3UnlinkFromList(i, &mem3.aiSmall[nBlock-2]);
      return memsys3Checkout(i, nBlock);
    }
  }else{
    int hash = nBlock % N_HASH;
    for(i=mem3.aiHash[hash]; i>0; i=mem3.aPool[i].u.list.next){
      if( mem3.aPool[i-1].u.hdr.size4x/4==nBlock ){
        memsys3UnlinkFromList(i, &mem3.aiHash[hash]);
        return memsys3Checkout(i, nBlock);
      }
    }
  }

  /* STEP 2:
  ** Try to satisfy the allocation by carving a piece off of the end
  ** of the master chunk.  This step usually works if step 1 fails.
  */
  if( mem3.szMaster>=nBlock ){
    return memsys3FromMaster(nBlock);
  }


  /* STEP 3:  
  ** Loop through the entire memory pool.  Coalesce adjacent free
  ** chunks.  Recompute the master chunk as the largest free chunk.
  ** Then try again to satisfy the allocation by carving a piece off
  ** of the end of the master chunk.  This step happens very
  ** rarely (we hope!)
  */
  for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2){
    memsys3OutOfMemory(toFree);
    if( mem3.iMaster ){
      memsys3Link(mem3.iMaster);
      mem3.iMaster = 0;
      mem3.szMaster = 0;
    }
    for(i=0; i<N_HASH; i++){
      memsys3Merge(&mem3.aiHash[i]);
    }
    for(i=0; i<MX_SMALL-1; i++){
      memsys3Merge(&mem3.aiSmall[i]);
    }
    if( mem3.szMaster ){
      memsys3Unlink(mem3.iMaster);
      if( mem3.szMaster>=nBlock ){
        return memsys3FromMaster(nBlock);
      }
    }
  }

  /* If none of the above worked, then we fail. */
  return 0;
}
示例#5
0
//给用户分配n字节的空间,返回该空间的地址。
//该函数返回至少n字节大小的block,没有则返回null。该函数假设所有必要的互斥锁都上了,所以不安全
static void *memsys3MallocUnsafe(int nByte) {
    u32 i;
    u32 nBlock;
    u32 toFree;

    assert( sqlite3_mutex_held(mem3.mutex) );   //如果不能加锁,则终止程序
    assert( sizeof(Mem3Block)==8 );   //若Mem3Block大小为8,继续往下执行
    if( nByte<=12 ) {               //给nBlock赋值
        nBlock = 2;
    } else {
        nBlock = (nByte + 11)/8;
    }
    assert( nBlock>=2 );

    /* STEP 1:
    ** Look for an entry of the correct size in either the small
    ** chunk table or in the large chunk hash table.  This is
    ** successful most of the time (about 9 times out of 10).
    */
    //首先在小chunk或者大chunk中寻找正确大小块的入口,一般都会成功
    if( nBlock <= MX_SMALL ) {       //nBlock小于MX_SMALL,则在小chunk中找
        i = mem3.aiSmall[nBlock-2];
        if( i>0 ) {
            memsys3UnlinkFromList(i, &mem3.aiSmall[nBlock-2]);
            return memsys3Checkout(i, nBlock);  //返回找到的满足的chunk
        }
    } else {   //若nBlock大于MX_SMALL,则在大chunk中找
        int hash = nBlock % N_HASH;
        for(i=mem3.aiHash[hash]; i>0; i=mem3.aPool[i].u.list.next) {
            if( mem3.aPool[i-1].u.hdr.size4x/4==nBlock ) {
                memsys3UnlinkFromList(i, &mem3.aiHash[hash]);
                return memsys3Checkout(i, nBlock);   //返回找到的chunk
            }
        }
    }

    /* STEP 2:
    ** Try to satisfy the allocation by carving a piece off of the end
    ** of the master chunk.  This step usually works if step 1 fails.
    */
    //尝试从master chunk中分裂出合适的空间,第一步失败才执行
    if( mem3.szMaster>=nBlock ) {
        return memsys3FromMaster(nBlock);  //从master chunk中获取chunk
    }


    /* STEP 3:
    ** Loop through the entire memory pool.  Coalesce adjacent free
    ** chunks.  Recompute the master chunk as the largest free chunk.
    ** Then try again to satisfy the allocation by carving a piece off
    ** of the end of the master chunk.  This step happens very
    ** rarely (we hope!)
    */
    //遍历整个内存池,合并相邻空闲chunk,重新计算主要的chunk大小,
    //再次尝试从master chunk中分裂出满足分配条件的chunk。前面都不行才执行该步骤。
    for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2) { //遍历内存池
        memsys3OutOfMemory(toFree);     //不够分配则释放
        if( mem3.iMaster ) {              //master chunk存在,将其链接到相应块索引表中
            memsys3Link(mem3.iMaster);
            mem3.iMaster = 0;
            mem3.szMaster = 0;
        }
        for(i=0; i<N_HASH; i++) {
            memsys3Merge(&mem3.aiHash[i]);  //链接相邻空chunk到aiHash中
        }
        for(i=0; i<MX_SMALL-1; i++) {
            memsys3Merge(&mem3.aiSmall[i]); //链接相邻空chunk到aiSmall中
        }
        if( mem3.szMaster ) {            //当前master chunk不为0,则从索引表中断开
            memsys3Unlink(mem3.iMaster);
            if( mem3.szMaster>=nBlock ) {
                return memsys3FromMaster(nBlock); //返回得到的内存空间
            }
        }
    }

    /* If none of the above worked, then we fail. */
    return 0;  //若上面三步都失败了,那就失败了,返回0
}