xref: /spdk/lib/env_ocf/mpool.c (revision 307b8c112ffd90a26d53dd15fad67bd9038ef526)
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