GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/util/smalloc.h
Date: 2024-04-21 02:33:16
Exec Total Coverage
Lines: 58 58 100.0%
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_UTIL_SMALLOC_H_
8 #define CVMFS_UTIL_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 7236125 static inline uint64_t RoundUp8(const uint64_t size) {
38 7236125 return (size + 7) & ~static_cast<uint64_t>(7);
39 }
40
41 1713663 static inline void * __attribute__((used)) smalloc(size_t size) {
42 1713663 void *mem = NULL;
43 #ifdef CVMFS_SUPPRESS_ASSERTS
44 do {
45 #endif
46 1713663 mem = malloc(size);
47 #ifdef CVMFS_SUPPRESS_ASSERTS
48 } while ((size > 0) && (mem == NULL));
49 #endif
50
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1713663 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1713663 assert((mem || (size == 0)) && "Out Of Memory");
51 1713663 return mem;
52 }
53
54 174901 static inline void * __attribute__((used)) srealloc(void *ptr, size_t size) {
55 174901 void *mem = NULL;
56
57 #ifdef CVMFS_SUPPRESS_ASSERTS
58 do {
59 #endif
60 174901 mem = realloc(ptr, size);
61 #ifdef CVMFS_SUPPRESS_ASSERTS
62 } while ((size > 0) && (mem == NULL));
63 #endif
64
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 174901 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
174901 assert((mem || (size == 0)) && "Out Of Memory");
65 174901 return mem;
66 }
67
68 324 static inline void * __attribute__((used)) scalloc(size_t count, size_t size) {
69 324 void *mem = NULL;
70
71 #ifdef CVMFS_SUPPRESS_ASSERTS
72 do {
73 #endif
74 324 mem = calloc(count, size);
75 #ifdef CVMFS_SUPPRESS_ASSERTS
76 } while ((count * size > 0) && (mem == NULL));
77 #endif
78
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 324 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
324 assert((mem || ((count * size) == 0)) && "Out Of Memory");
79 324 return mem;
80 }
81
82 11610 static inline void * __attribute__((used)) smmap(size_t size) {
83 // TODO(reneme): make page size platform independent
84
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11610 times.
11610 assert(size > 0);
85
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11610 times.
11610 assert(size < std::numeric_limits<size_t>::max() - 4096);
86
87 11610 const int anonymous_fd = -1;
88 11610 const off_t offset = 0;
89 11610 size_t pages = ((size + 2*sizeof(size_t))+4095)/4096; // round to full page
90 11610 unsigned char *mem = NULL;
91
92 #ifdef CVMFS_SUPPRESS_ASSERTS
93 do {
94 #endif
95 mem = static_cast<unsigned char *>(
96 11610 mmap(NULL,
97 pages*4096,
98 PROT_READ | PROT_WRITE,
99 MAP_PRIVATE | PLATFORM_MAP_ANONYMOUS,
100 anonymous_fd,
101 offset));
102
103 #ifdef CVMFS_SUPPRESS_ASSERTS
104 } while (mem == MAP_FAILED);
105 #endif
106 // printf("SMMAP %d bytes at %p\n", pages*4096, mem);
107 // NOLINTNEXTLINE(performance-no-int-to-ptr)
108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11613 times.
11613 assert((mem != MAP_FAILED) && "Out Of Memory");
109 11613 *(reinterpret_cast<size_t *>(mem)) = kMemMarker;
110 11613 *(reinterpret_cast<size_t *>(mem) + 1) = pages;
111 11613 return mem + 2*sizeof(size_t);
112 }
113
114 11600 static inline void __attribute__((used)) smunmap(void *mem) {
115 11600 unsigned char *area = static_cast<unsigned char *>(mem);
116 11600 area = area - sizeof(size_t);
117 11600 size_t pages = *(reinterpret_cast<size_t *>(area));
118 11600 int retval = munmap(area-sizeof(size_t), pages*4096);
119 // printf("SUNMMAP %d bytes at %p\n", pages*4096, area);
120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11600 times.
11600 assert((retval == 0) && "Invalid umnmap");
121 11600 }
122
123
124 /**
125 * Used when the caller remembers the size, so that it can call sxunmap later.
126 */
127 560 static inline void * __attribute__((used)) sxmmap(size_t size) {
128 560 const int anonymous_fd = -1;
129 560 const off_t offset = 0;
130 560 void *mem = NULL;
131
132 #ifdef CVMFS_SUPPRESS_ASSERTS
133 do {
134 #endif
135 560 mem = mmap(NULL,
136 size,
137 PROT_READ | PROT_WRITE,
138 MAP_PRIVATE | PLATFORM_MAP_ANONYMOUS,
139 anonymous_fd,
140 offset);
141
142 #ifdef CVMFS_SUPPRESS_ASSERTS
143 } while (mem == MAP_FAILED);
144 #endif
145 // NOLINTNEXTLINE(performance-no-int-to-ptr)
146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 560 times.
560 assert((mem != MAP_FAILED) && "Out Of Memory");
147 560 return mem;
148 }
149
150
151 /**
152 * Free memory acquired by sxmmap.
153 */
154 1239 static inline void __attribute__((used)) sxunmap(void *mem, size_t size) {
155 1239 int retval = munmap(mem, size);
156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1239 times.
1239 assert((retval == 0) && "Invalid umnmap");
157 1239 }
158
159
160 /**
161 * Pointer is aligned at a multiple of the size. The size has to be a multiple
162 * of 2MB.
163 */
164 370 static inline void * __attribute__((used)) sxmmap_align(size_t size) {
165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 370 times.
370 assert((size % (2 * 1024 * 1024)) == 0);
166 370 char *mem = NULL;
167 #ifdef CVMFS_SUPPRESS_ASSERTS
168 do {
169 #endif
170 370 mem = reinterpret_cast<char *>(sxmmap(2 * size));
171 #ifdef CVMFS_SUPPRESS_ASSERTS
172 } while (mem == MAP_FAILED);
173 #endif
174
175 370 uintptr_t head = size - (uintptr_t(mem) % size);
176 370 sxunmap(mem, head);
177 370 mem += head;
178 370 uintptr_t tail = size - head;
179
2/2
✓ Branch 0 taken 318 times.
✓ Branch 1 taken 52 times.
370 if (tail > 0)
180 318 sxunmap(mem + size, tail);
181 370 return mem;
182 }
183
184
185 #ifdef CVMFS_NAMESPACE_GUARD
186 } // namespace CVMFS_NAMESPACE_GUARD
187 #endif
188
189 #endif // CVMFS_UTIL_SMALLOC_H_
190