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