struct vr_btable * vr_btable_alloc(unsigned int num_entries, unsigned int entry_size) { unsigned int i = 0, num_parts, remainder; unsigned int total_parts; uint64_t total_mem; struct vr_btable *table; unsigned int offset = 0; total_mem = num_entries * entry_size; num_parts = total_mem / VR_SINGLE_ALLOC_LIMIT; remainder = total_mem % VR_SINGLE_ALLOC_LIMIT; total_parts = num_parts; /* * anything left over that is not a multiple of VR_SINGLE_ALLOC_LIMIT * gets accomodated in the remainder, and hence an extra partition has * to be given */ if (remainder) total_parts++; if (num_parts) { /* * the entry size has to be a factor of VR_SINGLE_ALLOC limit. * otherwise, we might access memory beyond the allocated chunk * while accessing the last entry */ if (VR_SINGLE_ALLOC_LIMIT % entry_size) return NULL; } if (!total_parts) return NULL; table = vr_zalloc(sizeof(*table)); if (!table) return NULL; table->vb_mem = vr_zalloc(total_parts * sizeof(void *)); table->vb_table_info = vr_zalloc(total_parts * sizeof(struct vr_btable_partition)); if (!table->vb_mem || !table->vb_table_info) goto exit_alloc; if (num_parts) { for (i = 0; i < num_parts; i++) { table->vb_mem[i] = vr_page_alloc(VR_SINGLE_ALLOC_LIMIT); if (!table->vb_mem[i]) goto exit_alloc; table->vb_table_info[i].vb_mem_size = VR_SINGLE_ALLOC_LIMIT; table->vb_table_info[i].vb_offset = offset; offset += table->vb_table_info[i].vb_mem_size; table->vb_partitions++; } } if (remainder) { table->vb_mem[i] = vr_page_alloc(remainder); if (!table->vb_mem[i]) goto exit_alloc; table->vb_table_info[i].vb_mem_size = remainder; table->vb_table_info[i].vb_offset = offset; table->vb_partitions++; } table->vb_entries = num_entries; table->vb_esize = entry_size; return table; exit_alloc: vr_btable_free(table); return NULL; }
struct vr_btable * vr_btable_alloc(unsigned int num_entries, unsigned int entry_size) { unsigned int i = 0, num_parts, remainder; uint64_t total_mem; struct vr_btable *table; unsigned int offset = 0; total_mem = num_entries * entry_size; /* need more testing. that's all */ if (total_mem > VR_KNOWN_BIG_MEM_LIMIT) return NULL; table = vr_zalloc(sizeof(*table)); if (!table) return NULL; num_parts = total_mem / VR_SINGLE_ALLOC_LIMIT; remainder = total_mem % VR_SINGLE_ALLOC_LIMIT; if (num_parts + !!remainder > VR_MAX_BTABLE_ENTRIES) return NULL; if (num_parts) { /* * the entry size has to be a factor of VR_SINGLE_ALLOC limit. * otherwise, we might access memory beyond the allocated chunk * while accessing the last entry */ if (VR_SINGLE_ALLOC_LIMIT % entry_size) return NULL; } if (num_parts) { for (i = 0; i < num_parts; i++) { table->vb_mem[i] = vr_page_alloc(VR_SINGLE_ALLOC_LIMIT); if (!table->vb_mem[i]) goto exit_alloc; table->vb_table_info[i].vb_mem_size = VR_SINGLE_ALLOC_LIMIT; table->vb_table_info[i].vb_offset = offset; offset += table->vb_table_info[i].vb_mem_size; } table->vb_partitions = num_parts; } if (remainder) { table->vb_mem[i] = vr_page_alloc(remainder); if (!table->vb_mem[i]) goto exit_alloc; table->vb_table_info[i].vb_mem_size = remainder; table->vb_table_info[i].vb_offset = offset; table->vb_partitions++; } table->vb_entries = num_entries; table->vb_esize = entry_size; return table; exit_alloc: vr_btable_free(table); return NULL; }