static int getmaxarray(void *base, G2DESC *rd) { void* vp = ((Vb_ATTLC*)base)->beginning(); int nel = ((Vb_ATTLC*)base)->size(); G2DESC* element = rd->child; int incr_size; if (element->type != 'L') { incr_size = element->size; } else { if (element->size == 0) { incr_size = element->nel; } else { incr_size = REALSIZE(element->size); } } int i = 0; int max_defined = -1; for (; --nel >= 0; vp = (char*)vp + incr_size) { if (!isnull_general(vp, element)) { // os << i << " "; if (i > max_defined) { max_defined = i; } } i++; } return (max_defined + 1); }
/* malloc function. Initializes the first page if needed, then returns the appropriate allocated space. */ void* kma_malloc(kma_size_t size) { if (REALSIZE(size)+sizeof(pageheaderT) > PAGESIZE) return NULL; if (first_page == NULL) { first_page = init_page(); kma_malloc(sizeof(pageheaderT)); // mallocs the page header so it isn't overwritten. PAGE_HEADER(first_page)->used = 0; // resets the allocation counter because the page // header doesn't count. } return get_free_buffer(size); }
static void malloc_dump1(int fd, struct dir_info *d) { char buf[64]; size_t i, realsize; snprintf(buf, sizeof(buf), "Malloc dir of %s at %p\n", __progname, d); write(fd, buf, strlen(buf)); snprintf(buf, sizeof(buf), "Regions slots %zu\n", d->regions_total); write(fd, buf, strlen(buf)); snprintf(buf, sizeof(buf), "Finds %zu/%zu %f\n", d->finds, d->find_collisions, 1.0 + (double)d->find_collisions / d->finds); write(fd, buf, strlen(buf)); snprintf(buf, sizeof(buf), "Inserts %zu/%zu %f\n", d->inserts, d->insert_collisions, 1.0 + (double)d->insert_collisions / d->inserts); write(fd, buf, strlen(buf)); snprintf(buf, sizeof(buf), "Deletes %zu/%zu\n", d->deletes, d->delete_moves); write(fd, buf, strlen(buf)); snprintf(buf, sizeof(buf), "Regions slots free %zu\n", d->regions_free); write(fd, buf, strlen(buf)); for (i = 0; i < d->regions_total; i++) { if (d->r[i].p != NULL) { size_t h = hash(d->r[i].p) & (d->regions_total - 1); snprintf(buf, sizeof(buf), "%4zx) #%zx %zd ", i, h, h - i); write(fd, buf, strlen(buf)); REALSIZE(realsize, &d->r[i]); if (realsize > MALLOC_MAXCHUNK) { snprintf(buf, sizeof(buf), "%p: %zu\n", d->r[i].p, realsize); write(fd, buf, strlen(buf)); } else dump_chunk(fd, (struct chunk_info *)d->r[i].size, 0); } } dump_free_chunk_info(fd, d); dump_free_page_info(fd, d); snprintf(buf, sizeof(buf), "In use %zu\n", malloc_used); write(fd, buf, strlen(buf)); snprintf(buf, sizeof(buf), "Guarded %zu\n", malloc_guarded); write(fd, buf, strlen(buf)); }
/* Searches all of the free buffers across all pages for one that properly fits the requested size (adjusted for alloc header). This searches all pages for given buffer size before moving on to the bigger size, splitting the larger buffer down if necessary. If none of the pages can fit the requested size, a new page is allocated and a page header created and allocated. In the special case of the buffer request being > PAGESIZE/2 a new page is always allocated. */ void* get_free_buffer(int size) { pageheaderT* page_header = PAGE_HEADER(first_page); pageheaderT* prev_page = NULL; int i = 0; int search_size = round_up(REALSIZE(size)); allocheaderT* to_be_allocated; freelistL* buffer_size = get_required_buffer(search_size, page_header); // Loops through each buffer size while (search_size <= PAGESIZE) { // Loops through each page until it goes through all of them or // finds a free buffer. while (page_header != NULL && buffer_size->first_block == NULL) { prev_page = page_header; page_header = page_header->next; buffer_size = get_required_buffer(search_size, page_header); } // None found, increase size and repeat if (buffer_size == NULL) { i++; page_header = PAGE_HEADER(first_page); prev_page = NULL; search_size = search_size * 2; buffer_size = get_required_buffer(search_size, page_header); } // Found. Splits depending on the number of times through the loop, // removes the buffer from the free list, and returns it. else { to_be_allocated = buffer_size->first_block; if (i == 0) { buffer_size->first_block = to_be_allocated->next; } else { for(; i > 0; i--) { buffer_size = split_buffer(buffer_size, page_header); } to_be_allocated = buffer_size->first_block; buffer_size->first_block = to_be_allocated->next; } page_header->used += 1; return to_be_allocated; } } // No buffers found. Find the last page again. while (page_header != NULL) { prev_page = page_header; page_header = page_header->next; } // Create a new page, split it up to insert the header. kma_page_t* new_page = init_page(); page_header = PAGE_HEADER(new_page); prev_page->next = page_header; buffer_size = get_required_buffer(sizeof(pageheaderT), page_header); to_be_allocated = buffer_size->first_block; i = 0; while (buffer_size != NULL && buffer_size->first_block == NULL) { buffer_size = buffer_size->bigger_size; i++; } for(; i > 0; i--) { buffer_size = split_buffer(buffer_size, page_header); } to_be_allocated = buffer_size->first_block; buffer_size->first_block = to_be_allocated->next; // If size > PAGESIZE/2, clears free headers and allocates the // whole page. if (round_up(REALSIZE(size)) == PAGESIZE) { page_header->free_headers.buffer32.first_block = NULL; page_header->free_headers.buffer64.first_block = NULL; page_header->free_headers.buffer128.first_block = NULL; page_header->free_headers.buffer256.first_block = NULL; page_header->free_headers.buffer512.first_block = NULL; page_header->free_headers.buffer1024.first_block = NULL; page_header->free_headers.buffer2048.first_block = NULL; page_header->free_headers.buffer4096.first_block = NULL; page_header->free_headers.buffer8192.first_block = NULL; page_header->used += 1; return (void*)((long int) page_header + sizeof(pageheaderT)); } // Now that the page has been created, try allocating again. return get_free_buffer(size); }
static int isnull_general(void *base, G2DESC *rd) { int retval = 1; switch (rd->type) { case 'L': retval = isnull_leaf(base, rd); break; case 'S': { G2DESC *child = rd->child; int nel = rd->nel; for (; --nel >= 0; child++) { if (child->type != 'L') { void *vp; vp = (char*)base + child->offset; if (isnull_general(vp, child) == 0) { retval = 0; break; } } else { void *vp = ((char*)base + child->offset); if (!isnull_leaf(vp, child)) { retval = 0; break; } } } break; } case 'A': { void* vp = ((Vb_ATTLC*)base)->beginning(); int nel = ((Vb_ATTLC*)base)->size(); G2DESC* element = rd->child; if (element->type != 'L') { int i = 0; for (; --nel >= 0; vp = (char*)vp + element->size) { if (i >= rd->nel && rd->nel > 0) { break; } if (!isnull_general(vp, element)) { retval = 0; break; } } } else { int i = 0; for (; --nel >= 0; vp = ((char*)vp + REALSIZE(element->size)),i++) { if (i >= rd->nel && rd->nel > 0) { break; } if (!isnull_leaf(vp, element)) { retval = 0; break; } if (element->size == 0) { vp = (char*)vp + element->nel; } } } } } /* end switch */ return (retval); }