1*d6b92ffaSHans Petter Selasky /* 2*d6b92ffaSHans Petter Selasky * Copyright (c) 2011 Intel Corporation. All rights reserved. 3*d6b92ffaSHans Petter Selasky * 4*d6b92ffaSHans Petter Selasky * This software is available to you under a choice of one of two 5*d6b92ffaSHans Petter Selasky * licenses. You may choose to be licensed under the terms of the GNU 6*d6b92ffaSHans Petter Selasky * General Public License (GPL) Version 2, available from the file 7*d6b92ffaSHans Petter Selasky * COPYING in the main directory of this source tree, or the 8*d6b92ffaSHans Petter Selasky * OpenIB.org BSD license below: 9*d6b92ffaSHans Petter Selasky * 10*d6b92ffaSHans Petter Selasky * Redistribution and use in source and binary forms, with or 11*d6b92ffaSHans Petter Selasky * without modification, are permitted provided that the following 12*d6b92ffaSHans Petter Selasky * conditions are met: 13*d6b92ffaSHans Petter Selasky * 14*d6b92ffaSHans Petter Selasky * - Redistributions of source code must retain the above 15*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following 16*d6b92ffaSHans Petter Selasky * disclaimer. 17*d6b92ffaSHans Petter Selasky * 18*d6b92ffaSHans Petter Selasky * - Redistributions in binary form must reproduce the above 19*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following 20*d6b92ffaSHans Petter Selasky * disclaimer in the documentation and/or other materials 21*d6b92ffaSHans Petter Selasky * provided with the distribution. 22*d6b92ffaSHans Petter Selasky * 23*d6b92ffaSHans Petter Selasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24*d6b92ffaSHans Petter Selasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25*d6b92ffaSHans Petter Selasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26*d6b92ffaSHans Petter Selasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27*d6b92ffaSHans Petter Selasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28*d6b92ffaSHans Petter Selasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29*d6b92ffaSHans Petter Selasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30*d6b92ffaSHans Petter Selasky * SOFTWARE. 31*d6b92ffaSHans Petter Selasky * 32*d6b92ffaSHans Petter Selasky */ 33*d6b92ffaSHans Petter Selasky 34*d6b92ffaSHans Petter Selasky #include <config.h> 35*d6b92ffaSHans Petter Selasky 36*d6b92ffaSHans Petter Selasky #include <errno.h> 37*d6b92ffaSHans Petter Selasky #include <sys/types.h> 38*d6b92ffaSHans Petter Selasky #include <stdlib.h> 39*d6b92ffaSHans Petter Selasky 40*d6b92ffaSHans Petter Selasky #include "indexer.h" 41*d6b92ffaSHans Petter Selasky 42*d6b92ffaSHans Petter Selasky /* 43*d6b92ffaSHans Petter Selasky * Indexer - to find a structure given an index 44*d6b92ffaSHans Petter Selasky * 45*d6b92ffaSHans Petter Selasky * We store pointers using a double lookup and return an index to the 46*d6b92ffaSHans Petter Selasky * user which is then used to retrieve the pointer. The upper bits of 47*d6b92ffaSHans Petter Selasky * the index are itself an index into an array of memory allocations. 48*d6b92ffaSHans Petter Selasky * The lower bits specify the offset into the allocated memory where 49*d6b92ffaSHans Petter Selasky * the pointer is stored. 50*d6b92ffaSHans Petter Selasky * 51*d6b92ffaSHans Petter Selasky * This allows us to adjust the number of pointers stored by the index 52*d6b92ffaSHans Petter Selasky * list without taking a lock during data lookups. 53*d6b92ffaSHans Petter Selasky */ 54*d6b92ffaSHans Petter Selasky 55*d6b92ffaSHans Petter Selasky static int idx_grow(struct indexer *idx) 56*d6b92ffaSHans Petter Selasky { 57*d6b92ffaSHans Petter Selasky union idx_entry *entry; 58*d6b92ffaSHans Petter Selasky int i, start_index; 59*d6b92ffaSHans Petter Selasky 60*d6b92ffaSHans Petter Selasky if (idx->size >= IDX_ARRAY_SIZE) 61*d6b92ffaSHans Petter Selasky goto nomem; 62*d6b92ffaSHans Petter Selasky 63*d6b92ffaSHans Petter Selasky idx->array[idx->size] = calloc(IDX_ENTRY_SIZE, sizeof(union idx_entry)); 64*d6b92ffaSHans Petter Selasky if (!idx->array[idx->size]) 65*d6b92ffaSHans Petter Selasky goto nomem; 66*d6b92ffaSHans Petter Selasky 67*d6b92ffaSHans Petter Selasky entry = idx->array[idx->size]; 68*d6b92ffaSHans Petter Selasky start_index = idx->size << IDX_ENTRY_BITS; 69*d6b92ffaSHans Petter Selasky entry[IDX_ENTRY_SIZE - 1].next = idx->free_list; 70*d6b92ffaSHans Petter Selasky 71*d6b92ffaSHans Petter Selasky for (i = IDX_ENTRY_SIZE - 2; i >= 0; i--) 72*d6b92ffaSHans Petter Selasky entry[i].next = start_index + i + 1; 73*d6b92ffaSHans Petter Selasky 74*d6b92ffaSHans Petter Selasky /* Index 0 is reserved */ 75*d6b92ffaSHans Petter Selasky if (start_index == 0) 76*d6b92ffaSHans Petter Selasky start_index++; 77*d6b92ffaSHans Petter Selasky idx->free_list = start_index; 78*d6b92ffaSHans Petter Selasky idx->size++; 79*d6b92ffaSHans Petter Selasky return start_index; 80*d6b92ffaSHans Petter Selasky 81*d6b92ffaSHans Petter Selasky nomem: 82*d6b92ffaSHans Petter Selasky errno = ENOMEM; 83*d6b92ffaSHans Petter Selasky return -1; 84*d6b92ffaSHans Petter Selasky } 85*d6b92ffaSHans Petter Selasky 86*d6b92ffaSHans Petter Selasky int idx_insert(struct indexer *idx, void *item) 87*d6b92ffaSHans Petter Selasky { 88*d6b92ffaSHans Petter Selasky union idx_entry *entry; 89*d6b92ffaSHans Petter Selasky int index; 90*d6b92ffaSHans Petter Selasky 91*d6b92ffaSHans Petter Selasky if ((index = idx->free_list) == 0) { 92*d6b92ffaSHans Petter Selasky if ((index = idx_grow(idx)) <= 0) 93*d6b92ffaSHans Petter Selasky return index; 94*d6b92ffaSHans Petter Selasky } 95*d6b92ffaSHans Petter Selasky 96*d6b92ffaSHans Petter Selasky entry = idx->array[idx_array_index(index)]; 97*d6b92ffaSHans Petter Selasky idx->free_list = entry[idx_entry_index(index)].next; 98*d6b92ffaSHans Petter Selasky entry[idx_entry_index(index)].item = item; 99*d6b92ffaSHans Petter Selasky return index; 100*d6b92ffaSHans Petter Selasky } 101*d6b92ffaSHans Petter Selasky 102*d6b92ffaSHans Petter Selasky void *idx_remove(struct indexer *idx, int index) 103*d6b92ffaSHans Petter Selasky { 104*d6b92ffaSHans Petter Selasky union idx_entry *entry; 105*d6b92ffaSHans Petter Selasky void *item; 106*d6b92ffaSHans Petter Selasky 107*d6b92ffaSHans Petter Selasky entry = idx->array[idx_array_index(index)]; 108*d6b92ffaSHans Petter Selasky item = entry[idx_entry_index(index)].item; 109*d6b92ffaSHans Petter Selasky entry[idx_entry_index(index)].next = idx->free_list; 110*d6b92ffaSHans Petter Selasky idx->free_list = index; 111*d6b92ffaSHans Petter Selasky return item; 112*d6b92ffaSHans Petter Selasky } 113*d6b92ffaSHans Petter Selasky 114*d6b92ffaSHans Petter Selasky void idx_replace(struct indexer *idx, int index, void *item) 115*d6b92ffaSHans Petter Selasky { 116*d6b92ffaSHans Petter Selasky union idx_entry *entry; 117*d6b92ffaSHans Petter Selasky 118*d6b92ffaSHans Petter Selasky entry = idx->array[idx_array_index(index)]; 119*d6b92ffaSHans Petter Selasky entry[idx_entry_index(index)].item = item; 120*d6b92ffaSHans Petter Selasky } 121*d6b92ffaSHans Petter Selasky 122*d6b92ffaSHans Petter Selasky 123*d6b92ffaSHans Petter Selasky static int idm_grow(struct index_map *idm, int index) 124*d6b92ffaSHans Petter Selasky { 125*d6b92ffaSHans Petter Selasky idm->array[idx_array_index(index)] = calloc(IDX_ENTRY_SIZE, sizeof(void *)); 126*d6b92ffaSHans Petter Selasky if (!idm->array[idx_array_index(index)]) 127*d6b92ffaSHans Petter Selasky goto nomem; 128*d6b92ffaSHans Petter Selasky 129*d6b92ffaSHans Petter Selasky return index; 130*d6b92ffaSHans Petter Selasky 131*d6b92ffaSHans Petter Selasky nomem: 132*d6b92ffaSHans Petter Selasky errno = ENOMEM; 133*d6b92ffaSHans Petter Selasky return -1; 134*d6b92ffaSHans Petter Selasky } 135*d6b92ffaSHans Petter Selasky 136*d6b92ffaSHans Petter Selasky int idm_set(struct index_map *idm, int index, void *item) 137*d6b92ffaSHans Petter Selasky { 138*d6b92ffaSHans Petter Selasky void **entry; 139*d6b92ffaSHans Petter Selasky 140*d6b92ffaSHans Petter Selasky if (index > IDX_MAX_INDEX) { 141*d6b92ffaSHans Petter Selasky errno = ENOMEM; 142*d6b92ffaSHans Petter Selasky return -1; 143*d6b92ffaSHans Petter Selasky } 144*d6b92ffaSHans Petter Selasky 145*d6b92ffaSHans Petter Selasky if (!idm->array[idx_array_index(index)]) { 146*d6b92ffaSHans Petter Selasky if (idm_grow(idm, index) < 0) 147*d6b92ffaSHans Petter Selasky return -1; 148*d6b92ffaSHans Petter Selasky } 149*d6b92ffaSHans Petter Selasky 150*d6b92ffaSHans Petter Selasky entry = idm->array[idx_array_index(index)]; 151*d6b92ffaSHans Petter Selasky entry[idx_entry_index(index)] = item; 152*d6b92ffaSHans Petter Selasky return index; 153*d6b92ffaSHans Petter Selasky } 154*d6b92ffaSHans Petter Selasky 155*d6b92ffaSHans Petter Selasky void *idm_clear(struct index_map *idm, int index) 156*d6b92ffaSHans Petter Selasky { 157*d6b92ffaSHans Petter Selasky void **entry; 158*d6b92ffaSHans Petter Selasky void *item; 159*d6b92ffaSHans Petter Selasky 160*d6b92ffaSHans Petter Selasky entry = idm->array[idx_array_index(index)]; 161*d6b92ffaSHans Petter Selasky item = entry[idx_entry_index(index)]; 162*d6b92ffaSHans Petter Selasky entry[idx_entry_index(index)] = NULL; 163*d6b92ffaSHans Petter Selasky return item; 164*d6b92ffaSHans Petter Selasky } 165