1 /* -*- mesa-c++ -*-
2 *
3 * Copyright (c) 2022 Collabora LTD
4 *
5 * Author: Gert Wollny <gert.wollny@collabora.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * on the rights to use, copy, modify, merge, publish, distribute, sub
11 * license, and/or sell copies of the Software, and to permit persons to whom
12 * the Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27 #include "sfn_memorypool.h"
28
29 #include <cassert>
30 #include <iostream>
31
32 #ifdef HAVE_MEMORY_RESOURCE
33 #include <memory_resource>
34 #else
35 #include <list>
36 #include <stdlib.h>
37 #endif
38
39 namespace r600 {
40
41 #ifndef HAVE_MEMORY_RESOURCE
42 /* Fallback memory resource if the C++17 memory resource is not
43 * available
44 */
45 struct MemoryBacking {
46 ~MemoryBacking();
47 void *allocate(size_t size);
48 void *allocate(size_t size, size_t align);
49 std::list<void *> m_data;
50 };
51 #endif
52
53 struct MemoryPoolImpl {
54 public:
55 MemoryPoolImpl();
56 ~MemoryPoolImpl();
57 #ifdef HAVE_MEMORY_RESOURCE
58 using MemoryBacking = ::std::pmr::monotonic_buffer_resource;
59 #endif
60 MemoryBacking *pool;
61 };
62
MemoryPool()63 MemoryPool::MemoryPool() noexcept:
64 impl(nullptr)
65 {
66 }
67
68 MemoryPool&
instance()69 MemoryPool::instance()
70 {
71 static thread_local MemoryPool me;
72 return me;
73 }
74
75 void
free()76 MemoryPool::free()
77 {
78 delete impl;
79 impl = nullptr;
80 }
81
82 void
initialize()83 MemoryPool::initialize()
84 {
85 if (!impl)
86 impl = new MemoryPoolImpl();
87 }
88
89 void *
allocate(size_t size)90 MemoryPool::allocate(size_t size)
91 {
92 assert(impl);
93 return impl->pool->allocate(size);
94 }
95
96 void *
allocate(size_t size,size_t align)97 MemoryPool::allocate(size_t size, size_t align)
98 {
99 assert(impl);
100 return impl->pool->allocate(size, align);
101 }
102
103 void
release_all()104 MemoryPool::release_all()
105 {
106 instance().free();
107 }
108
109 void
init_pool()110 init_pool()
111 {
112 MemoryPool::instance().initialize();
113 }
114
115 void
release_pool()116 release_pool()
117 {
118 MemoryPool::release_all();
119 }
120
121 void *
operator new(size_t size)122 Allocate::operator new(size_t size)
123 {
124 return MemoryPool::instance().allocate(size);
125 }
126
127 void
operator delete(void * p,size_t size)128 Allocate::operator delete(void *p, size_t size)
129 {
130 // MemoryPool::instance().deallocate(p, size);
131 }
132
MemoryPoolImpl()133 MemoryPoolImpl::MemoryPoolImpl() { pool = new MemoryBacking(); }
134
~MemoryPoolImpl()135 MemoryPoolImpl::~MemoryPoolImpl() { delete pool; }
136
137 #ifndef HAVE_MEMORY_RESOURCE
~MemoryBacking()138 MemoryBacking::~MemoryBacking()
139 {
140 for (auto p : m_data)
141 free(p);
142 }
143
144 void *
allocate(size_t size)145 MemoryBacking::allocate(size_t size)
146 {
147 void *retval = malloc(size);
148 m_data.push_back(retval);
149 return retval;
150 }
151
152 void *
allocate(size_t size,size_t align)153 MemoryBacking::allocate(size_t size, size_t align)
154 {
155 void *retval = aligned_alloc(align, size);
156 m_data.push_back(retval);
157 return retval;
158 }
159
160 #endif
161
162 } // namespace r600
163