Quake II RTX doxygen  1.0 dev
buddy_allocator.h File Reference
#include <stdint.h>

Go to the source code of this file.

Typedefs

typedef struct BuddyAllocator BuddyAllocator
 

Enumerations

enum  BAResult { BA_SUCCESS = 0, BA_NOT_ENOUGH_MEMORY, BA_INVALID_ALIGNMENT }
 

Functions

BuddyAllocatorcreate_buddy_allocator (uint64_t capacity, uint64_t block_size)
 
BAResult buddy_allocator_allocate (BuddyAllocator *allocator, uint64_t size, uint64_t alignment, uint64_t *offset)
 
void buddy_allocator_free (BuddyAllocator *allocator, uint64_t offset, uint64_t size)
 
void destroy_buddy_allocator (BuddyAllocator *allocator)
 

Typedef Documentation

◆ BuddyAllocator

Definition at line 29 of file buddy_allocator.h.

Enumeration Type Documentation

◆ BAResult

enum BAResult
Enumerator
BA_SUCCESS 
BA_NOT_ENOUGH_MEMORY 
BA_INVALID_ALIGNMENT 

Definition at line 22 of file buddy_allocator.h.

23 {
24  BA_SUCCESS = 0,
27 } BAResult;

Function Documentation

◆ buddy_allocator_allocate()

BAResult buddy_allocator_allocate ( BuddyAllocator allocator,
uint64_t  size,
uint64_t  alignment,
uint64_t *  offset 
)

Definition at line 97 of file buddy_allocator.c.

98 {
99  uint32_t level = max((uint32_t)ceil(log2(size)), allocator->base_level) - allocator->base_level;
100 
101  // The requested size exceeds the allocator capacity
102  if (level >= allocator->level_num)
103  return BA_NOT_ENOUGH_MEMORY;
104 
105  // Every block is aligned to its size
106  const uint64_t block_size = (uint64_t)(1 << (level + allocator->base_level));
107  const uint64_t alignment_size = block_size % alignment;
108 
109  assert(alignment_size == 0);
110  if (alignment_size != 0)
111  return BA_INVALID_ALIGNMENT;
112 
113  uint32_t i = level;
114  for (; i < allocator->level_num && allocator->free_block_lists[i] == NULL; i++)
115  {
116  }
117 
118  if (i == allocator->level_num)
119  return BA_NOT_ENOUGH_MEMORY;
120 
121  if (i > level)
122  subdivide_block(allocator, i, level);
123 
124  AllocatorFreeListItem* item = allocator->free_block_lists[level];
125  allocator->free_block_lists[level] = item->next;
126 
127  const uint32_t level_block_offset = get_level_offset(allocator, level);
128  allocator->block_states[level_block_offset + item->block_index] = BLOCK_ALLOCATED;
129 
130  *offset = item->block_index * block_size;
131  free_list_item(allocator, item);
132 
133  return BA_SUCCESS;
134 }

Referenced by allocate_device_memory().

◆ buddy_allocator_free()

void buddy_allocator_free ( BuddyAllocator allocator,
uint64_t  offset,
uint64_t  size 
)

Definition at line 136 of file buddy_allocator.c.

137 {
138  const uint32_t level = max((uint32_t)ceil(log2(size)), allocator->base_level) - allocator->base_level;
139  const uint64_t block_size = (uint64_t)(1 << (level + allocator->base_level));
140  const uint32_t block_index = offset / block_size;
141 
142  const uint32_t level_block_offset = get_level_offset(allocator, level);
143  assert(allocator->block_states[level_block_offset + block_index] == BLOCK_ALLOCATED);
144  allocator->block_states[level_block_offset + block_index] = BLOCK_FREE;
145 
146  if (!merge_blocks(allocator, level, block_index))
147  write_free_block_to_list(allocator, level, block_index);
148 }

Referenced by free_device_memory().

◆ create_buddy_allocator()

BuddyAllocator* create_buddy_allocator ( uint64_t  capacity,
uint64_t  block_size 
)

Definition at line 59 of file buddy_allocator.c.

60 {
61  const uint32_t base_level = uint_log2(block_size);
62  const uint32_t level_num = uint_log2(capacity) - base_level + 1;
63 
64  uint32_t block_num = 0;
65  for (uint32_t i = 0; i < level_num; i++)
66  block_num += 1 << ((level_num - 1) - i);
67 
68  const size_t alignment = 16;
69  const size_t allocator_size = _align(sizeof(BuddyAllocator), alignment);
70  const size_t free_list_array_size = _align(level_num * sizeof(AllocatorFreeListItem*), alignment);
71  const size_t free_item_buffer_size = _align(block_num * sizeof(AllocatorFreeListItem), alignment);
72  const size_t block_state_size = _align(block_num * sizeof(uint8_t), alignment);
73  char* memory = malloc(allocator_size + free_list_array_size + free_item_buffer_size + block_state_size);
74 
75  BuddyAllocator* allocator = (BuddyAllocator*)memory;
76  allocator->base_level = base_level;
77  allocator->level_num = level_num;
78  allocator->memory = memory;
79  allocator->free_block_lists = (AllocatorFreeListItem**)(memory + allocator_size);
80  allocator->free_items = (AllocatorFreeListItem*)(memory + allocator_size + free_list_array_size);
81  allocator->block_states = (uint8_t*)(memory + allocator_size + free_list_array_size + free_item_buffer_size);
82 
83  memset(allocator->free_block_lists, 0, level_num * sizeof(AllocatorFreeListItem*));
84  memset(allocator->free_items, 0, block_num * sizeof(AllocatorFreeListItem));
85  memset(allocator->block_states, 0, block_num * sizeof(uint8_t));
86 
87  for (uint32_t i = 0; i < block_num; i++)
88  allocator->free_items[i].next = allocator->free_items + i + 1;
89  allocator->free_items[block_num - 1].next = NULL;
90 
91  allocator->block_states[block_num - 1] = BLOCK_FREE;
92  write_free_block_to_list(allocator, level_num - 1, 0);
93 
94  return allocator;
95 }

Referenced by create_sub_allocator().

◆ destroy_buddy_allocator()

void destroy_buddy_allocator ( BuddyAllocator allocator)

Definition at line 150 of file buddy_allocator.c.

151 {
152  free(allocator->memory);
153 }
free_list_item
static void free_list_item(BuddyAllocator *allocator, AllocatorFreeListItem *item)
Definition: buddy_allocator.c:254
subdivide_block
void subdivide_block(BuddyAllocator *allocator, uint32_t src_level, uint32_t dst_level)
Definition: buddy_allocator.c:155
uint_log2
static int32_t uint_log2(uint64_t x)
Definition: buddy_allocator.c:239
BuddyAllocator::block_states
uint8_t * block_states
Definition: buddy_allocator.c:42
BA_SUCCESS
@ BA_SUCCESS
Definition: buddy_allocator.h:24
BuddyAllocator::free_block_lists
struct AllocatorFreeListItem ** free_block_lists
Definition: buddy_allocator.c:41
BuddyAllocator::base_level
uint32_t base_level
Definition: buddy_allocator.c:39
BuddyAllocator::free_items
struct AllocatorFreeListItem * free_items
Definition: buddy_allocator.c:43
_align
static size_t _align(size_t value, size_t alignment)
Definition: buddy_allocator.c:234
BLOCK_FREE
@ BLOCK_FREE
Definition: buddy_allocator.c:26
BuddyAllocator
Definition: buddy_allocator.c:37
BAResult
BAResult
Definition: buddy_allocator.h:22
get_level_offset
static uint32_t get_level_offset(BuddyAllocator *allocator, uint32_t level)
Definition: buddy_allocator.c:268
write_free_block_to_list
static void write_free_block_to_list(BuddyAllocator *allocator, uint32_t level, uint32_t block_index)
Definition: buddy_allocator.c:260
AllocatorFreeListItem::block_index
uint32_t block_index
Definition: buddy_allocator.c:33
BA_INVALID_ALIGNMENT
@ BA_INVALID_ALIGNMENT
Definition: buddy_allocator.h:26
BuddyAllocator::memory
void * memory
Definition: buddy_allocator.c:44
AllocatorFreeListItem::next
struct AllocatorFreeListItem * next
Definition: buddy_allocator.c:34
level
level_locals_t level
Definition: g_main.c:22
BuddyAllocator::level_num
uint32_t level_num
Definition: buddy_allocator.c:40
BLOCK_ALLOCATED
@ BLOCK_ALLOCATED
Definition: buddy_allocator.c:28
BA_NOT_ENOUGH_MEMORY
@ BA_NOT_ENOUGH_MEMORY
Definition: buddy_allocator.h:25
merge_blocks
qboolean merge_blocks(BuddyAllocator *allocator, uint32_t level, uint32_t block_index)
Definition: buddy_allocator.c:190
AllocatorFreeListItem
Definition: buddy_allocator.c:31