GCC Code Coverage Report
Directory: cvmfs/ Exec Total Coverage
File: cvmfs/smalloc.h Lines: 52 52 100.0 %
Date: 2019-02-03 02:48:13 Branches: 12 28 42.9 %

Line Branch Exec Source
1
/**
2
 * This file is part of the CernVM File System.
3
 *
4
 * Ensures that cvmfs aborts on out-of-memory errors.
5
 */
6
7
#ifndef CVMFS_SMALLOC_H_
8
#define CVMFS_SMALLOC_H_
9
10
#include <stdint.h>
11
#include <stdlib.h>
12
#include <sys/mman.h>
13
14
#include <cassert>
15
// #include <cstdio>
16
17
#include <limits>
18
19
#ifdef __APPLE__
20
#define PLATFORM_MAP_ANONYMOUS MAP_ANON
21
#else
22
#define PLATFORM_MAP_ANONYMOUS MAP_ANONYMOUS
23
#endif
24
25
26
#ifdef CVMFS_NAMESPACE_GUARD
27
namespace CVMFS_NAMESPACE_GUARD {
28
#endif
29
30
// Checkerboard marker (binary 101010...)
31
const uint32_t kMemMarker = 0xAAAAAAAA;
32
33
/**
34
 * Round up size to the next larger multiple of 8.  This is used to enforce
35
 * 8-byte alignment.
36
 */
37
7623870
static inline uint64_t RoundUp8(const uint64_t size) {
38
7623870
  return (size + 7) & ~static_cast<uint64_t>(7);
39
}
40
41
221118
static inline void * __attribute__((used)) smalloc(size_t size) {
42
221118
  void *mem = malloc(size);
43

221118
  assert((mem || (size == 0)) && "Out Of Memory");
44
221118
  return mem;
45
}
46
47
579427
static inline void * __attribute__((used)) srealloc(void *ptr, size_t size) {
48
579427
  void *mem = realloc(ptr, size);
49

579427
  assert((mem || (size == 0)) && "Out Of Memory");
50
579427
  return mem;
51
}
52
53
491
static inline void * __attribute__((used)) scalloc(size_t count, size_t size) {
54
491
  void *mem = calloc(count, size);
55

491
  assert((mem || ((count * size) == 0)) && "Out Of Memory");
56
491
  return mem;
57
}
58
59
25135
static inline void * __attribute__((used)) smmap(size_t size) {
60
  // TODO(reneme): make page size platform independent
61
25135
  assert(size > 0);
62
25135
  assert(size < std::numeric_limits<size_t>::max() - 4096);
63
64
25135
  const int anonymous_fd = -1;
65
25135
  const off_t offset = 0;
66
25135
  size_t pages = ((size + 2*sizeof(size_t))+4095)/4096;  // round to full page
67
  unsigned char *mem = static_cast<unsigned char *>(
68
    mmap(NULL,
69
         pages*4096,
70
         PROT_READ | PROT_WRITE,
71
         MAP_PRIVATE | PLATFORM_MAP_ANONYMOUS,
72
         anonymous_fd,
73
25135
         offset));
74
  // printf("SMMAP %d bytes at %p\n", pages*4096, mem);
75
25135
  assert((mem != MAP_FAILED) && "Out Of Memory");
76
25135
  *(reinterpret_cast<size_t *>(mem)) = kMemMarker;
77
25135
  *(reinterpret_cast<size_t *>(mem) + 1) = pages;
78
25135
  return mem + 2*sizeof(size_t);
79
}
80
81
25133
static inline void __attribute__((used)) smunmap(void *mem) {
82
25133
  unsigned char *area = static_cast<unsigned char *>(mem);
83
25133
  area = area - sizeof(size_t);
84
25133
  size_t pages = *(reinterpret_cast<size_t *>(area));
85
25133
  int retval = munmap(area-sizeof(size_t), pages*4096);
86
  // printf("SUNMMAP %d bytes at %p\n", pages*4096, area);
87
25133
  assert((retval == 0) && "Invalid umnmap");
88
25133
}
89
90
91
/**
92
 * Used when the caller remembers the size, so that it can call sxunmap later.
93
 */
94
1049
static inline void * __attribute__((used)) sxmmap(size_t size) {
95
1049
  const int anonymous_fd = -1;
96
1049
  const off_t offset = 0;
97
  void *mem = mmap(NULL,
98
                   size,
99
                   PROT_READ | PROT_WRITE,
100
                   MAP_PRIVATE | PLATFORM_MAP_ANONYMOUS,
101
                   anonymous_fd,
102
1049
                   offset);
103
1049
  assert((mem != MAP_FAILED) && "Out Of Memory");
104
1049
  return mem;
105
}
106
107
108
/**
109
 * Free memory acquired by sxmmap.
110
 */
111
1850
static inline void __attribute__((used)) sxunmap(void *mem, size_t size) {
112
1850
  int retval = munmap(mem, size);
113
1850
  assert((retval == 0) && "Invalid umnmap");
114
1850
}
115
116
117
/**
118
 * Pointer is aligned at a multiple of the size.  The size has to be a multiple
119
 * of 2MB.
120
 */
121
512
static inline void * __attribute__((used)) sxmmap_align(size_t size) {
122
512
  assert((size % (2 * 1024 * 1024)) == 0);
123
512
  char *mem = reinterpret_cast<char *>(sxmmap(2 * size));
124
512
  uintptr_t head = size - (uintptr_t(mem) % size);
125
512
  sxunmap(mem, head);
126
512
  mem += head;
127
512
  uintptr_t tail = size - head;
128
512
  if (tail > 0)
129
301
    sxunmap(mem + size, tail);
130
512
  return mem;
131
}
132
133
134
#ifdef CVMFS_NAMESPACE_GUARD
135
}  // namespace CVMFS_NAMESPACE_GUARD
136
#endif
137
138
#endif  // CVMFS_SMALLOC_H_