summaryrefslogtreecommitdiffstats
path: root/vespamalloc/src/vespamalloc/malloc/overload.h
blob: 7d9c2b9c72ee2a6748a3652fb16531edb369dca1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#pragma once

#include <dlfcn.h>
#include <errno.h>
#include <new>
#include <cstdlib>
#include <malloc.h>

class CreateAllocator
{
public:
    CreateAllocator() : _initialized(0x192A3B4C) {
        vespamalloc::createAllocator();
    }
private:
#ifdef __clang__
    [[maybe_unused]]
#endif
    unsigned _initialized;
};

static CreateAllocator _CreateAllocator __attribute__ ((init_priority (543)));

void* operator new(std::size_t sz)
{
    void * ptr(vespamalloc::createAllocator()->malloc(sz));
    if (ptr == nullptr) {
        throw std::bad_alloc();
    }
    return ptr;
}

void* operator new[](std::size_t sz)
{
    return ::operator new(sz);
}

void* operator new(std::size_t sz, const std::nothrow_t&) noexcept {
    return vespamalloc::_GmemP->malloc(sz);
}
void* operator new[](std::size_t sz, const std::nothrow_t&) noexcept {
    return vespamalloc::_GmemP->malloc(sz);
}

void operator delete(void* ptr) noexcept {
    if (ptr) { vespamalloc::_GmemP->free(ptr); }
}
void operator delete[](void* ptr) noexcept {
    if (ptr) { vespamalloc::_GmemP->free(ptr); }
}
void operator delete(void* ptr, const std::nothrow_t&) noexcept {
    if (ptr) { vespamalloc::_GmemP->free(ptr); }
}
void operator delete[](void* ptr, const std::nothrow_t&) noexcept {
    if (ptr) { vespamalloc::_GmemP->free(ptr); }
}
void operator delete(void* ptr, std::size_t sz) noexcept {
    if (ptr) { vespamalloc::_GmemP->free(ptr, sz); }
}
void operator delete[](void* ptr, std::size_t sz) noexcept {
    if (ptr) { vespamalloc::_GmemP->free(ptr, sz); }
}
void operator delete(void* ptr, std::size_t sz, const std::nothrow_t&) noexcept {
    if (ptr) { vespamalloc::_GmemP->free(ptr, sz); }
}
void operator delete[](void* ptr, std::size_t sz, const std::nothrow_t&) noexcept {
    if (ptr) { vespamalloc::_GmemP->free(ptr, sz); }
}

/*
 * Below are overloads taking alignment into account too.
 * Due to allocation being power of 2 up to huge page size (2M)
 * alignment will always be satisfied. size will always be larger or equal to alignment.
 */
void* operator new(std::size_t sz, std::align_val_t alignment) {
    return vespamalloc::_GmemP->malloc(sz, alignment);
}
void* operator new(std::size_t sz, std::align_val_t alignment, const std::nothrow_t&) noexcept {
    return vespamalloc::_GmemP->malloc(sz, alignment);
}
void operator delete(void* ptr , std::align_val_t) noexcept {
    return vespamalloc::_GmemP->free(ptr);
}
void operator delete(void* ptr, std::align_val_t, const std::nothrow_t&) noexcept {
    return vespamalloc::_GmemP->free(ptr);
}
void* operator new[](std::size_t sz, std::align_val_t alignment) {
    return vespamalloc::_GmemP->malloc(sz, alignment);
}
void* operator new[](std::size_t sz, std::align_val_t alignment, const std::nothrow_t&) noexcept {
    return vespamalloc::_GmemP->malloc(sz, alignment);
}
void operator delete[](void* ptr, std::align_val_t) noexcept {
    return vespamalloc::_GmemP->free(ptr);
}
void operator delete[](void* ptr, std::align_val_t, const std::nothrow_t&) noexcept {
    return vespamalloc::_GmemP->free(ptr);
}
void operator delete(void* ptr, std::size_t sz, std::align_val_t alignment) noexcept {
    return vespamalloc::_GmemP->free(ptr, sz, alignment);
}
void operator delete[](void* ptr, std::size_t sz, std::align_val_t alignment) noexcept {
    return vespamalloc::_GmemP->free(ptr, sz, alignment);
}

extern "C" {

#if __GLIBC_PREREQ(2, 33)
struct mallinfo2 mallinfo2() __THROW __attribute__((visibility ("default")));
struct mallinfo2 mallinfo2() __THROW {
    struct mallinfo2 info;
    info.arena = vespamalloc::_GmemP->dataSegment().dataSize();
    info.ordblks = 0;
    info.smblks = 0;
    info.hblks = 0;
    info.hblkhd = 0;
    info.usmblks = 0;
    info.fsmblks = 0;
    info.uordblks = 0;
    info.fordblks = 0;
    info.keepcost = 0;
    return info;
}
#else
struct mallinfo mallinfo() __THROW __attribute__((visibility ("default")));
struct mallinfo mallinfo() __THROW {
    struct mallinfo info;
    info.arena = (vespamalloc::_GmemP->dataSegment().dataSize() >> 20); // Note reporting in 1M blocks
    info.ordblks = 0;
    info.smblks = 0;
    info.hblks = 0;
    info.hblkhd = 0;
    info.usmblks = 0;
    info.fsmblks = 0;
    info.uordblks = 0;
    info.fordblks = 0;
    info.keepcost = 0;
    return info;
}
#endif

int mallopt(int param, int value) throw() __attribute((visibility("default")));
int mallopt(int param, int value) throw() {
    return vespamalloc::createAllocator()->mallopt(param, value);
}

void * malloc(size_t sz) __attribute((visibility("default")));
void * malloc(size_t sz) {
    return vespamalloc::createAllocator()->malloc(sz);
}

void * calloc(size_t nelem, size_t esz) __attribute((visibility("default")));
void * calloc(size_t nelem, size_t esz)
{
    return vespamalloc::createAllocator()->calloc(nelem, esz);
}

void * realloc(void * ptr, size_t sz) __attribute((visibility("default")));
void * realloc(void * ptr, size_t sz)
{
    return vespamalloc::createAllocator()->realloc(ptr, sz);
}

void * reallocarray(void * ptr, size_t nemb, size_t elemSize) __THROW __attribute__((visibility ("default")));
void * reallocarray(void * ptr, size_t nemb, size_t elemSize) __THROW
{
    size_t sz = nemb * elemSize;
    if (nemb != 0 && (sz/nemb != elemSize)) {
        errno = ENOMEM;
        return nullptr;
    }
    return vespamalloc::createAllocator()->realloc(ptr, sz);
}

void* memalign(size_t align, size_t sz) __THROW __attribute__((visibility ("default")));
void* memalign(size_t align, size_t sz) __THROW
{
    void *ptr(nullptr);
    size_t align_1(align - 1);
    if ((align & (align_1)) == 0) {
        ptr = vespamalloc::_GmemP->malloc(vespamalloc::_GmemP->getMinSizeForAlignment(align, sz));
        ptr = (void *) ((size_t(ptr) + align_1) & ~align_1);
    }
    return ptr;
}

int posix_memalign(void** ptr, size_t align, size_t sz) __THROW __nonnull((1)) __attribute__((visibility ("default")));
int posix_memalign(void** ptr, size_t align, size_t sz) __THROW
{
    int retval(0);
    if (((align % sizeof(void*)) != 0) ||
        ((align & (align - 1)) != 0) ||
        (align == 0)) {
        retval = EINVAL;
    } else {
        void* result = memalign(align, sz);
        if (result) {
            *ptr = result;
        } else {
            retval = ENOMEM;
        }
    }
    return retval;
}

void *valloc(size_t size) __THROW __attribute__((visibility ("default")));
void *valloc(size_t size) __THROW
{
  return memalign(sysconf(_SC_PAGESIZE),size);
}

void free(void * ptr) __attribute__((visibility ("default")));
void free(void * ptr) {
    if (ptr) { vespamalloc::_GmemP->free(ptr); }
}

size_t malloc_usable_size(void *) __THROW __attribute__((visibility ("default")));
size_t malloc_usable_size (void * ptr) __THROW  {
    return (ptr) ? vespamalloc::_GmemP->usable_size(ptr) : 0;
}

#define ALIAS(x) __attribute__ ((weak, alias (x), visibility ("default")))
#ifdef __clang__
void* __libc_malloc(size_t sz)                       __THROW __attribute__((malloc, alloc_size(1))) ALIAS("malloc");
void* __libc_realloc(void* ptr, size_t sz)           __THROW __attribute__((malloc, alloc_size(2))) ALIAS("realloc");
void* __libc_reallocarray(void* ptr, size_t nemb, size_t sz) __THROW __attribute__((malloc, alloc_size(2,3))) ALIAS("reallocarray");
void* __libc_calloc(size_t n, size_t sz)             __THROW __attribute__((malloc, alloc_size(1,2))) ALIAS("calloc");
void cfree(void *)                                   __THROW ALIAS("free");
void  __libc_free(void* ptr)                         __THROW ALIAS("free");
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wignored-attributes"
void  __libc_cfree(void* ptr)                        __THROW ALIAS("cfree");
#pragma clang diagnostic pop
#else
void* __libc_malloc(size_t sz)                       __THROW __attribute__((leaf, malloc, alloc_size(1))) ALIAS("malloc");
void* __libc_realloc(void* ptr, size_t sz)           __THROW __attribute__((leaf, malloc, alloc_size(2))) ALIAS("realloc");
void* __libc_reallocarray(void* ptr, size_t nemb, size_t sz) __THROW __attribute__((leaf, malloc, alloc_size(2,3))) ALIAS("reallocarray");
void* __libc_calloc(size_t n, size_t sz)             __THROW __attribute__((leaf, malloc, alloc_size(1,2))) ALIAS("calloc");
void cfree(void *)                                   __THROW __attribute__((leaf)) ALIAS("free");
void  __libc_free(void* ptr)                         __THROW __attribute__((leaf)) ALIAS("free");
void  __libc_cfree(void* ptr)                        __THROW __attribute__((leaf)) ALIAS("cfree");
#endif
size_t  __libc_malloc_usable_size(void *ptr)         __THROW  ALIAS("malloc_usable_size");
#if __GLIBC_PREREQ(2, 34)
void* __libc_memalign(size_t align, size_t s)        __THROW __attribute__((leaf, malloc, alloc_align(1), alloc_size(2))) ALIAS("memalign");
#else
void* __libc_memalign(size_t align, size_t s)        __THROW __attribute__((leaf, malloc, alloc_size(2))) ALIAS("memalign");
#endif
int   __posix_memalign(void** r, size_t a, size_t s) __THROW __nonnull((1)) ALIAS("posix_memalign");
#if __GLIBC_PREREQ(2, 33)
struct mallinfo2 __libc_mallinfo2()                  __THROW  ALIAS("mallinfo2");
#else
struct mallinfo __libc_mallinfo()                    __THROW  ALIAS("mallinfo");
#endif
#undef ALIAS

}