1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/env.h" 35 #include "ocf_env.h" 36 37 #include "mpool.h" 38 39 struct env_mpool { 40 env_allocator *allocator[env_mpool_max]; 41 /* Handles to memory pools */ 42 43 uint32_t hdr_size; 44 /* Data header size (constant allocation part) */ 45 46 uint32_t elem_size; 47 /* Per element size increment (variable allocation part) */ 48 49 uint32_t mpool_max; 50 /* Max mpool allocation order */ 51 52 bool fallback; 53 /* Fallback to vmalloc */ 54 }; 55 56 struct env_mpool *env_mpool_create(uint32_t hdr_size, uint32_t elem_size, 57 int flags, int mpool_max, bool fallback, 58 const uint32_t limits[env_mpool_max], 59 const char *name_prefix, bool zero) 60 { 61 int i; 62 char name[OCF_ALLOCATOR_NAME_MAX] = {}; 63 int ret; 64 int size; 65 66 struct env_mpool *mpool = env_zalloc(sizeof(struct env_mpool), ENV_MEM_NOIO); 67 if (!mpool) { 68 return NULL; 69 } 70 71 mpool->hdr_size = hdr_size; 72 mpool->elem_size = elem_size; 73 mpool->mpool_max = mpool_max; 74 mpool->fallback = fallback; 75 76 for (i = 0; i < min(env_mpool_max, mpool_max + 1); i++) { 77 ret = snprintf(name, sizeof(name), "%s_%u", name_prefix, (1 << i)); 78 if (ret < 0 || ret >= (int)sizeof(name)) { 79 goto err; 80 } 81 82 size = hdr_size + (elem_size * (1 << i)); 83 84 mpool->allocator[i] = env_allocator_create_extended(size, name, 85 limits ? limits[i] : -1, zero); 86 87 if (!mpool->allocator[i]) { 88 goto err; 89 } 90 } 91 92 return mpool; 93 94 err: 95 env_mpool_destroy(mpool); 96 return NULL; 97 } 98 99 void env_mpool_destroy(struct env_mpool *mpool) 100 { 101 if (mpool) { 102 int i; 103 104 for (i = 0; i < env_mpool_max; i++) { 105 if (mpool->allocator[i]) { 106 env_allocator_destroy(mpool->allocator[i]); 107 } 108 } 109 110 env_free(mpool); 111 } 112 } 113 114 static env_allocator *env_mpool_get_allocator(struct env_mpool *mpool, 115 uint32_t count) 116 { 117 unsigned int idx; 118 119 if (unlikely(count == 0)) { 120 return mpool->allocator[env_mpool_1]; 121 } 122 123 idx = 31 - __builtin_clz(count); 124 125 if (__builtin_ffs(count) <= idx) { 126 idx++; 127 } 128 129 if (idx >= env_mpool_max || idx > mpool->mpool_max) { 130 return NULL; 131 } 132 133 return mpool->allocator[idx]; 134 } 135 136 void *env_mpool_new(struct env_mpool *mpool, uint32_t count) 137 { 138 void *items = NULL; 139 env_allocator *allocator; 140 size_t size = mpool->hdr_size + (mpool->elem_size * count); 141 142 allocator = env_mpool_get_allocator(mpool, count); 143 144 if (allocator) { 145 items = env_allocator_new(allocator); 146 } else if (mpool->fallback) { 147 items = env_vmalloc(size); 148 } 149 150 return items; 151 } 152 153 bool env_mpool_del(struct env_mpool *mpool, 154 void *items, uint32_t count) 155 { 156 env_allocator *allocator; 157 158 allocator = env_mpool_get_allocator(mpool, count); 159 160 if (allocator) { 161 env_allocator_del(allocator, items); 162 } else if (mpool->fallback) { 163 env_vfree(items); 164 } else { 165 return false; 166 } 167 168 return true; 169 } 170