/**
 * Allocate a chunk of specified size
 *
 * @return pointer to allocated chunk, if allocation was successful,
 *         or NULL - if not enough memory.
 */
uint8_t* __attr_always_inline___
mem_pools_alloc (void)
{
#ifdef MEM_GC_BEFORE_EACH_ALLOC
    mem_run_try_to_give_memory_back_callbacks (MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_HIGH);
#endif /* MEM_GC_BEFORE_EACH_ALLOC */

    mem_check_pools ();

    do
    {
        if (mem_free_chunk_p != NULL)
        {
            mem_pool_chunk_t *chunk_p = mem_free_chunk_p;

            MEM_POOLS_STAT_ALLOC_CHUNK ();

#ifndef JERRY_NDEBUG
            mem_free_chunks_number--;
#endif /* !JERRY_NDEBUG */

            VALGRIND_DEFINED_SPACE (chunk_p, MEM_POOL_CHUNK_SIZE);

            mem_free_chunk_p = chunk_p->u.free.next_p;

            VALGRIND_UNDEFINED_SPACE (chunk_p, MEM_POOL_CHUNK_SIZE);


            mem_check_pools ();

            VALGRIND_FREYA_MALLOCLIKE_SPACE (chunk_p, MEM_POOL_CHUNK_SIZE);
            return (uint8_t *) chunk_p;
        }
        else
        {
            mem_pools_alloc_longpath ();

            /* the assertion guarantees that there will be no more than two iterations */
            JERRY_ASSERT (mem_free_chunk_p != NULL);
        }
    } while (true);
} /* mem_pools_alloc */
/**
 * Allocate a chunk of specified size
 *
 * @return pointer to allocated chunk, if allocation was successful,
 *         or NULL - if not enough memory.
 */
uint8_t*
mem_pools_alloc (void)
{
  if (mem_pools == NULL || mem_pools->first_free_chunk == MEM_POOL_CHUNKS_NUMBER)
  {
    if (!mem_pools_alloc_longpath ())
    {
      return NULL;
    }
  }

  JERRY_ASSERT (mem_pools != NULL && mem_pools->first_free_chunk != MEM_POOL_CHUNKS_NUMBER);

  /**
   * And allocate chunk within it.
   */
  mem_free_chunks_number--;

  MEM_POOLS_STAT_ALLOC_CHUNK ();

  return mem_pool_alloc_chunk (mem_pools);
} /* mem_pools_alloc */