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 #define MEMPOOL_SIZE 24 40 41 struct env_mpool { 42 env_allocator *allocator[env_mpool_max]; 43 /* Handles to memory pools */ 44 45 uint32_t hdr_size; 46 /* Data header size (constant allocation part) */ 47 48 uint32_t elem_size; 49 /* Per element size increment (variable allocation part) */ 50 51 uint32_t mpool_max; 52 /* Max mpool allocation order */ 53 54 bool fallback; 55 /* Fallback to vmalloc */ 56 }; 57 58 struct env_mpool *env_mpool_create(uint32_t hdr_size, uint32_t elem_size, 59 int flags, int mpool_max, bool fallback, 60 const uint32_t limits[env_mpool_max], 61 const char *name_perfix, bool zero) 62 { 63 int i; 64 char name[MEMPOOL_SIZE] = {}; 65 int ret; 66 int size; 67 68 struct env_mpool *mpool = env_zalloc(sizeof(struct env_mpool), ENV_MEM_NOIO); 69 if (!mpool) { 70 return NULL; 71 } 72 73 mpool->hdr_size = hdr_size; 74 mpool->elem_size = elem_size; 75 mpool->mpool_max = mpool_max; 76 mpool->fallback = fallback; 77 78 for (i = 0; i < min(env_mpool_max, mpool_max + 1); i++) { 79 ret = snprintf(name, sizeof(name), "%s_%u", name, (1 << i)); 80 if (ret < 0 || ret >= (int)sizeof(name)) { 81 goto err; 82 } 83 84 size = hdr_size + (elem_size * (1 << i)); 85 86 mpool->allocator[i] = env_allocator_create_extended(size, name, 87 limits ? limits[i] : -1, zero); 88 89 if (!mpool->allocator[i]) { 90 goto err; 91 } 92 } 93 94 return mpool; 95 96 err: 97 env_mpool_destroy(mpool); 98 return NULL; 99 } 100 101 void env_mpool_destroy(struct env_mpool *mpool) 102 { 103 if (mpool) { 104 int i; 105 106 for (i = 0; i < env_mpool_max; i++) { 107 if (mpool->allocator[i]) { 108 env_allocator_destroy(mpool->allocator[i]); 109 } 110 } 111 112 env_free(mpool); 113 } 114 } 115 116 static env_allocator *env_mpool_get_allocator(struct env_mpool *mpool, 117 uint32_t count) 118 { 119 unsigned int idx; 120 121 if (unlikely(count == 0)) { 122 return mpool->allocator[env_mpool_1]; 123 } 124 125 idx = 31 - __builtin_clz(count); 126 127 if (__builtin_ffs(count) <= idx) { 128 idx++; 129 } 130 131 if (idx >= env_mpool_max || idx > mpool->mpool_max) { 132 return NULL; 133 } 134 135 return mpool->allocator[idx]; 136 } 137 138 void *env_mpool_new(struct env_mpool *mpool, uint32_t count) 139 { 140 void *items = NULL; 141 env_allocator *allocator; 142 size_t size = mpool->hdr_size + (mpool->elem_size * count); 143 144 allocator = env_mpool_get_allocator(mpool, count); 145 146 if (allocator) { 147 items = env_allocator_new(allocator); 148 } else if (mpool->fallback) { 149 items = env_vmalloc(size); 150 } 151 152 return items; 153 } 154 155 bool env_mpool_del(struct env_mpool *mpool, 156 void *items, uint32_t count) 157 { 158 env_allocator *allocator; 159 160 allocator = env_mpool_get_allocator(mpool, count); 161 162 if (allocator) { 163 env_allocator_del(allocator, items); 164 } else if (mpool->fallback) { 165 env_vfree(items); 166 } else { 167 return false; 168 } 169 170 return true; 171 } 172