Ejemplo n.º 1
0
Archivo: mem3.c Proyecto: soubok/libset
/*
** Return a block of memory of at least nBytes in size.
** Return NULL if unable.
*/
static void *memsys3Malloc(int nByte){
  int i;
  int nBlock;
  int toFree;

  assert( sqlite3_mutex_held(mem.mutex) );
  assert( sizeof(Mem3Block)==8 );
  if( nByte<=0 ){
    nBlock = 2;
  }else{
    nBlock = (nByte + 15)/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 = mem.aiSmall[nBlock-2];
    if( i>0 ){
      memsys3UnlinkFromList(i, &mem.aiSmall[nBlock-2]);
      return memsys3Checkout(i, nBlock);
    }
  }else{
    int hash = nBlock % N_HASH;
    for(i=mem.aiHash[hash]; i>0; i=mem.aPool[i].u.list.next){
      if( mem.aPool[i-1].u.hdr.size==nBlock ){
        memsys3UnlinkFromList(i, &mem.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( mem.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<SQLITE_MEMORY_SIZE*2; toFree *= 2){
    memsys3OutOfMemory(toFree);
    if( mem.iMaster ){
      memsys3Link(mem.iMaster);
      mem.iMaster = 0;
      mem.szMaster = 0;
    }
    for(i=0; i<N_HASH; i++){
      memsys3Merge(&mem.aiHash[i]);
    }
    for(i=0; i<MX_SMALL-1; i++){
      memsys3Merge(&mem.aiSmall[i]);
    }
    if( mem.szMaster ){
      memsys3Unlink(mem.iMaster);
      if( mem.szMaster>=nBlock ){
        return memsys3FromMaster(nBlock);
      }
    }
  }

  /* If none of the above worked, then we fail. */
  return 0;
}
Ejemplo n.º 2
0
*/该函数返回至少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
}