Advertisement
Guest User

Untitled

a guest
Apr 18th, 2019
134
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.67 KB | None | 0 0
  1. /* buddy.c
  2.  *
  3.  * Description:
  4.  *   Implement buddy system for memory management
  5.  *
  6.  * Idea & part of the code are from https://github.com/wuwenbin/buddy2
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <assert.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <stdbool.h>
  14. #include "buddy.h"
  15.  
  16. struct buddy {
  17.     size_t size;
  18.     size_t longest[1];
  19. };
  20.  
  21. static inline int left_child(int index)
  22. {
  23.     /* index * 2 + 1 */
  24.     return ((index << 1) + 1);
  25. }
  26.  
  27. static inline int right_child(int index)
  28. {
  29.     /* index * 2 + 2 */
  30.     return ((index << 1) + 2);
  31. }
  32.  
  33. static inline int parent(int index)
  34. {
  35.     /* (index+1)/2 - 1 */
  36.     return (((index+1)>>1) - 1);
  37. }
  38.  
  39. static inline bool is_power_of_2(int index)
  40. {
  41.     return !(index & (index - 1));
  42. }
  43.  
  44. #define max(a, b) (((a)>(b))?(a):(b))
  45. #define min(a, b) (((a)<(b))?(a):(b))
  46.  
  47. static inline unsigned next_power_of_2(unsigned size)
  48. {
  49.     /* depend on the fact that size < 2^32 */
  50.     size -= 1;
  51.     size |= (size >> 1);
  52.     size |= (size >> 2);
  53.     size |= (size >> 4);
  54.     size |= (size >> 8);
  55.     size |= (size >> 16);
  56.     return size + 1;
  57. }
  58.  
  59. /** allocate a new buddy structure
  60.  * @param num_of_fragments number of fragments of the memory to be managed
  61.  * @return pointer to the allocated buddy structure */
  62. struct buddy *buddy_new(unsigned num_of_fragments)
  63. {
  64.     struct buddy *self = NULL;
  65.     size_t node_size;
  66.  
  67.     int i;
  68.  
  69.     if (num_of_fragments < 1 || !is_power_of_2(num_of_fragments)) {
  70.         return NULL;
  71.     }
  72.  
  73.     /* alloacte an array to represent a complete binary tree */
  74.     self = (struct buddy *) b_malloc(sizeof(struct buddy)
  75.                                      + 2 * num_of_fragments * sizeof(size_t));
  76.     self->size = num_of_fragments;
  77.     node_size = num_of_fragments * 2;
  78.    
  79.     /* initialize *longest* array for buddy structure */
  80.     int iter_end = num_of_fragments * 2 - 1;
  81.     for (i = 0; i < iter_end; i++) {
  82.         if (is_power_of_2(i+1)) {
  83.             node_size >>= 1;
  84.         }
  85.         self->longest[i] = node_size;
  86.     }
  87.  
  88.     return self;
  89. }
  90.  
  91. /* choose the child with smaller longest value which is still larger
  92.  * than *size* */
  93. unsigned choose_better_child(struct buddy *self, unsigned index, size_t size)
  94. {
  95.     struct compound {
  96.         size_t size;
  97.         unsigned index;
  98.     } children[2];
  99.     children[0].index = left_child(index);
  100.     children[0].size = self->longest[children[0].index];
  101.     children[1].index = right_child(index);
  102.     children[1].size = self->longest[children[1].index];
  103.  
  104.     int min_idx = (children[0].size <= children[1].size) ? 0: 1;
  105.  
  106.     if (size > children[min_idx].size) {
  107.         min_idx = 1 - min_idx;
  108.     }
  109.    
  110.     return children[min_idx].index;
  111. }
  112.  
  113. /** allocate *size* from a buddy system *self*
  114.  * @return the offset from the beginning of memory to be managed */
  115. int buddy_alloc(struct buddy *self, size_t size)
  116. {
  117.     if (self == NULL || self->size < size) {
  118.         return -1;
  119.     }
  120.     size = next_power_of_2(size);
  121.  
  122.     unsigned index = 0;
  123.     if (self->longest[index] < size) {
  124.         return -1;
  125.     }
  126.  
  127.     /* search recursively for the child */
  128.     unsigned node_size = 0;
  129.     for (node_size = self->size; node_size != size; node_size >>= 1) {
  130.         /* choose the child with smaller longest value which is still larger
  131.          * than *size* */
  132.         /* TODO */
  133.         index = choose_better_child(self, index, size);
  134.     }
  135.  
  136.     /* update the *longest* value back */
  137.     self->longest[index] = 0;
  138.     int offset = (index + 1)*node_size - self->size;
  139.  
  140.     while (index) {
  141.         index = parent(index);
  142.         self->longest[index] =
  143.             max(self->longest[left_child(index)],
  144.                 self->longest[right_child(index)]);
  145.     }
  146.  
  147.     return offset;
  148. }
  149.  
  150. void buddy_free(struct buddy *self, int offset)
  151. {
  152.     if (self == NULL || offset < 0 || offset > self->size) {
  153.         return;
  154.     }
  155.  
  156.     size_t node_size;
  157.     unsigned index;
  158.  
  159.     /* get the corresponding index from offset */
  160.     node_size = 1;
  161.     index = offset + self->size - 1;
  162.  
  163.     for (; self->longest[index] != 0; index = parent(index)) {
  164.         node_size <<= 1;    /* node_size *= 2; */
  165.  
  166.         if (index == 0) {
  167.             break;
  168.         }
  169.     }
  170.  
  171.     self->longest[index] = node_size;
  172.  
  173.     while (index) {
  174.         index = parent(index);
  175.         node_size <<= 1;
  176.  
  177.         size_t left_longest = self->longest[left_child(index)];
  178.         size_t right_longest = self->longest[right_child(index)];
  179.  
  180.         if (left_longest + right_longest == node_size) {
  181.             self->longest[index] = node_size;
  182.         } else {
  183.             self->longest[index] = max(left_longest, right_longest);
  184.         }
  185.     }
  186. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement