CernVM-FS  2.13.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
malloc_heap.cc
Go to the documentation of this file.
1 
6 #include "malloc_heap.h"
7 
8 #include <cassert>
9 #include <cstring>
10 #include <new>
11 
12 #include "util/smalloc.h"
13 
14 using namespace std; // NOLINT
15 
16 void *MallocHeap::Allocate(uint64_t size, void *header, unsigned header_size) {
17  assert(size > 0);
18  assert(header_size <= size);
19  uint64_t rounded_size = RoundUp8(size);
20  int64_t real_size = rounded_size + sizeof(Tag);
21  if (gauge_ + real_size > capacity_)
22  return NULL;
23 
24  unsigned char *new_block = heap_ + gauge_;
25  new (new_block) Tag(rounded_size);
26  new_block += sizeof(Tag);
27  memcpy(new_block, header, header_size);
28  gauge_ += real_size;
29  stored_ += rounded_size;
30  num_blocks_++;
31  return new_block;
32 }
33 
34 
36  if (gauge_ == 0)
37  return;
38 
39  // Not really a tag, just the top memory address
40  Tag *heap_top = reinterpret_cast<Tag *>(heap_ + gauge_);
41  Tag *current_tag = reinterpret_cast<Tag *>(heap_);
42  Tag *next_tag = current_tag->JumpToNext();
43  // Move a sliding window of two blocks over the heap and compact where
44  // possible
45  while (next_tag < heap_top) {
46  if (current_tag->IsFree()) {
47  if (next_tag->IsFree()) {
48  // Adjacent free blocks, merge and try again
49  current_tag->size -= sizeof(Tag) + next_tag->GetSize();
50  next_tag = next_tag->JumpToNext();
51  } else {
52  // Free block followed by a reserved block, move memory and create a
53  // new free tag at the end of the moved block
54  int64_t free_space = current_tag->size;
55  current_tag->size = next_tag->size;
56  memmove(current_tag->GetBlock(), next_tag->GetBlock(),
57  next_tag->GetSize());
58  (*callback_ptr_)(BlockPtr(current_tag->GetBlock()));
59  next_tag = current_tag->JumpToNext();
60  next_tag->size = free_space;
61  }
62  } else {
63  // Current block allocated, move on
64  current_tag = next_tag;
65  next_tag = next_tag->JumpToNext();
66  }
67  }
68 
69  gauge_ = (reinterpret_cast<unsigned char *>(current_tag) - heap_);
70  if (!current_tag->IsFree())
71  gauge_ += sizeof(Tag) + current_tag->GetSize();
72 }
73 
74 
75 void *MallocHeap::Expand(void *block, uint64_t new_size) {
76  uint64_t old_size = GetSize(block);
77  assert(old_size <= new_size);
78  void *new_block = Allocate(new_size, block, old_size);
79  if (new_block != NULL)
80  MarkFree(block);
81  return new_block;
82 }
83 
84 
85 bool MallocHeap::HasSpaceFor(uint64_t nbytes) {
86  return RoundUp8(gauge_ + nbytes + sizeof(Tag)) <= capacity_;
87 }
88 
89 
90 void MallocHeap::MarkFree(void *block) {
91  Tag *tag = reinterpret_cast<Tag *>(block) - 1;
92  assert(tag->size > 0);
93  tag->size = -(tag->size);
94  stored_ -= tag->GetSize();
95  num_blocks_--;
96  // TODO(jblomer): if MarkFree() takes place at the top of the heap, one could
97  // move back the gauge_ pointer. If this is an optimization or unnecessary
98  // extra work depends on how the MallocHeap is used.
99 }
100 
101 
102 uint64_t MallocHeap::GetSize(void *block) {
103  Tag *tag = reinterpret_cast<Tag *>(block) - 1;
104  assert(tag->size > 0);
105  return tag->size;
106 }
107 
108 
109 MallocHeap::MallocHeap(uint64_t capacity, CallbackPtr callback_ptr)
110  : callback_ptr_(callback_ptr)
111  , capacity_(capacity)
112  , gauge_(0)
113  , stored_(0)
114  , num_blocks_(0) {
116  // Ensure 8-byte alignment
117  assert((capacity_ % 8) == 0);
118  heap_ = reinterpret_cast<unsigned char *>(sxmmap(capacity));
119  assert(uintptr_t(heap_) % 8 == 0);
120 }
121 
122 
static const unsigned kMinCapacity
Definition: malloc_heap.h:73
void * Allocate(uint64_t size, void *header, unsigned header_size)
Definition: malloc_heap.cc:16
unsigned char * heap_
Definition: malloc_heap.h:124
MallocHeap(uint64_t capacity, CallbackPtr callback_ptr)
Definition: malloc_heap.cc:109
assert((mem||(size==0))&&"Out Of Memory")
uint64_t capacity_
Definition: malloc_heap.h:108
uint64_t GetSize()
Definition: malloc_heap.h:82
void * Expand(void *block, uint64_t new_size)
Definition: malloc_heap.cc:75
uint64_t GetSize(void *block)
Definition: malloc_heap.cc:102
Callbackable< BlockPtr >::CallbackTN * CallbackPtr
Definition: malloc_heap.h:46
void MarkFree(void *block)
Definition: malloc_heap.cc:90
static uint64_t RoundUp8(const uint64_t size)
Definition: smalloc.h:37
Tag * JumpToNext()
Definition: malloc_heap.h:88
bool HasSpaceFor(uint64_t nbytes)
Definition: malloc_heap.cc:85
unsigned char * GetBlock()
Definition: malloc_heap.h:92
static void size_t size
Definition: smalloc.h:54
void Compact()
Definition: malloc_heap.cc:35