1#include <stddef.h>
2#include <stdint.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6
7#include "allocator.h"
8
9static AllocatorStats stats = {};
10
11static void* _allocate(unsigned nbytes, bool clean)
12{
13 void* result;
14 if (clean) {
15 result = calloc(1, nbytes);
16 } else {
17 result = malloc(nbytes);
18 }
19 if (result) {
20 atomic_fetch_add(&stats.blocks_allocated, 1);
21 }
22 return result;
23}
24
25static void _release(void** addr_ptr, unsigned nbytes)
26{
27 void* addr = *addr_ptr;
28 if (addr) {
29 free(addr);
30 *addr_ptr = nullptr;
31 atomic_fetch_sub(&stats.blocks_allocated, 1);
32 }
33}
34
35static bool _reallocate(void** addr_ptr, unsigned old_nbytes, unsigned new_nbytes, bool clean, bool* addr_changed)
36{
37 if (old_nbytes == new_nbytes) {
38 goto success_same_addr;
39 }
40
41 void* addr = *addr_ptr;
42
43 // shall we allocate new addr?
44 if (addr == nullptr) {
45 if (old_nbytes != 0) {
46 goto error;
47 }
48 addr = _allocate(new_nbytes, clean);
49 if (!addr) {
50 goto error;
51 }
52 *addr_ptr = addr;
53 goto success_changed_addr;
54 }
55
56 void* new_block = realloc(addr, new_nbytes);
57 if (!new_block) {
58 goto error;
59 }
60 *addr_ptr = new_block;
61 if (addr_changed) { *addr_changed = new_block != addr; }
62 if (clean && old_nbytes < new_nbytes) {
63 memset(((uint8_t*) new_block) + old_nbytes, 0, new_nbytes - old_nbytes);
64 }
65 return true;
66
67success_changed_addr:
68 if (addr_changed) { *addr_changed = true; }
69 return true;
70
71success_same_addr:
72 if (addr_changed) { *addr_changed = false; }
73 return true;
74
75error:
76 if (addr_changed) { *addr_changed = false; }
77 return false;
78}
79
80static void _dump()
81{
82 fprintf(stderr, "Stdlib allocator: dump is not implemented\n");
83}
84
85Allocator stdlib_allocator = {
86 .init = nullptr,
87 .allocate = _allocate,
88 .reallocate = _reallocate,
89 .release = _release,
90 .dump = _dump,
91 .trace = false,
92 .verbose = false,
93 .stats = &stats
94};