4 * Copyright (C) 2012 VMware, Inc. All rights reserved.
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.
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
16 #include <linux/slab.h>
17 #include "vmci_handle_array.h"
19 static size_t handle_arr_calc_size(u32 capacity
)
21 return VMCI_HANDLE_ARRAY_HEADER_SIZE
+
22 capacity
* sizeof(struct vmci_handle
);
25 struct vmci_handle_arr
*vmci_handle_arr_create(u32 capacity
, u32 max_capacity
)
27 struct vmci_handle_arr
*array
;
29 if (max_capacity
== 0 || capacity
> max_capacity
)
33 capacity
= min((u32
)VMCI_HANDLE_ARRAY_DEFAULT_CAPACITY
,
36 array
= kmalloc(handle_arr_calc_size(capacity
), GFP_ATOMIC
);
40 array
->capacity
= capacity
;
41 array
->max_capacity
= max_capacity
;
47 void vmci_handle_arr_destroy(struct vmci_handle_arr
*array
)
52 int vmci_handle_arr_append_entry(struct vmci_handle_arr
**array_ptr
,
53 struct vmci_handle handle
)
55 struct vmci_handle_arr
*array
= *array_ptr
;
57 if (unlikely(array
->size
>= array
->capacity
)) {
59 struct vmci_handle_arr
*new_array
;
60 u32 capacity_bump
= min(array
->max_capacity
- array
->capacity
,
62 size_t new_size
= handle_arr_calc_size(array
->capacity
+
65 if (array
->size
>= array
->max_capacity
)
66 return VMCI_ERROR_NO_MEM
;
68 new_array
= krealloc(array
, new_size
, GFP_ATOMIC
);
70 return VMCI_ERROR_NO_MEM
;
72 new_array
->capacity
+= capacity_bump
;
73 *array_ptr
= array
= new_array
;
76 array
->entries
[array
->size
] = handle
;
83 * Handle that was removed, VMCI_INVALID_HANDLE if entry not found.
85 struct vmci_handle
vmci_handle_arr_remove_entry(struct vmci_handle_arr
*array
,
86 struct vmci_handle entry_handle
)
88 struct vmci_handle handle
= VMCI_INVALID_HANDLE
;
91 for (i
= 0; i
< array
->size
; i
++) {
92 if (vmci_handle_is_equal(array
->entries
[i
], entry_handle
)) {
93 handle
= array
->entries
[i
];
95 array
->entries
[i
] = array
->entries
[array
->size
];
96 array
->entries
[array
->size
] = VMCI_INVALID_HANDLE
;
105 * Handle that was removed, VMCI_INVALID_HANDLE if array was empty.
107 struct vmci_handle
vmci_handle_arr_remove_tail(struct vmci_handle_arr
*array
)
109 struct vmci_handle handle
= VMCI_INVALID_HANDLE
;
113 handle
= array
->entries
[array
->size
];
114 array
->entries
[array
->size
] = VMCI_INVALID_HANDLE
;
121 * Handle at given index, VMCI_INVALID_HANDLE if invalid index.
124 vmci_handle_arr_get_entry(const struct vmci_handle_arr
*array
, u32 index
)
126 if (unlikely(index
>= array
->size
))
127 return VMCI_INVALID_HANDLE
;
129 return array
->entries
[index
];
132 bool vmci_handle_arr_has_entry(const struct vmci_handle_arr
*array
,
133 struct vmci_handle entry_handle
)
137 for (i
= 0; i
< array
->size
; i
++)
138 if (vmci_handle_is_equal(array
->entries
[i
], entry_handle
))
145 * NULL if the array is empty. Otherwise, a pointer to the array
146 * of VMCI handles in the handle array.
148 struct vmci_handle
*vmci_handle_arr_get_handles(struct vmci_handle_arr
*array
)
151 return array
->entries
;