1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/env.h" 7 #include "ocf_env.h" 8 9 #include "mpool.h" 10 11 struct env_mpool { 12 env_allocator *allocator[env_mpool_max]; 13 /* Handles to memory pools */ 14 15 uint32_t hdr_size; 16 /* Data header size (constant allocation part) */ 17 18 uint32_t elem_size; 19 /* Per element size increment (variable allocation part) */ 20 21 uint32_t mpool_max; 22 /* Max mpool allocation order */ 23 24 bool fallback; 25 /* Fallback to vmalloc */ 26 }; 27 28 struct env_mpool *env_mpool_create(uint32_t hdr_size, uint32_t elem_size, 29 int flags, int mpool_max, bool fallback, 30 const uint32_t limits[env_mpool_max], 31 const char *name_prefix, bool zero) 32 { 33 int i; 34 char name[OCF_ALLOCATOR_NAME_MAX] = {}; 35 int ret; 36 int size; 37 38 struct env_mpool *mpool = env_zalloc(sizeof(struct env_mpool), ENV_MEM_NOIO); 39 if (!mpool) { 40 return NULL; 41 } 42 43 mpool->hdr_size = hdr_size; 44 mpool->elem_size = elem_size; 45 mpool->mpool_max = mpool_max; 46 mpool->fallback = fallback; 47 48 for (i = 0; i < min(env_mpool_max, mpool_max + 1); i++) { 49 ret = snprintf(name, sizeof(name), "%s_%u", name_prefix, (1 << i)); 50 if (ret < 0 || ret >= (int)sizeof(name)) { 51 goto err; 52 } 53 54 size = hdr_size + (elem_size * (1 << i)); 55 56 mpool->allocator[i] = env_allocator_create_extended(size, name, 57 limits ? limits[i] : -1, zero); 58 59 if (!mpool->allocator[i]) { 60 goto err; 61 } 62 } 63 64 return mpool; 65 66 err: 67 env_mpool_destroy(mpool); 68 return NULL; 69 } 70 71 void 72 env_mpool_destroy(struct env_mpool *mpool) 73 { 74 if (mpool) { 75 int i; 76 77 for (i = 0; i < env_mpool_max; i++) { 78 if (mpool->allocator[i]) { 79 env_allocator_destroy(mpool->allocator[i]); 80 } 81 } 82 83 env_free(mpool); 84 } 85 } 86 87 static env_allocator * 88 env_mpool_get_allocator(struct env_mpool *mpool, 89 uint32_t count) 90 { 91 unsigned int idx; 92 93 if (unlikely(count == 0)) { 94 return mpool->allocator[env_mpool_1]; 95 } 96 97 idx = 31 - __builtin_clz(count); 98 99 if (__builtin_ffs(count) <= idx) { 100 idx++; 101 } 102 103 if (idx >= env_mpool_max || idx > mpool->mpool_max) { 104 return NULL; 105 } 106 107 return mpool->allocator[idx]; 108 } 109 110 void * 111 env_mpool_new(struct env_mpool *mpool, uint32_t count) 112 { 113 void *items = NULL; 114 env_allocator *allocator; 115 size_t size = mpool->hdr_size + (mpool->elem_size * count); 116 117 allocator = env_mpool_get_allocator(mpool, count); 118 119 if (allocator) { 120 items = env_allocator_new(allocator); 121 } else if (mpool->fallback) { 122 items = env_vmalloc(size); 123 } 124 125 return items; 126 } 127 128 bool 129 env_mpool_del(struct env_mpool *mpool, 130 void *items, uint32_t count) 131 { 132 env_allocator *allocator; 133 134 allocator = env_mpool_get_allocator(mpool, count); 135 136 if (allocator) { 137 env_allocator_del(allocator, items); 138 } else if (mpool->fallback) { 139 env_vfree(items); 140 } else { 141 return false; 142 } 143 144 return true; 145 } 146