github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/cpvmm/vmm/utils/array_list.c (about) 1 /* 2 * Copyright (c) 2013 Intel Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * Unless required by applicable law or agreed to in writing, software 9 * distributed under the License is distributed on an "AS IS" BASIS, 10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 * See the License for the specific language governing permissions and 12 * limitations under the License. 13 */ 14 15 #include "list.h" 16 #ifdef JLMDEBUG 17 #include "jlmdebug.h" 18 #endif 19 20 // %VT% typedef struct _ARRAY_LIST_ELEMENT ARRAY_LIST_ELEMENT; 21 #define ARRAY_LIST_HEADER_SIZE(alignment) \ 22 (UINT32) (ALIGN_FORWARD(sizeof(ARRAY_LIST) - sizeof(((ARRAY_LIST *) 0)->array), (ADDRESS) alignment)) 23 24 #define ARRAY_LIST_ELEMENT_HEADER_SIZE ((UINT32) sizeof(ARRAY_LIST_ELEMENT) - (UINT32) sizeof(((ARRAY_LIST_ELEMENT *) 0)->data)) 25 26 #define ARRAY_LIST_ELEMENT_SIZE(element_size, alignment) (UINT32) (ALIGN_FORWARD(ARRAY_LIST_ELEMENT_HEADER_SIZE + element_size, (ADDRESS) alignment)) 27 28 #define ARRAY_LIST_ELEMENT_BY_INDEX(alist, i) \ 29 (ARRAY_LIST_ELEMENT *)(alist->array + ARRAY_LIST_ELEMENT_SIZE(alist->element_size, alist->alignment) * i) 30 31 #define ARRAY_LIST_DATA_TO_ELEMENT(data) (ARRAY_LIST_ELEMENT *)((char *) data - (char *)((ARRAY_LIST_ELEMENT *) 0)->data) 32 33 #define ARRAY_LIST_PADDING_SIZE(address, alignment) (UINT32) (((char *) ALIGN_FORWARD(address, (ADDRESS) alignment)) - address) 34 35 typedef struct _ARRAY_LIST_ELEMENT 36 { 37 LIST_ELEMENT list; // free/used list 38 char data[ARCH_ADDRESS_WIDTH]; 39 } ARRAY_LIST_ELEMENT; 40 41 typedef struct _ARRAY_LIST 42 { 43 UINT32 element_size; 44 UINT32 max_num_of_elements; 45 UINT32 alignment; 46 UINT32 memory_size; 47 UINT32 header_padding_size; 48 UINT32 id; 49 LIST_ELEMENT free_list; 50 LIST_ELEMENT used_list; 51 UINT32 num_of_used_elements; 52 char array[4]; 53 } ARRAY_LIST; 54 55 UINT32 array_list_memory_size(char *buffer, UINT32 element_size, UINT32 num_of_elements, UINT32 alignment) 56 { 57 return (UINT32) (ARRAY_LIST_PADDING_SIZE(buffer, alignment) + 58 ARRAY_LIST_HEADER_SIZE(alignment) + 59 ARRAY_LIST_ELEMENT_SIZE(element_size, alignment) * num_of_elements); 60 } 61 62 UINT32 array_list_size(ARRAY_LIST *alist) 63 { 64 return alist->num_of_used_elements; 65 } 66 67 ARRAY_LIST_HANDLE array_list_init(char *buffer, UINT32 buffer_size, UINT32 element_size, UINT32 num_of_elements, UINT32 alignment) 68 { 69 static UINT16 list_id = 1; 70 UINT32 required_buffer_size = array_list_memory_size(buffer, element_size, num_of_elements, alignment); 71 ARRAY_LIST *alist; 72 UINT32 i; 73 ARRAY_LIST_ELEMENT *entry = NULL; 74 LIST_ELEMENT *free_list = NULL; 75 76 if(required_buffer_size > buffer_size) { 77 return NULL; 78 } 79 80 alist = (ARRAY_LIST *) (buffer + ARRAY_LIST_PADDING_SIZE(buffer, alignment)); 81 alist->id = list_id++; 82 alist->element_size = element_size; 83 alist->max_num_of_elements = num_of_elements; 84 alist->alignment = alignment; 85 alist->memory_size = buffer_size; 86 alist->header_padding_size = ARRAY_LIST_PADDING_SIZE(buffer, alignment); 87 alist->num_of_used_elements = 0; 88 89 list_init(&alist->free_list); 90 list_init(&alist->used_list); 91 92 free_list = &alist->free_list; 93 94 for(i = 0; i < num_of_elements; i++) { 95 entry = ARRAY_LIST_ELEMENT_BY_INDEX(alist, i); 96 list_add(free_list, &entry->list); 97 free_list = free_list->next; 98 } 99 100 return alist; 101 } 102 103 BOOLEAN array_list_add(ARRAY_LIST_HANDLE alist, void* data) 104 { 105 LIST_ELEMENT *free_element = NULL; 106 ARRAY_LIST_ELEMENT *free_list_entry = NULL; 107 108 if(list_is_empty(&alist->free_list) || alist == NULL || data == NULL) { 109 return FALSE; 110 } 111 free_element = alist->free_list.next; 112 list_remove(free_element); 113 list_add(alist->used_list.prev, free_element); 114 alist->num_of_used_elements++; 115 116 free_list_entry = LIST_ENTRY(free_element, ARRAY_LIST_ELEMENT, list); 117 vmm_memcpy(free_list_entry->data, data, alist->element_size); 118 return TRUE; 119 } 120 121 BOOLEAN array_list_remove(ARRAY_LIST_HANDLE alist, void *data) 122 { 123 ARRAY_LIST_ELEMENT *element; 124 125 if(list_is_empty(&alist->used_list) || alist == NULL || data == NULL) { 126 return FALSE; 127 } 128 129 element = ARRAY_LIST_DATA_TO_ELEMENT(data); 130 list_remove(&element->list); 131 list_add(alist->free_list.prev, &element->list); 132 alist->num_of_used_elements--; 133 134 return TRUE; 135 } 136 137 138 char *array_list_first(ARRAY_LIST_HANDLE alist, ARRAY_LIST_ITERATOR *iter) 139 { 140 ARRAY_LIST_ELEMENT *element; 141 char* data; 142 143 if(list_is_empty(&alist->used_list)) { 144 return NULL; 145 } 146 element = LIST_ENTRY(alist->used_list.next, ARRAY_LIST_ELEMENT, list); 147 data = element->data; 148 149 if(iter != NULL) { 150 iter->alist = alist; 151 iter->element = element; 152 } 153 return data; 154 } 155 156 157 #ifdef INCLUDE_UNUSED_CODE 158 char *array_list_next(ARRAY_LIST_ITERATOR *iter) 159 { 160 if(iter == NULL || iter->element->list.next == &iter->alist->used_list) { 161 return NULL; 162 } 163 164 iter->element = LIST_ENTRY(iter->element->list.next, ARRAY_LIST_ELEMENT, list); 165 return iter->element->data; 166 } 167 #endif