memalign.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /*
  2. * Copyright Institute of Communication and Computer Systems (ICCS)
  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. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. /**
  18. * @file freelist/memalign.c
  19. * @author Ioannis Koutras
  20. * @date February 2013
  21. * @brief memalign() implementation for freelist-organised raw blocks
  22. */
  23. #include "dmmlib/freelist/freelist.h"
  24. #include <inttypes.h>
  25. #include "memcpy.h"
  26. #include "dmmlib/config.h"
  27. #include "freelist/block_header_funcs.h"
  28. void * freelist_memalign(freelist_rb_t *raw_block, size_t alignment,
  29. size_t size) {
  30. void *return_ptr;
  31. return_ptr = freelist_malloc(raw_block, size + alignment - 1);
  32. if(return_ptr != NULL) {
  33. check_alignment:
  34. if(((uintptr_t) return_ptr) % alignment == 0) {
  35. /* Memory address is already aligned, no need for
  36. * modifications */
  37. return return_ptr;
  38. }
  39. size_t padding = (- (size_t) return_ptr) & (alignment - 1);
  40. block_header_t *block_header = get_header(return_ptr);
  41. /* Check if the currently selected memory block is the first
  42. * allocated in the raw block. If it is, then there is no previous
  43. * block in the data layout, so we cannot increase its size as this
  44. * would conclude to wasted space. Instead of this, we try to
  45. * allocate another block which is guaranteed not to be the first
  46. * memory block at this point. If we find one, then we free the
  47. * first allocated block and repeat the process of alignment.
  48. * Otherwise, we go to the next raw block. */
  49. size_t previous_size_availability =
  50. get_previous_size_availability(block_header);
  51. if(previous_size_availability == 1) {
  52. void *old_ptr = return_ptr;
  53. return_ptr = freelist_malloc(raw_block, size + alignment - 1);
  54. freelist_free(raw_block, old_ptr);
  55. if(return_ptr != NULL) {
  56. goto check_alignment;
  57. }
  58. } else {
  59. size_t previous_size = previous_size_availability >> 1;
  60. size_t previous_availability = previous_size_availability & 1;
  61. block_header_t *previous_block = (block_header_t *)
  62. ((uintptr_t) block_header - previous_size - HEADER_SIZE);
  63. block_header_t *next_block = get_dlnext(raw_block,
  64. block_header);
  65. previous_size += padding;
  66. previous_block->size = (previous_size << 1) |
  67. previous_availability;
  68. block_header->previous_size = (previous_size << 1) |
  69. previous_availability;
  70. #ifdef REQUEST_SIZE_INFO
  71. block_header->requested_size = size;
  72. #endif /* REQUEST_SIZE_INFO */
  73. size_t new_size = get_size(block_header) - padding;
  74. block_header->size = (new_size << 1) | 1;
  75. if(next_block != NULL) {
  76. next_block->previous_size = block_header->size;
  77. } else { /* The aligned memory block is the border pointer */
  78. raw_block->border_ptr = (block_header_t *)
  79. ((uintptr_t) block_header + padding);
  80. }
  81. memcpy((void *) ((uintptr_t) block_header + padding),
  82. (void *) block_header, HEADER_SIZE);
  83. return_ptr = (void *)((uintptr_t) return_ptr + padding);
  84. }
  85. }
  86. return return_ptr;
  87. }