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