Commit | Line | Data |
---|---|---|
b484b26c GZ |
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 | } |