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