1685a6bf8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2b484b26cSGeorge Zhang /* 3b484b26cSGeorge Zhang * VMware VMCI Driver 4b484b26cSGeorge Zhang * 5b484b26cSGeorge Zhang * Copyright (C) 2012 VMware, Inc. All rights reserved. 6b484b26cSGeorge Zhang */ 7b484b26cSGeorge Zhang 8b484b26cSGeorge Zhang #include <linux/slab.h> 9b484b26cSGeorge Zhang #include "vmci_handle_array.h" 10b484b26cSGeorge Zhang 11b484b26cSGeorge Zhang static size_t handle_arr_calc_size(size_t capacity) 12b484b26cSGeorge Zhang { 13b484b26cSGeorge Zhang return sizeof(struct vmci_handle_arr) + 14b484b26cSGeorge Zhang capacity * sizeof(struct vmci_handle); 15b484b26cSGeorge Zhang } 16b484b26cSGeorge Zhang 17b484b26cSGeorge Zhang struct vmci_handle_arr *vmci_handle_arr_create(size_t capacity) 18b484b26cSGeorge Zhang { 19b484b26cSGeorge Zhang struct vmci_handle_arr *array; 20b484b26cSGeorge Zhang 21b484b26cSGeorge Zhang if (capacity == 0) 22b484b26cSGeorge Zhang capacity = VMCI_HANDLE_ARRAY_DEFAULT_SIZE; 23b484b26cSGeorge Zhang 24b484b26cSGeorge Zhang array = kmalloc(handle_arr_calc_size(capacity), GFP_ATOMIC); 25b484b26cSGeorge Zhang if (!array) 26b484b26cSGeorge Zhang return NULL; 27b484b26cSGeorge Zhang 28b484b26cSGeorge Zhang array->capacity = capacity; 29b484b26cSGeorge Zhang array->size = 0; 30b484b26cSGeorge Zhang 31b484b26cSGeorge Zhang return array; 32b484b26cSGeorge Zhang } 33b484b26cSGeorge Zhang 34b484b26cSGeorge Zhang void vmci_handle_arr_destroy(struct vmci_handle_arr *array) 35b484b26cSGeorge Zhang { 36b484b26cSGeorge Zhang kfree(array); 37b484b26cSGeorge Zhang } 38b484b26cSGeorge Zhang 39b484b26cSGeorge Zhang void vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr, 40b484b26cSGeorge Zhang struct vmci_handle handle) 41b484b26cSGeorge Zhang { 42b484b26cSGeorge Zhang struct vmci_handle_arr *array = *array_ptr; 43b484b26cSGeorge Zhang 44b484b26cSGeorge Zhang if (unlikely(array->size >= array->capacity)) { 45b484b26cSGeorge Zhang /* reallocate. */ 46b484b26cSGeorge Zhang struct vmci_handle_arr *new_array; 47b484b26cSGeorge Zhang size_t new_capacity = array->capacity * VMCI_ARR_CAP_MULT; 48b484b26cSGeorge Zhang size_t new_size = handle_arr_calc_size(new_capacity); 49b484b26cSGeorge Zhang 50b484b26cSGeorge Zhang new_array = krealloc(array, new_size, GFP_ATOMIC); 51b484b26cSGeorge Zhang if (!new_array) 52b484b26cSGeorge Zhang return; 53b484b26cSGeorge Zhang 54b484b26cSGeorge Zhang new_array->capacity = new_capacity; 55b484b26cSGeorge Zhang *array_ptr = array = new_array; 56b484b26cSGeorge Zhang } 57b484b26cSGeorge Zhang 58b484b26cSGeorge Zhang array->entries[array->size] = handle; 59b484b26cSGeorge Zhang array->size++; 60b484b26cSGeorge Zhang } 61b484b26cSGeorge Zhang 62b484b26cSGeorge Zhang /* 63b484b26cSGeorge Zhang * Handle that was removed, VMCI_INVALID_HANDLE if entry not found. 64b484b26cSGeorge Zhang */ 65b484b26cSGeorge Zhang struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array, 66b484b26cSGeorge Zhang struct vmci_handle entry_handle) 67b484b26cSGeorge Zhang { 68b484b26cSGeorge Zhang struct vmci_handle handle = VMCI_INVALID_HANDLE; 69b484b26cSGeorge Zhang size_t i; 70b484b26cSGeorge Zhang 71b484b26cSGeorge Zhang for (i = 0; i < array->size; i++) { 72b484b26cSGeorge Zhang if (vmci_handle_is_equal(array->entries[i], entry_handle)) { 73b484b26cSGeorge Zhang handle = array->entries[i]; 74b484b26cSGeorge Zhang array->size--; 75b484b26cSGeorge Zhang array->entries[i] = array->entries[array->size]; 76b484b26cSGeorge Zhang array->entries[array->size] = VMCI_INVALID_HANDLE; 77b484b26cSGeorge Zhang break; 78b484b26cSGeorge Zhang } 79b484b26cSGeorge Zhang } 80b484b26cSGeorge Zhang 81b484b26cSGeorge Zhang return handle; 82b484b26cSGeorge Zhang } 83b484b26cSGeorge Zhang 84b484b26cSGeorge Zhang /* 85b484b26cSGeorge Zhang * Handle that was removed, VMCI_INVALID_HANDLE if array was empty. 86b484b26cSGeorge Zhang */ 87b484b26cSGeorge Zhang struct vmci_handle vmci_handle_arr_remove_tail(struct vmci_handle_arr *array) 88b484b26cSGeorge Zhang { 89b484b26cSGeorge Zhang struct vmci_handle handle = VMCI_INVALID_HANDLE; 90b484b26cSGeorge Zhang 91b484b26cSGeorge Zhang if (array->size) { 92b484b26cSGeorge Zhang array->size--; 93b484b26cSGeorge Zhang handle = array->entries[array->size]; 94b484b26cSGeorge Zhang array->entries[array->size] = VMCI_INVALID_HANDLE; 95b484b26cSGeorge Zhang } 96b484b26cSGeorge Zhang 97b484b26cSGeorge Zhang return handle; 98b484b26cSGeorge Zhang } 99b484b26cSGeorge Zhang 100b484b26cSGeorge Zhang /* 101b484b26cSGeorge Zhang * Handle at given index, VMCI_INVALID_HANDLE if invalid index. 102b484b26cSGeorge Zhang */ 103b484b26cSGeorge Zhang struct vmci_handle 104b484b26cSGeorge Zhang vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, size_t index) 105b484b26cSGeorge Zhang { 106b484b26cSGeorge Zhang if (unlikely(index >= array->size)) 107b484b26cSGeorge Zhang return VMCI_INVALID_HANDLE; 108b484b26cSGeorge Zhang 109b484b26cSGeorge Zhang return array->entries[index]; 110b484b26cSGeorge Zhang } 111b484b26cSGeorge Zhang 112b484b26cSGeorge Zhang bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array, 113b484b26cSGeorge Zhang struct vmci_handle entry_handle) 114b484b26cSGeorge Zhang { 115b484b26cSGeorge Zhang size_t i; 116b484b26cSGeorge Zhang 117b484b26cSGeorge Zhang for (i = 0; i < array->size; i++) 118b484b26cSGeorge Zhang if (vmci_handle_is_equal(array->entries[i], entry_handle)) 119b484b26cSGeorge Zhang return true; 120b484b26cSGeorge Zhang 121b484b26cSGeorge Zhang return false; 122b484b26cSGeorge Zhang } 123b484b26cSGeorge Zhang 124b484b26cSGeorge Zhang /* 125b484b26cSGeorge Zhang * NULL if the array is empty. Otherwise, a pointer to the array 126b484b26cSGeorge Zhang * of VMCI handles in the handle array. 127b484b26cSGeorge Zhang */ 128b484b26cSGeorge Zhang struct vmci_handle *vmci_handle_arr_get_handles(struct vmci_handle_arr *array) 129b484b26cSGeorge Zhang { 130b484b26cSGeorge Zhang if (array->size) 131b484b26cSGeorge Zhang return array->entries; 132b484b26cSGeorge Zhang 133b484b26cSGeorge Zhang return NULL; 134b484b26cSGeorge Zhang } 135