Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/openzfs/module/icp/include/generic_impl.c
48529 views
1
// SPDX-License-Identifier: CDDL-1.0
2
/*
3
* CDDL HEADER START
4
*
5
* The contents of this file are subject to the terms of the
6
* Common Development and Distribution License (the "License").
7
* You may not use this file except in compliance with the License.
8
*
9
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10
* or https://opensource.org/licenses/CDDL-1.0.
11
* See the License for the specific language governing permissions
12
* and limitations under the License.
13
*
14
* When distributing Covered Code, include this CDDL HEADER in each
15
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16
* If applicable, add the following below this CDDL HEADER, with the
17
* fields enclosed by brackets "[]" replaced with your own identifying
18
* information: Portions Copyright [yyyy] [name of copyright owner]
19
*
20
* CDDL HEADER END
21
*/
22
23
/*
24
* Copyright (c) 2003, 2010 Oracle and/or its affiliates.
25
* Copyright (c) 2022 Tino Reichardt <[email protected]>
26
*/
27
28
/*
29
* This file gets included by c files for implementing the full set
30
* of zfs_impl.h defines.
31
*
32
* It's ment for easier maintaining multiple implementations of
33
* algorithms. Look into blake3_impl.c, sha256_impl.c or sha512_impl.c
34
* for reference.
35
*/
36
37
#include <sys/zfs_context.h>
38
#include <sys/zio_checksum.h>
39
#include <sys/zfs_impl.h>
40
41
/* Two default implementations */
42
#define IMPL_FASTEST (UINT32_MAX)
43
#define IMPL_CYCLE (UINT32_MAX - 1)
44
45
#define IMPL_READ(i) (*(volatile uint32_t *) &(i))
46
47
/* Implementation that contains the fastest method */
48
static IMPL_OPS_T generic_fastest_impl = {
49
.name = "fastest"
50
};
51
52
/* Hold all supported implementations */
53
static const IMPL_OPS_T *generic_supp_impls[ARRAY_SIZE(IMPL_ARRAY)];
54
static uint32_t generic_supp_impls_cnt = 0;
55
56
/* Currently selected implementation */
57
static uint32_t generic_impl_chosen = IMPL_FASTEST;
58
59
static struct generic_impl_selector {
60
const char *name;
61
uint32_t sel;
62
} generic_impl_selectors[] = {
63
{ "cycle", IMPL_CYCLE },
64
{ "fastest", IMPL_FASTEST }
65
};
66
67
/* check the supported implementations */
68
static void
69
generic_impl_init(void)
70
{
71
int i, c;
72
73
/* init only once */
74
if (likely(generic_supp_impls_cnt != 0))
75
return;
76
77
/* Move supported implementations into generic_supp_impls */
78
for (i = 0, c = 0; i < ARRAY_SIZE(IMPL_ARRAY); i++) {
79
const IMPL_OPS_T *impl = IMPL_ARRAY[i];
80
81
if (impl->is_supported && impl->is_supported())
82
generic_supp_impls[c++] = impl;
83
}
84
generic_supp_impls_cnt = c;
85
86
/* first init generic impl, may be changed via set_fastest() */
87
memcpy(&generic_fastest_impl, generic_supp_impls[0],
88
sizeof (generic_fastest_impl));
89
}
90
91
/* get number of supported implementations */
92
static uint32_t
93
generic_impl_getcnt(void)
94
{
95
generic_impl_init();
96
return (generic_supp_impls_cnt);
97
}
98
99
/* get id of selected implementation */
100
static uint32_t
101
generic_impl_getid(void)
102
{
103
generic_impl_init();
104
return (IMPL_READ(generic_impl_chosen));
105
}
106
107
/* get name of selected implementation */
108
static const char *
109
generic_impl_getname(void)
110
{
111
uint32_t impl = IMPL_READ(generic_impl_chosen);
112
113
generic_impl_init();
114
switch (impl) {
115
case IMPL_FASTEST:
116
return ("fastest");
117
case IMPL_CYCLE:
118
return ("cycle");
119
default:
120
return (generic_supp_impls[impl]->name);
121
}
122
}
123
124
/* set implementation by id */
125
static void
126
generic_impl_setid(uint32_t id)
127
{
128
generic_impl_init();
129
switch (id) {
130
case IMPL_FASTEST:
131
atomic_swap_32(&generic_impl_chosen, IMPL_FASTEST);
132
break;
133
case IMPL_CYCLE:
134
atomic_swap_32(&generic_impl_chosen, IMPL_CYCLE);
135
break;
136
default:
137
ASSERT3U(id, <, generic_supp_impls_cnt);
138
atomic_swap_32(&generic_impl_chosen, id);
139
break;
140
}
141
}
142
143
/* set implementation by name */
144
static int
145
generic_impl_setname(const char *val)
146
{
147
uint32_t impl = IMPL_READ(generic_impl_chosen);
148
size_t val_len;
149
int i, err = -EINVAL;
150
151
generic_impl_init();
152
val_len = strlen(val);
153
while ((val_len > 0) && !!isspace(val[val_len-1])) /* trim '\n' */
154
val_len--;
155
156
/* check mandatory implementations */
157
for (i = 0; i < ARRAY_SIZE(generic_impl_selectors); i++) {
158
const char *name = generic_impl_selectors[i].name;
159
160
if (val_len == strlen(name) &&
161
strncmp(val, name, val_len) == 0) {
162
impl = generic_impl_selectors[i].sel;
163
err = 0;
164
break;
165
}
166
}
167
168
/* check all supported implementations */
169
if (err != 0) {
170
for (i = 0; i < generic_supp_impls_cnt; i++) {
171
const char *name = generic_supp_impls[i]->name;
172
173
if (val_len == strlen(name) &&
174
strncmp(val, name, val_len) == 0) {
175
impl = i;
176
err = 0;
177
break;
178
}
179
}
180
}
181
182
if (err == 0) {
183
atomic_swap_32(&generic_impl_chosen, impl);
184
}
185
186
return (err);
187
}
188
189
/* setup id as fastest implementation */
190
static void
191
generic_impl_set_fastest(uint32_t id)
192
{
193
generic_impl_init();
194
memcpy(&generic_fastest_impl, generic_supp_impls[id],
195
sizeof (generic_fastest_impl));
196
}
197
198
/* return impl iterating functions */
199
const zfs_impl_t ZFS_IMPL_OPS = {
200
.name = IMPL_NAME,
201
.getcnt = generic_impl_getcnt,
202
.getid = generic_impl_getid,
203
.getname = generic_impl_getname,
204
.set_fastest = generic_impl_set_fastest,
205
.setid = generic_impl_setid,
206
.setname = generic_impl_setname
207
};
208
209
/* get impl ops_t of selected implementation */
210
const IMPL_OPS_T *
211
IMPL_GET_OPS(void)
212
{
213
const IMPL_OPS_T *ops = NULL;
214
uint32_t idx, impl = IMPL_READ(generic_impl_chosen);
215
static uint32_t cycle_count = 0;
216
217
generic_impl_init();
218
switch (impl) {
219
case IMPL_FASTEST:
220
ops = &generic_fastest_impl;
221
break;
222
case IMPL_CYCLE:
223
idx = (++cycle_count) % generic_supp_impls_cnt;
224
ops = generic_supp_impls[idx];
225
break;
226
default:
227
ASSERT3U(impl, <, generic_supp_impls_cnt);
228
ops = generic_supp_impls[impl];
229
break;
230
}
231
232
ASSERT3P(ops, !=, NULL);
233
return (ops);
234
}
235
236