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++; }
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); }
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); }
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); }
/** * @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); }
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)); }
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); }