1 /* 2 * VMware VMCI Driver 3 * 4 * Copyright (C) 2012 VMware, Inc. All rights reserved. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation version 2 and no later version. 9 * 10 * This program is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * for more details. 14 */ 15 16 #include <linux/slab.h> 17 #include "vmci_handle_array.h" 18 19 static size_t handle_arr_calc_size(size_t capacity) 20 { 21 return sizeof(struct vmci_handle_arr) + 22 capacity * sizeof(struct vmci_handle); 23 } 24 25 struct vmci_handle_arr *vmci_handle_arr_create(size_t capacity) 26 { 27 struct vmci_handle_arr *array; 28 29 if (capacity == 0) 30 capacity = VMCI_HANDLE_ARRAY_DEFAULT_SIZE; 31 32 array = kmalloc(handle_arr_calc_size(capacity), GFP_ATOMIC); 33 if (!array) 34 return NULL; 35 36 array->capacity = capacity; 37 array->size = 0; 38 39 return array; 40 } 41 42 void vmci_handle_arr_destroy(struct vmci_handle_arr *array) 43 { 44 kfree(array); 45 } 46 47 void vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr, 48 struct vmci_handle handle) 49 { 50 struct vmci_handle_arr *array = *array_ptr; 51 52 if (unlikely(array->size >= array->capacity)) { 53 /* reallocate. */ 54 struct vmci_handle_arr *new_array; 55 size_t new_capacity = array->capacity * VMCI_ARR_CAP_MULT; 56 size_t new_size = handle_arr_calc_size(new_capacity); 57 58 new_array = krealloc(array, new_size, GFP_ATOMIC); 59 if (!new_array) 60 return; 61 62 new_array->capacity = new_capacity; 63 *array_ptr = array = new_array; 64 } 65 66 array->entries[array->size] = handle; 67 array->size++; 68 } 69 70 /* 71 * Handle that was removed, VMCI_INVALID_HANDLE if entry not found. 72 */ 73 struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array, 74 struct vmci_handle entry_handle) 75 { 76 struct vmci_handle handle = VMCI_INVALID_HANDLE; 77 size_t i; 78 79 for (i = 0; i < array->size; i++) { 80 if (vmci_handle_is_equal(array->entries[i], entry_handle)) { 81 handle = array->entries[i]; 82 array->size--; 83 array->entries[i] = array->entries[array->size]; 84 array->entries[array->size] = VMCI_INVALID_HANDLE; 85 break; 86 } 87 } 88 89 return handle; 90 } 91 92 /* 93 * Handle that was removed, VMCI_INVALID_HANDLE if array was empty. 94 */ 95 struct vmci_handle vmci_handle_arr_remove_tail(struct vmci_handle_arr *array) 96 { 97 struct vmci_handle handle = VMCI_INVALID_HANDLE; 98 99 if (array->size) { 100 array->size--; 101 handle = array->entries[array->size]; 102 array->entries[array->size] = VMCI_INVALID_HANDLE; 103 } 104 105 return handle; 106 } 107 108 /* 109 * Handle at given index, VMCI_INVALID_HANDLE if invalid index. 110 */ 111 struct vmci_handle 112 vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, size_t index) 113 { 114 if (unlikely(index >= array->size)) 115 return VMCI_INVALID_HANDLE; 116 117 return array->entries[index]; 118 } 119 120 bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array, 121 struct vmci_handle entry_handle) 122 { 123 size_t i; 124 125 for (i = 0; i < array->size; i++) 126 if (vmci_handle_is_equal(array->entries[i], entry_handle)) 127 return true; 128 129 return false; 130 } 131 132 /* 133 * NULL if the array is empty. Otherwise, a pointer to the array 134 * of VMCI handles in the handle array. 135 */ 136 struct vmci_handle *vmci_handle_arr_get_handles(struct vmci_handle_arr *array) 137 { 138 if (array->size) 139 return array->entries; 140 141 return NULL; 142 } 143