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