Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}