/*
** 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;
}
Exemple #2
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
}