Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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}