| 245 | */ |
| 246 | |
| 247 | static void * |
| 248 | zstd_mempool_alloc(struct zstd_pool *zstd_mempool, size_t size) |
| 249 | { |
| 250 | struct zstd_pool *pool; |
| 251 | struct zstd_kmem *mem = NULL; |
| 252 | |
| 253 | if (!zstd_mempool) { |
| 254 | return (NULL); |
| 255 | } |
| 256 | |
| 257 | /* Seek for preallocated memory slot and free obsolete slots */ |
| 258 | for (int i = 0; i < ZSTD_POOL_MAX; i++) { |
| 259 | pool = &zstd_mempool[i]; |
| 260 | /* |
| 261 | * This lock is simply a marker for a pool object beeing in use. |
| 262 | * If it's already hold, it will be skipped. |
| 263 | * |
| 264 | * We need to create it before checking it to avoid race |
| 265 | * conditions caused by running in a threaded context. |
| 266 | * |
| 267 | * The lock is later released by zstd_mempool_free. |
| 268 | */ |
| 269 | if (mutex_tryenter(&pool->barrier)) { |
| 270 | /* |
| 271 | * Check if objects fits the size, if so we take it and |
| 272 | * update the timestamp. |
| 273 | */ |
| 274 | if (pool->mem && size <= pool->size) { |
| 275 | pool->timeout = gethrestime_sec() + |
| 276 | ZSTD_POOL_TIMEOUT; |
| 277 | mem = pool->mem; |
| 278 | return (mem); |
| 279 | } |
| 280 | mutex_exit(&pool->barrier); |
| 281 | } |
| 282 | } |
| 283 | |
| 284 | /* |
| 285 | * If no preallocated slot was found, try to fill in a new one. |
| 286 | * |
| 287 | * We run a similar algorithm twice here to avoid pool fragmentation. |
| 288 | * The first one may generate holes in the list if objects get released. |
| 289 | * We always make sure that these holes get filled instead of adding new |
| 290 | * allocations constantly at the end. |
| 291 | */ |
| 292 | for (int i = 0; i < ZSTD_POOL_MAX; i++) { |
| 293 | pool = &zstd_mempool[i]; |
| 294 | if (mutex_tryenter(&pool->barrier)) { |
| 295 | /* Object is free, try to allocate new one */ |
| 296 | if (!pool->mem) { |
| 297 | mem = vmem_alloc(size, KM_SLEEP); |
| 298 | if (mem) { |
| 299 | ZSTDSTAT_ADD(zstd_stat_buffers, 1); |
| 300 | ZSTDSTAT_ADD(zstd_stat_size, size); |
| 301 | pool->mem = mem; |
| 302 | pool->size = size; |
| 303 | /* Keep track for later release */ |
| 304 | mem->pool = pool; |
no test coverage detected