Пример #1
0
void heap_insert(heap_t* heap, void* data, long long int key) {
  int findex = heap->size;
  if (findex == heap->private_size) {
    expand_heap(heap);
  }
  
  findex = heap->size;
  HEAP_NODE(heap, findex).key = key;
  HEAP_NODE(heap, findex).data = data;
  up_heap(heap, findex);

  heap->size++;
}
Пример #2
0
CAMLexport value caml_alloc_shr (mlsize_t wosize, tag_t tag)
{
  header_t *hp;
  value *new_block;

  if (wosize > Max_wosize) caml_raise_out_of_memory ();
  hp = caml_fl_allocate (wosize);
  if (hp == NULL){
    new_block = expand_heap (wosize);
    if (new_block == NULL) {
      if (caml_in_minor_collection)
        caml_fatal_error ("Fatal error: out of memory.\n");
      else
        caml_raise_out_of_memory ();
    }
    caml_fl_add_blocks ((value) new_block);
    hp = caml_fl_allocate (wosize);
  }

  Assert (Is_in_heap (Val_hp (hp)));

  /* Inline expansion of caml_allocation_color. */
  if (caml_gc_phase == Phase_mark
      || (caml_gc_phase == Phase_sweep && (addr)hp >= (addr)caml_gc_sweep_hp)){
    Hd_hp (hp) = Make_header (wosize, tag, Caml_black);
  }else{
    Assert (caml_gc_phase == Phase_idle
            || (caml_gc_phase == Phase_sweep
                && (addr)hp < (addr)caml_gc_sweep_hp));
    Hd_hp (hp) = Make_header (wosize, tag, Caml_white);
  }
  Assert (Hd_hp (hp) == Make_header (wosize, tag, caml_allocation_color (hp)));
  caml_allocated_words += Whsize_wosize (wosize);
  if (caml_allocated_words > caml_minor_heap_wsz){
    caml_urge_major_slice ();
  }
#ifdef DEBUG
  {
    uintnat i;
    for (i = 0; i < wosize; i++){
      Field (Val_hp (hp), i) = Debug_uninit_major;
    }
  }
#endif
  return Val_hp (hp);
}
Пример #3
0
EXTERN value alloc_shr (mlsize_t wosize, tag_t tag)
{
  char *hp, *new_block;

  hp = fl_allocate (wosize);
  if (hp == NULL){
    new_block = expand_heap (wosize);
    if (new_block == NULL) raise_out_of_memory ();
    fl_add_block (new_block);
    hp = fl_allocate (wosize);
    if (hp == NULL) fatal_error ("alloc_shr: expand heap failed\n");
  }

  Assert (Is_in_heap (Val_hp (hp)));

  if (gc_phase == Phase_mark || (addr)hp >= (addr)gc_sweep_hp){
    Hd_hp (hp) = Make_header (wosize, tag, Black);
  }else{
    Hd_hp (hp) = Make_header (wosize, tag, White);
  }
  allocated_words += Whsize_wosize (wosize);
  if (allocated_words > Wsize_bsize (minor_heap_size)) force_minor_gc ();
  return Val_hp (hp);
}
Пример #4
0
void
wsload(FILE * f1, int user)
{
  nialptr     addr,
              cnt,
              lastfree,
              nextaddr;
  char        stampcheck[256];


  /* read global structure */
  testrderr(readblock(f1, (char *) &G, (long) sizeof G, false, 0L, 0));

  /* nprintf(OF_DEBUG,"wssize read in is %ld\n",wssize); */

  /* check workspace stamp */

#ifdef DEBUG
  strcpy(stampcheck, systemname);
  strcat(stampcheck, nialversion);
  strcat(stampcheck, " (debug)");
#else
  strcpy(stampcheck, systemname);
  strcat(stampcheck, nialversion);
#endif


  if (strcmp(stampcheck, wsstamp) != 0) {
    if (user)
      exit_cover(NC_USER_WS_WRONG_VERSION_W);
    else
      exit_cover(NC_WS_WRONG_VERSION_S);
  }

  /* check that the new workspace will fit in the current memory */

/* printf("wssize %d memsize %d instartup %d\n",wssize,memsize,instartup); */

  if (wssize + MINHEAPSPACE > memsize) {
    if (expansion)
      expand_heap(wssize - memsize);
    else {
      if (interpreter_running) {
        nprintf(OF_MESSAGE, "Not enough memory to load the workspace\n");
        exit_cover(NC_MEM_EXPAND_FAILED_W);
      }
      else {
        nprintf(OF_NORMAL, "Unable to load the workspace\n");
        longjmp(init_buf, NC_MEM_EXPAND_NOT_TRIED_F);
      }
    }
  }

  /* set the link to the first free block */
  fwdlink(freelisthdr) = firstfree;

  /* read memory blocks */

  lastfree = freelisthdr;
  nextaddr = membase;

  testrderr(readblock(f1, (char *) &cnt, (long) sizeof cnt, false, 0L, 0));
  testrderr(readblock(f1, (char *) &addr, (long) sizeof addr, false, 0L, 0));
  while (cnt != 0) {

    /* nprintf(OF_DEBUG,"reading addr %d cnt %d\n",addr,cnt); */

    testrderr(readblock(f1, (char *) &mem[addr],
                        (long) (bytespu * cnt), false, 0L, 0));
    nextaddr = addr + cnt;

    /* get info for next block */
    testrderr(readblock(f1, (char *) &cnt, (long) sizeof cnt, false, 0L, 0));

    if (cnt != 0) {          /* still blocks to read */
      testrderr(readblock(f1, (char *) &addr, (long) sizeof addr, false, 0L, 0));

      /* set up free block between used blocks */
      fwdlink(lastfree) = nextaddr;
      blksize(nextaddr) = addr - nextaddr;

      /* nprintf(OF_DEBUG,"inserting freeblock %d size %d\n",nextaddr,blksize(nextaddr)); */

      bcklink(nextaddr) = lastfree;
      set_freetag(nextaddr); /* sets free tag */
      set_endinfo(nextaddr);
      lastfree = nextaddr;
    }
  }

  if (nextaddr < memsize) {  /* add in last free block */
    fwdlink(lastfree) = nextaddr;
    blksize(nextaddr) = memsize - nextaddr;

    /* nprintf(OF_DEBUG,"adding last freeblock %d size %d\n",nextaddr,blksize(nextaddr)); */

    bcklink(nextaddr) = lastfree;
    set_freetag(nextaddr);
    set_endinfo(nextaddr);
    fwdlink(nextaddr) = TERMINATOR; /* to complete the chain */
  }
  else
    fwdlink(lastfree) = TERMINATOR; /* to complete the chain */

/* reset atomtbl stuff */
atomtblsize = tally(atomtblbase);
atomtbl = pfirstitem(atomtblbase);

#ifdef DEBUG
  memchk();
#endif

  closefile(f1);
  return;

fail:
  closefile(f1);
  nprintf(OF_NORMAL_LOG, "workspace failed to read correctly\n");
  exit_cover(NC_WS_LOAD_ERR_F);
}
Пример #5
0
/**
 * @brief Solicita la asignacion de memoria dentro de un heap.
 * Primero se busca dentro de las regiones libres, una que tenga
 * un tamaño cercano al buscado. Si no existe una region, expande el heap.
 * Si existe suficiente espacio adicional al buscado dentro de la region, esta
 * region se divide en dos: una region asignada, que se retorna, y una
 * region libre con el espacio sobrante.
 * @param heap Heap del cual se desea obtener el espacio
 * @param size Cantidad de memoria a asignar
 * @return Apuntador a la region de memoria asignada. 0 si no se puede
 * asignar memoria.
 *
 * @verbatim
     Ejemplo 1:
     se solicita 5M de memoria, en este caso hay una región con la cantidad
     disponible

     Heap X
     -------     -------     -------     -------     -------
     |     |     |     |     |     |     |     |     |     |
     | 36K |-----| 3M  |-----| 6M  |-----| 15M |-----| 15K |
     |Libre|     |Usado|     |Usado|     |Libre|     |Usado|
     -------     -------     -------     -------     -------
                                           |
                                           |
                                           |---->Se divide esta región en
                                                 asignada y libre

     -------     -------     -------     -------     -------     -------
     |     |     |     |     |     |     |     |     |     |     |     |
     | 36K |-----| 3M  |-----| 6M  |-----| 5M  |-----| 10M |-----| 15K |
     |Libre|     |Usado|     |Usado|     |Usado|     |Libre|     |Usado|
     -------     -------     -------     -------     -------     -------
     Se retorna el apuntador a la región de memoria asignada.

     Ejemplo 2:
     se solicita 5M de memoria, en este caso no hay una región con la cantidad
     disponible
     -------     -------     -------     -------     -------
     |     |     |     |     |     |     |     |     |     |
     | 36K |-----| 3M  |-----| 6M  |-----| 1M  |-----| 15K |
     |Libre|     |Usado|     |Usado|     |Libre|     |Usado|
     -------     -------     -------     -------     -------
     en este caso la función retorna 0 indicando que no hay regiones con memoria
     suficiente

 * @endverbatim
 */
void * alloc_from_heap(heap_t * heap, unsigned int size) {

	/* Region candidata a asignar */
	memreg_header_t * candidate = 0;
	
	/* Apuntador al pie original de la region candidata */
	memreg_footer_t * candidate_footer;

	/* Tamanio original de la region de memoria candidata a asignar */
	unsigned int candidate_limit;

	/* Apuntadores al nuevo encabezado y pie, si se requiere partir
	 * una region de memoria libre */

	/* Apuntador al nuevo encabezado */
	memreg_header_t * new_header;
	/* Apuntador al nuevo pie */
	memreg_footer_t * new_footer;

	unsigned int requested_size = 0;

	/* Verificar que el tamaño solicitado sea mayor o igual que el minimo
	 * tamaño que se puede asignar */

	if (size < MEMREG_GRANULARITY) {
		size = MEMREG_GRANULARITY;
	}

	/* Ahora buscar una region marcada como libre, que tenga
	 * un tamano mayor o igual a la cantidad  solicitada.
	 */

	candidate = heap->free->head;
	while (candidate != 0 && candidate->limit < size ) {
		candidate = candidate->next_memreg_header;
	}

	/* No existe una region candidata, tratar de expandir  el heap */
	if (candidate == 0) {
		/*Expandir la pila para que contenga la nueva region candidata.*/
		candidate = expand_heap(heap, size);
		//printf("Trying to expand the heap in %d bytes..\n", size);
	}

	/* No existe region candidata luego de expandir el heap? */
	if (candidate == 0) {
		//printf("Unable to expand the heap in %d bytes!\n", size);
		return 0; /* No se puede asignar memoria! */
	}

	/* La region candidata se encuentra en la lista de regiones disponibles,
	 * primero extraerla de la lista */
	remove_memreg_header(heap->free, candidate);

	//printf("Candidate region for allocating %u bytes: ", size);
	//print_memory_region(candidate);

	/* Marcar la region como usada */
	candidate->used = 1;

	/* La region candidata se debe partir? */
	if (candidate->limit - size >=
		MEMREG_FOOTER_SIZE + MEMREG_MIN_SIZE) {

		/*
		printf("Attempting to split existing memory region [%u]\n",
				(unsigned int)candidate);
		*/

		/* Almacenar el tamaño original de la region candidata */
		candidate_limit = candidate->limit;

		/* Recuperar el pie original, para actualizarlo mas adelante */
		candidate_footer = (memreg_footer_t *)(candidate->base +
								candidate_limit);

		/* Y actualizar el nuevo tamaño de la region candidata */
		candidate->limit = size;

		/* Validacion: Verificar si el footer original es valido. */

		if (candidate_footer->header != candidate
				|| candidate_footer->base != candidate->base) {
			//printf("Error reading old footer!\n");
			return 0;
		}

		/* Crear el nuevo footer para la region de memoria asignada,
		 * usando el tamano solicitado */
		new_footer = (memreg_footer_t *)(candidate->base +  size);
		new_footer->base = candidate->base;
		new_footer->header = candidate;

		//printf("New footer at %u\n", new_footer);


		/*
		 printf("Splitting region ending at %u. Top=%u. Is this the last region?\n",
				(unsigned int)candidate_footer +
				MEMREG_FOOTER_SIZE, heap->top);
		*/

		/* Crear el nuevo header, para la region de memoria restante.
		 * Este header se ubica inmediatamente despues de new_footer */
		new_header = (memreg_header_t * )(candidate->base + size +
				MEMREG_FOOTER_SIZE);
		new_header->base = (unsigned int)new_header + MEMREG_HEADER_SIZE;
		/* El tamaño de esta region libre luego de asignar size :
	     * tamaño original - size - sizeof(new_footer) - sizeof(new_header) */
		new_header->limit = candidate_limit - size - MEMREG_FOOTER_SIZE
							- MEMREG_HEADER_SIZE;

		new_header->used = 0;
		new_header->next_memreg_header = 0;
		new_header->prev_memreg_header = 0;

	/* Validacion : verificar si los calculos para el limite son correctos.
	 * El pie original de la region deberia estar ubicado en
	 * new_header->base + new_header->limit, es decir justo al final de la
	 * nueva region de memoria */
		if (new_header->base + new_header->limit !=
				(unsigned int)candidate_footer) {
			//printf("ERROR! original footer is out of place!. Whatever...");
		}


		/* Actualizar el footer original para que apunte al nuevo header */
		candidate_footer->header = new_header;
					candidate_footer->base = new_header->base;

		/* Validacion: Si la region candidata no es la ultima region
		   definida en el heap, agregar el espacio restante luego
		   de dividirla como una nueva region disponible dentro del heap */
		if (heap->top != (unsigned int)candidate_footer + MEMREG_FOOTER_SIZE){
			//printf("No!\n");
			/* Insertar la region en la lista de regiones disponibles */
			push_front_memreg_header(heap->free, new_header);
		}else {
			//printf("YES!");
			/* La region candidata era la ultima en el heap, Verificar si
			 * es necesario contraer.
			 * Solo se contrae el heap cuando el numero de regiones marcadas
			 * como libres es mayor a FREE_MEMREGS_LIMIT
			 *  */
			/* Ya existen suficientes regiones disponibles? */
			//printf("Have to contract the heap?\n");
			if (heap->free->count > FREE_MEMREGS_LIMIT) {
				//printf("Yes!\n");
				/* Liberar esta region, contrayendo el heap */
				//printf("Contracting the heap from %u ", heap->top);
				heap->top = (unsigned int)new_footer + MEMREG_FOOTER_SIZE;

				/*Borrar el header que se creo */
				new_header->base = 0;
				new_header->limit = 0;
				new_header->used = 0;

				/* Borrar el footer original*/
				candidate_footer->header = 0;
				candidate_footer->base = 0;
				//printf("to %u\n", heap->top);
			}else { //Agregar la region restante a la lista de disponibles
				/* Insertar la region en la lista de regiones disponibles */
				push_front_memreg_header(heap->free, new_header);
			}
		}
	}

	/* Insertar la region asignada en la lista de regiones usadas */
	//push_front_memreg_header(heap->used, candidate);

	return (void *)(candidate->base);

}
Пример #6
0
static void *heap_malloc(UINT size, UCHAR page_align, heap *aheap)
{
	UINT newsize = size + sizeof(mm_header) + sizeof(mm_footer);
	UINT hole_pos = find_smallest_hole(newsize, page_align, aheap), oldsize, oldpos, newpos, oldend;
	mm_header *header, *newheader;
	mm_footer *newfooter;

	if ((!size) || (!aheap)) return 0;
	if (hole_pos == MM_NO_HOLE) {
		oldsize = aheap->end - aheap->start;
		oldend = aheap->end;
		expand_heap(oldsize + newsize, aheap);
		newsize = aheap->end - aheap->start;
		UINT idx = MM_NO_HOLE;
		UINT value = 0;
		for (hole_pos = 0; hole_pos < aheap->entrycount; hole_pos++) {
			UINT tmp = (UINT) aheap->entries[hole_pos];
			if (tmp > value) {
				value = tmp;
				idx = hole_pos;
			}
		}
		if (idx == MM_NO_HOLE) {
			header = (mm_header *)oldend;
			header->size = newsize - oldsize;
			header->flag = MM_FLAG_HOLE;
			newfooter = (mm_footer *) (oldend + header->size - sizeof(mm_footer));
			header->magic = newfooter->magic = MM_MAGIC;
			newfooter->header = header;
			heap_add_entry(header, aheap);
		} else  {
			header = aheap->entries[idx];
			header->size += newsize - oldsize;
			newfooter = (mm_footer *) ((UINT)header + header->size - sizeof(mm_footer));
			newfooter->header = header;
			newfooter->magic = MM_MAGIC;
		}
		return heap_malloc(size, page_align, aheap);
	}
	header = aheap->entries[hole_pos];
	if (header->size - sizeof(mm_header) - sizeof(mm_footer) < newsize) {
		size += header->size - newsize;
		newsize = header->size;
	}
	oldpos = (UINT)header;
	oldsize = header->size;
	if (page_align && (oldpos & 0xFFFFF000)) {
		newpos = oldpos + FRAME_SIZE - (oldpos & 0xFFF) - sizeof(mm_header);
		newheader = (mm_header *) oldpos;
		newfooter = (mm_footer *) ((UINT)newpos - sizeof(mm_footer));
		newheader->size = newpos - oldpos;
		newheader->flag = MM_FLAG_HOLE;
		newheader->magic = newfooter->magic = MM_MAGIC;
		newfooter->header = newheader;
		oldpos = newpos;
		oldsize = oldsize - newheader->size;
	} else  {
		heap_del_entry(hole_pos, aheap);
	}
	header = (mm_header *) oldpos;
	newfooter = (mm_footer *) (oldpos + sizeof(mm_header) + size);
	header->flag = MM_FLAG_BLOCK;
	header->size = newsize;
	header->magic = newfooter->magic = MM_MAGIC;
	newfooter->header = header;
	if (oldsize - newsize > 0) {
		newheader = (mm_header *) (oldpos + newsize);
		newheader->magic = MM_MAGIC;
		newheader->flag = MM_FLAG_HOLE;
		newheader->size = oldsize - newsize;
		newfooter = (mm_footer *) ((UINT)newheader + newheader->size - sizeof(mm_footer));
		if ((UINT)newfooter < aheap->end)  {
			newfooter->magic = MM_MAGIC;
			newfooter->header = newheader;
		}
		heap_add_entry(newheader, aheap);
	}
	return (void *) ((UINT)header + sizeof(mm_header));
}
Пример #7
0
static void* do_alloc(size_t i)
{
	node_t* pn = heap->index[i];
	node_t* prev = NULL;

	while (pn)
	{
		if (pn->stat == MEM_STAT_FREE)
		{
			if (prev)
			{
				void* ret = pn->addr;
				node_t* newNode = get_free_node();
				prev->next = newNode;
				newNode->addr = ret;
				newNode->stat = MEM_STAT_USED;
				newNode->len = indsiz[i];
				newNode->next = pn;
				pn->addr = (void*)((size_t)pn->addr + indsiz[i]);
				pn->len -= indsiz[i];
				if (pn->len == 0)
				{
					newNode->next = pn->next;
					pn->next = heap->free_node;
					heap->free_node = pn;
					merge(prev);
				}
				return ret;
			}
			else
			{
				node_t* tmp = get_free_node();
				tmp->addr = pn->addr;
				tmp->len = indsiz[i];
				tmp->next = pn;
				tmp->stat = MEM_STAT_USED;
				pn->addr = (void*)((size_t)pn->addr + indsiz[i]);
				pn->len -= indsiz[i];
				heap->index[i] = tmp;
				if (pn->len == 0)
				{
					tmp->next = pn->next;
					pn->next = heap->free_node;
					heap->free_node = pn;
					merge(tmp);
				}
				return tmp->addr;
			}
		}
		else if (pn->next)
		{
			prev = pn;
			pn = pn->next;
		}
		else
		{
			expand_heap(i);
			return do_alloc(i);
		}
	}
	expand_heap(i);
	return do_alloc(i);
}