예제 #1
0
파일: mempool.cpp 프로젝트: bj-/Arduino
memhandle
MemoryPool::allocBlock(memaddress size)
{
  #if ACTLOGLEVEL>=LOG_DEBUG_V3
    LogObject.uart_send_strln(F("MemoryPool::allocBlock(memaddress size) DEBUG_V3:Function started"));
  #endif
  if (size==0)
    {
    #if ACTLOGLEVEL>=LOG_WARNING
      LogObject.uart_send_strln(F("MemoryPool::allocBlock(memaddress size) WARNING: Called 0 size"));
    #endif
    return NOBLOCK;
    }

  memblock* best = NULL;
  memhandle cur = POOLSTART;
  memblock* block = &blocks[POOLSTART];
  memaddress bestsize = MEMPOOL_SIZE + 1;

  do
    {
      memhandle next = block->nextblock;
      memaddress freesize = ( next == NOBLOCK ? blocks[POOLSTART].begin + MEMPOOL_SIZE : blocks[next].begin) - block->begin - block->size;
      if (freesize == size)
        {
          best = &blocks[cur];
          goto found;
        }
      if (freesize > size && freesize < bestsize)
        {
          bestsize = freesize;
          best = &blocks[cur];
        }
      if (next == NOBLOCK)
        {
          if (best)
            goto found;
          else
            goto collect;
        }
      block = &blocks[next];
      cur = next;
    }
  while (true);

  collect:
    {
      cur = POOLSTART;
      block = &blocks[POOLSTART];
      memhandle next;
      while ((next = block->nextblock) != NOBLOCK)
        {
          memaddress dest = block->begin + block->size;
          memblock* nextblock = &blocks[next];
          memaddress* src = &nextblock->begin;
          if (dest != *src)
            {
#ifdef MEMPOOL_MEMBLOCK_MV
              MEMPOOL_MEMBLOCK_MV(dest,*src,nextblock->size);
#endif
              *src = dest;
            }
          block = nextblock;
        }
      if (blocks[POOLSTART].begin + MEMPOOL_SIZE - block->begin - block->size >= size)
        best = block;
      else
        goto notfound;
    }

  found:
    {
      block = &blocks[POOLOFFSET];
      for (cur = POOLOFFSET; cur < MEMPOOL_NUM_MEMBLOCKS + POOLOFFSET; cur++)
        {
          if (block->size)
            {
              block++;
              continue;
            }
          memaddress address = best->begin + best->size;
#ifdef MEMBLOCK_ALLOC
          MEMBLOCK_ALLOC(address,size);
#endif
          block->begin = address;
          block->size = size;
          block->nextblock = best->nextblock;
          best->nextblock = cur;
          #if ACTLOGLEVEL>=LOG_DEBUG_V3
            LogObject.uart_send_str(F("MemoryPool::allocBlock(memaddress size) DEBUG_V3:Allocated "));
            LogObject.uart_send_dec(size);
            LogObject.uart_send_str(F("byte to block:"));
            LogObject.uart_send_decln(cur);
          #endif
          return cur;
        }
    }

  notfound:
  #if ACTLOGLEVEL>=LOG_ERR
    LogObject.uart_send_strln(F("MemoryPool::allocBlock(memaddress size) ERROR:Failed to allocate memory for packet"));
  #endif
  return NOBLOCK;
}
예제 #2
0
memhandle
MemoryPool::allocBlock(memaddress size)
{
  memblock* best = NULL;
  memhandle cur = POOLSTART;
  memblock* block = &blocks[POOLSTART];
  memaddress bestsize = MEMPOOL_SIZE + 1;

  do
    {
      memhandle next = block->nextblock;
      memaddress freesize = ( next == NOBLOCK ? blocks[POOLSTART].begin + MEMPOOL_SIZE : blocks[next].begin) - block->begin - block->size;
      if (freesize == size)
        {
          best = &blocks[cur];
          goto found;
        }
      if (freesize > size && freesize < bestsize)
        {
          bestsize = freesize;
          best = &blocks[cur];
        }
      if (next == NOBLOCK)
        {
          if (best)
            goto found;
          else
            goto collect;
        }
      block = &blocks[next];
      cur = next;
    }
  while (true);

  collect:
    {
      cur = POOLSTART;
      block = &blocks[POOLSTART];
      memhandle next;
      while ((next = block->nextblock) != NOBLOCK)
        {
          memaddress dest = block->begin + block->size;
          memblock* nextblock = &blocks[next];
          memaddress* src = &nextblock->begin;
          if (dest != *src)
            {
#ifdef MEMPOOL_MEMBLOCK_MV
              MEMPOOL_MEMBLOCK_MV(dest,*src,nextblock->size);
#endif
              *src = dest;
            }
          block = nextblock;
        }
      if (blocks[POOLSTART].begin + MEMPOOL_SIZE - block->begin - block->size >= size)
        best = block;
      else
        goto notfound;
    }

  found:
    {
      block = &blocks[POOLOFFSET];
      for (cur = POOLOFFSET; cur < MEMPOOL_NUM_MEMBLOCKS + POOLOFFSET; cur++)
        {
          if (block->size)
            {
              block++;
              continue;
            }
          memaddress address = best->begin + best->size;
#ifdef MEMBLOCK_ALLOC
          MEMBLOCK_ALLOC(address,size);
#endif
          block->begin = address;
          block->size = size;
          block->nextblock = best->nextblock;
          best->nextblock = cur;
          return cur;
        }
    }

  notfound: return NOBLOCK;
}