Пример #1
0
static void *vm_malloc_pages(VM *vm, size_t len, size_t alignment, int dirty_ok)
{
  char *r;
  FreeBlock *blockfree = vm->freeblocks;

  if (!page_size)
    page_size = getpagesize();

  /* Round up to nearest page: */
  if (len & (page_size - 1))
    len += page_size - (len & (page_size - 1));

  /* Something from the cache, perhaps? */
  r = alloc_cache_find_pages(blockfree, len, alignment, dirty_ok);
  if(!r) {
    /* attempt to allocate from OS */
    r = os_vm_alloc_pages(len + alignment);
    if(r == (void *)-1) { return NULL; }

    if (alignment) {
      /* We allocated too large so we can choose the alignment. */
      size_t extra    = alignment;
      char *real_r    = (char*)(((unsigned long)r + (alignment - 1)) & (~(alignment - 1)));
      long pre_extra  = real_r - r;

      /* in front extra */
      if (pre_extra) { os_vm_free_pages(r, pre_extra); }
      /* in back extra exists */
      if (pre_extra < extra) {
        if (pre_extra == 0) {
          /* Instead of actually unmapping, put it in the cache, and there's
             a good chance we can use it next time: */
          vm_memory_allocated_inc(vm, extra);
          alloc_cache_return_mem(vm, real_r + len, extra, 1);
        } 
        else { os_vm_free_pages(real_r + len, extra - pre_extra); }
      }
      r = real_r;
    }

    vm_memory_allocated_inc(vm, len);
  }

  return r;
}
Пример #2
0
static void *alloc_cache_alloc_page(AllocCacheBlock *blockfree,  size_t len, size_t alignment, int dirty_ok, intptr_t *size_diff)
{
  char *r;

  /* Something from the cache, perhaps? */
  r = alloc_cache_find_pages(blockfree, len, alignment, dirty_ok);
  if(!r) {
    /* attempt to allocate from OS */
    size_t extra = (alignment ? (alignment + CACHE_SEED_PAGES * APAGE_SIZE) : 0);
    r = os_alloc_pages(len + extra);
    if(r == (void *)-1) { return NULL; }

    if (alignment) {
      /* We allocated too large so we can choose the alignment. */
      char *real_r    = (char*)(((uintptr_t)r + (alignment - 1)) & (~(alignment - 1)));
      intptr_t pre_extra  = real_r - r;

      /* in front extra */
      if (pre_extra) { 
        /* printf("FREEING FRONT %p %lx\n", r, pre_extra); */
        os_free_pages(r, pre_extra); }
      /* in back extra exists */
      if (pre_extra < extra) {
        if (pre_extra == 0) {
          /* Instead of actually unmapping, put it in the cache, and there's
             a good chance we can use it next time: */
          (*size_diff) += extra;
          (*size_diff) += alloc_cache_free_page(blockfree, real_r + len, extra, 1, 1);
        } else { 
          os_free_pages(real_r + len, extra - pre_extra);
        }
      }
      r = real_r;
    }

    (*size_diff) += len;
  }

  return r;
}