1 /* -*- mesa-c++ -*-
2 * Copyright 2022 Collabora LTD
3 * Author: Gert Wollny <[email protected]>
4 * SPDX-License-Identifier: MIT
5 */
6
7 #include "sfn_memorypool.h"
8
9 #include <cassert>
10 #include <iostream>
11
12 #ifdef HAVE_MEMORY_RESOURCE
13 #include <memory_resource>
14 #else
15 #include <list>
16 #include <stdlib.h>
17 #endif
18
19 namespace r600 {
20
21 #ifndef HAVE_MEMORY_RESOURCE
22 /* Fallback memory resource if the C++17 memory resource is not
23 * available
24 */
25 struct MemoryBacking {
26 ~MemoryBacking();
27 void *allocate(size_t size);
28 void *allocate(size_t size, size_t align);
29 std::list<void *> m_data;
30 };
31 #endif
32
33 struct MemoryPoolImpl {
34 public:
35 MemoryPoolImpl();
36 ~MemoryPoolImpl();
37 #ifdef HAVE_MEMORY_RESOURCE
38 using MemoryBacking = ::std::pmr::monotonic_buffer_resource;
39 #endif
40 MemoryBacking *pool;
41 };
42
MemoryPool()43 MemoryPool::MemoryPool() noexcept:
44 impl(nullptr)
45 {
46 }
47
48 MemoryPool&
instance()49 MemoryPool::instance()
50 {
51 static thread_local MemoryPool me;
52 return me;
53 }
54
55 void
free()56 MemoryPool::free()
57 {
58 delete impl;
59 impl = nullptr;
60 }
61
62 void
initialize()63 MemoryPool::initialize()
64 {
65 if (!impl)
66 impl = new MemoryPoolImpl();
67 }
68
69 void *
allocate(size_t size)70 MemoryPool::allocate(size_t size)
71 {
72 assert(impl);
73 return impl->pool->allocate(size);
74 }
75
76 void *
allocate(size_t size,size_t align)77 MemoryPool::allocate(size_t size, size_t align)
78 {
79 assert(impl);
80 return impl->pool->allocate(size, align);
81 }
82
83 void
release_all()84 MemoryPool::release_all()
85 {
86 instance().free();
87 }
88
89 void
init_pool()90 init_pool()
91 {
92 MemoryPool::instance().initialize();
93 }
94
95 void
release_pool()96 release_pool()
97 {
98 MemoryPool::release_all();
99 }
100
101 void *
operator new(size_t size)102 Allocate::operator new(size_t size)
103 {
104 return MemoryPool::instance().allocate(size);
105 }
106
107 void
operator delete(void * p,size_t size)108 Allocate::operator delete(void *p, size_t size)
109 {
110 // MemoryPool::instance().deallocate(p, size);
111 }
112
MemoryPoolImpl()113 MemoryPoolImpl::MemoryPoolImpl() { pool = new MemoryBacking(); }
114
~MemoryPoolImpl()115 MemoryPoolImpl::~MemoryPoolImpl() { delete pool; }
116
117 #ifndef HAVE_MEMORY_RESOURCE
~MemoryBacking()118 MemoryBacking::~MemoryBacking()
119 {
120 for (auto p : m_data)
121 free(p);
122 }
123
124 void *
allocate(size_t size)125 MemoryBacking::allocate(size_t size)
126 {
127 void *retval = malloc(size);
128 m_data.push_back(retval);
129 return retval;
130 }
131
132 void *
allocate(size_t size,size_t align)133 MemoryBacking::allocate(size_t size, size_t align)
134 {
135 void *retval = aligned_alloc(align, size);
136 m_data.push_back(retval);
137 return retval;
138 }
139
140 #endif
141
142 } // namespace r600
143