File: allocator.h

package info (click to toggle)
aws-crt-python 0.20.4%2Bdfsg-1~bpo12%2B1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-backports
  • size: 72,656 kB
  • sloc: ansic: 381,805; python: 23,008; makefile: 6,251; sh: 4,536; cpp: 699; ruby: 208; java: 77; perl: 73; javascript: 46; xml: 11
file content (234 lines) | stat: -rw-r--r-- 9,447 bytes parent folder | download | duplicates (2)
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
#ifndef AWS_COMMON_ALLOCATOR_H
#define AWS_COMMON_ALLOCATOR_H
/**
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

#include <aws/common/macros.h>
#include <aws/common/stdbool.h>
#include <aws/common/stdint.h>

AWS_PUSH_SANE_WARNING_LEVEL
AWS_EXTERN_C_BEGIN

/*
 * Quick guide to allocators:
 *  CRT offers several flavours of allocators:
 * - default: basic allocator that invokes system one directly.
 * - aligned: basic allocator that aligns small allocations on 8 byte
 *   boundary and big buffers on 32/64 byte (system dependent) boundary.
 *   Aligned mem can improve perf on some operations, like memcpy or hashes.
 *   Depending on a system, can result in higher peak memory count in heavy
 *   acquire/free scenarios (ex. s3), due to memory fragmentation related to how
 *   aligned allocators work (over allocate, find aligned offset, release extra memory)
 * - wrapped_cf: wraps MacOS's Security Framework allocator.
 * - mem_tracer: wraps any allocator and provides tracing functionality to allocations
 * - small_block_allocator: pools smaller allocations into preallocated buckets.
 *   Not actively maintained. Avoid if possible.
 */

/* Allocator structure. An instance of this will be passed around for anything needing memory allocation */
struct aws_allocator {
    void *(*mem_acquire)(struct aws_allocator *allocator, size_t size);
    void (*mem_release)(struct aws_allocator *allocator, void *ptr);
    /* Optional method; if not supported, this pointer must be NULL */
    void *(*mem_realloc)(struct aws_allocator *allocator, void *oldptr, size_t oldsize, size_t newsize);
    /* Optional method; if not supported, this pointer must be NULL */
    void *(*mem_calloc)(struct aws_allocator *allocator, size_t num, size_t size);
    void *impl;
};

/**
 * Inexpensive (constant time) check of data-structure invariants.
 */
AWS_COMMON_API
bool aws_allocator_is_valid(const struct aws_allocator *alloc);

AWS_COMMON_API
struct aws_allocator *aws_default_allocator(void);

/*
 * Allocator that align small allocations on 8 byte boundary and big allocations
 * on 32/64 byte boundary.
 */
AWS_COMMON_API
struct aws_allocator *aws_aligned_allocator(void);

#ifdef __MACH__
/* Avoid pulling in CoreFoundation headers in a header file. */
struct __CFAllocator; /* NOLINT(bugprone-reserved-identifier) */
typedef const struct __CFAllocator *CFAllocatorRef;

/**
 * Wraps a CFAllocator around aws_allocator. For Mac only. Use this anytime you need a CFAllocatorRef for interacting
 * with Apple Frameworks. Unfortunately, it allocates memory so we can't make it static file scope, be sure to call
 * aws_wrapped_cf_allocator_destroy when finished.
 */
AWS_COMMON_API
CFAllocatorRef aws_wrapped_cf_allocator_new(struct aws_allocator *allocator);

/**
 * Cleans up any resources alloced in aws_wrapped_cf_allocator_new.
 */
AWS_COMMON_API
void aws_wrapped_cf_allocator_destroy(CFAllocatorRef allocator);
#endif

/**
 * Returns at least `size` of memory ready for usage. In versions v0.6.8 and prior, this function was allowed to return
 * NULL. In later versions, if allocator->mem_acquire() returns NULL, this function will assert and exit. To handle
 * conditions where OOM is not a fatal error, allocator->mem_acquire() is responsible for finding/reclaiming/running a
 * GC etc...before returning.
 */
AWS_COMMON_API
void *aws_mem_acquire(struct aws_allocator *allocator, size_t size);

/**
 * Allocates a block of memory for an array of num elements, each of them size bytes long, and initializes all its bits
 * to zero. In versions v0.6.8 and prior, this function was allowed to return NULL.
 * In later versions, if allocator->mem_calloc() returns NULL, this function will assert and exit. To handle
 * conditions where OOM is not a fatal error, allocator->mem_calloc() is responsible for finding/reclaiming/running a
 * GC etc...before returning.
 */
AWS_COMMON_API
void *aws_mem_calloc(struct aws_allocator *allocator, size_t num, size_t size);

/**
 * Allocates many chunks of bytes into a single block. Expects to be called with alternating void ** (dest), size_t
 * (size). The first void ** will be set to the root of the allocation. Alignment is assumed to be sizeof(intmax_t).
 *
 * This is useful for allocating structs using the pimpl pattern, as you may allocate the public object and impl object
 * in the same contiguous block of memory.
 *
 * Returns a pointer to the allocation.
 *
 * In versions v0.6.8 and prior, this function was allowed to return
 * NULL. In later versions, if allocator->mem_acquire() returns NULL, this function will assert and exit. To handle
 * conditions where OOM is not a fatal error, allocator->mem_acquire() is responsible for finding/reclaiming/running a
 * GC etc...before returning.
 */
AWS_COMMON_API
void *aws_mem_acquire_many(struct aws_allocator *allocator, size_t count, ...);

/**
 * Releases ptr back to whatever allocated it.
 * Nothing happens if ptr is NULL.
 */
AWS_COMMON_API
void aws_mem_release(struct aws_allocator *allocator, void *ptr);

/**
 * Attempts to adjust the size of the pointed-to memory buffer from oldsize to
 * newsize. The pointer (*ptr) may be changed if the memory needs to be
 * reallocated.
 *
 * In versions v0.6.8 and prior, this function was allowed to return
 * NULL. In later versions, if allocator->mem_realloc() returns NULL, this function will assert and exit. To handle
 * conditions where OOM is not a fatal error, allocator->mem_realloc() is responsible for finding/reclaiming/running a
 * GC etc...before returning.
 */
AWS_COMMON_API
int aws_mem_realloc(struct aws_allocator *allocator, void **ptr, size_t oldsize, size_t newsize);
/*
 * Maintainer note: The above function doesn't return the pointer (as with
 * standard C realloc) as this pattern becomes error-prone when OOMs occur.
 * In particular, we want to avoid losing the old pointer when an OOM condition
 * occurs, so we prefer to take the old pointer as an in/out reference argument
 * that we can leave unchanged on failure.
 */

enum aws_mem_trace_level {
    AWS_MEMTRACE_NONE = 0,   /* no tracing */
    AWS_MEMTRACE_BYTES = 1,  /* just track allocation sizes and total allocated */
    AWS_MEMTRACE_STACKS = 2, /* capture callstacks for each allocation */
};

/*
 * Wraps an allocator and tracks all external allocations. If aws_mem_trace_dump() is called
 * and there are still allocations active, they will be reported to the aws_logger at TRACE level.
 * allocator - The allocator to wrap
 * deprecated - Deprecated arg, ignored.
 * level - The level to track allocations at
 * frames_per_stack is how many frames to store per callstack if AWS_MEMTRACE_STACKS is in use,
 * otherwise it is ignored. 8 tends to be a pretty good number balancing storage space vs useful stacks.
 * Returns the tracer allocator, which should be used for all allocations that should be tracked.
 */
AWS_COMMON_API
struct aws_allocator *aws_mem_tracer_new(
    struct aws_allocator *allocator,
    struct aws_allocator *deprecated,
    enum aws_mem_trace_level level,
    size_t frames_per_stack);

/*
 * Unwraps the traced allocator and cleans up the tracer.
 * Returns the original allocator
 */
AWS_COMMON_API
struct aws_allocator *aws_mem_tracer_destroy(struct aws_allocator *trace_allocator);

/*
 * If there are outstanding allocations, dumps them to log, along with any information gathered
 * based on the trace level set when aws_mem_trace() was called.
 * Should be passed the tracer allocator returned from aws_mem_trace().
 */
AWS_COMMON_API
void aws_mem_tracer_dump(struct aws_allocator *trace_allocator);

/*
 * Returns the current number of bytes in outstanding allocations
 */
AWS_COMMON_API
size_t aws_mem_tracer_bytes(struct aws_allocator *trace_allocator);

/*
 * Returns the current number of outstanding allocations
 */
AWS_COMMON_API
size_t aws_mem_tracer_count(struct aws_allocator *trace_allocator);

/*
 * Creates a new Small Block Allocator which fronts the supplied parent allocator. The SBA will intercept
 * and handle small allocs, and will forward anything larger to the parent allocator.
 * If multi_threaded is true, the internal allocator will protect its internal data structures with a mutex
 */
AWS_COMMON_API
struct aws_allocator *aws_small_block_allocator_new(struct aws_allocator *allocator, bool multi_threaded);

/*
 * Destroys a Small Block Allocator instance and frees its memory to the parent allocator. The parent
 * allocator will otherwise be unaffected.
 */
AWS_COMMON_API
void aws_small_block_allocator_destroy(struct aws_allocator *sba_allocator);

/*
 * Returns the number of bytes currently active in the SBA
 */
AWS_COMMON_API
size_t aws_small_block_allocator_bytes_active(struct aws_allocator *sba_allocator);

/*
 * Returns the number of bytes reserved in pages/bins inside the SBA, e.g. the
 * current system memory used by the SBA
 */
AWS_COMMON_API
size_t aws_small_block_allocator_bytes_reserved(struct aws_allocator *sba_allocator);

/*
 * Returns the page size that the SBA is using
 */
AWS_COMMON_API
size_t aws_small_block_allocator_page_size(struct aws_allocator *sba_allocator);

/*
 * Returns the amount of memory in each page available to user allocations
 */
AWS_COMMON_API
size_t aws_small_block_allocator_page_size_available(struct aws_allocator *sba_allocator);

AWS_EXTERN_C_END
AWS_POP_SANE_WARNING_LEVEL

#endif /* AWS_COMMON_ALLOCATOR_H */