| 156 | } |
| 157 | |
| 158 | void *DefaultMemoryManager::alloc(bool user_lock, const unsigned ndims, |
| 159 | dim_t *dims, const unsigned element_size) { |
| 160 | size_t bytes = element_size; |
| 161 | for (unsigned i = 0; i < ndims; ++i) { bytes *= dims[i]; } |
| 162 | |
| 163 | void *ptr = nullptr; |
| 164 | size_t alloc_bytes = this->debug_mode |
| 165 | ? bytes |
| 166 | : (divup(bytes, mem_step_size) * mem_step_size); |
| 167 | |
| 168 | if (bytes > 0) { |
| 169 | memory_info ¤t = this->getCurrentMemoryInfo(); |
| 170 | locked_info info = {!user_lock, user_lock, alloc_bytes}; |
| 171 | |
| 172 | // There is no memory cache in debug mode |
| 173 | if (!this->debug_mode) { |
| 174 | // FIXME: Add better checks for garbage collection |
| 175 | // Perhaps look at total memory available as a metric |
| 176 | if (current.lock_bytes >= current.max_bytes || |
| 177 | current.total_buffers >= this->max_buffers) { |
| 178 | AF_TRACE( |
| 179 | "Running GC: current.lock_bytes({}) >= " |
| 180 | "current.max_bytes({}) || current.total_buffers({}) >= " |
| 181 | "this->max_buffers({})\n", |
| 182 | current.lock_bytes, current.max_bytes, |
| 183 | current.total_buffers, this->max_buffers); |
| 184 | |
| 185 | this->signalMemoryCleanup(); |
| 186 | } |
| 187 | |
| 188 | lock_guard_t lock(this->memory_mutex); |
| 189 | auto free_buffer_iter = current.free_map.find(alloc_bytes); |
| 190 | if (free_buffer_iter != current.free_map.end() && |
| 191 | !free_buffer_iter->second.empty()) { |
| 192 | // Delete existing buffer info and underlying event |
| 193 | // Set to existing in from free map |
| 194 | vector<void *> &free_buffer_vector = free_buffer_iter->second; |
| 195 | ptr = free_buffer_vector.back(); |
| 196 | free_buffer_vector.pop_back(); |
| 197 | current.locked_map[ptr] = info; |
| 198 | current.lock_bytes += alloc_bytes; |
| 199 | current.lock_buffers++; |
| 200 | } |
| 201 | } |
| 202 | |
| 203 | // Only comes here if buffer size not found or in debug mode |
| 204 | if (ptr == nullptr) { |
| 205 | // Perform garbage collection if memory can not be allocated |
| 206 | try { |
| 207 | ptr = this->nativeAlloc(alloc_bytes); |
| 208 | } catch (const AfError &ex) { |
| 209 | // If out of memory, run garbage collect and try again |
| 210 | if (ex.getError() != AF_ERR_NO_MEM) { throw; } |
| 211 | this->signalMemoryCleanup(); |
| 212 | ptr = this->nativeAlloc(alloc_bytes); |
| 213 | } |
| 214 | lock_guard_t lock(this->memory_mutex); |
| 215 | // Increment these two only when it succeeds to come here. |
no test coverage detected