1 /*
2 * Copyright (c) 2023, Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/kernel/obj_core.h>
9
10 static struct k_spinlock lock;
11
12 sys_slist_t z_obj_type_list = SYS_SLIST_STATIC_INIT(&z_obj_type_list);
13
z_obj_type_init(struct k_obj_type * type,uint32_t id,size_t off)14 struct k_obj_type *z_obj_type_init(struct k_obj_type *type,
15 uint32_t id, size_t off)
16 {
17 sys_slist_init(&type->list);
18 sys_slist_append(&z_obj_type_list, &type->node);
19 type->id = id;
20 type->obj_core_offset = off;
21
22 return type;
23 }
24
k_obj_core_init(struct k_obj_core * obj_core,struct k_obj_type * type)25 void k_obj_core_init(struct k_obj_core *obj_core, struct k_obj_type *type)
26 {
27 obj_core->node.next = NULL;
28 obj_core->type = type;
29 #ifdef CONFIG_OBJ_CORE_STATS
30 obj_core->stats = NULL;
31 #endif
32 }
33
k_obj_core_link(struct k_obj_core * obj_core)34 void k_obj_core_link(struct k_obj_core *obj_core)
35 {
36 k_spinlock_key_t key = k_spin_lock(&lock);
37
38 sys_slist_append(&obj_core->type->list, &obj_core->node);
39
40 k_spin_unlock(&lock, key);
41 }
42
k_obj_core_init_and_link(struct k_obj_core * obj_core,struct k_obj_type * type)43 void k_obj_core_init_and_link(struct k_obj_core *obj_core,
44 struct k_obj_type *type)
45 {
46 k_obj_core_init(obj_core, type);
47 k_obj_core_link(obj_core);
48 }
49
k_obj_core_unlink(struct k_obj_core * obj_core)50 void k_obj_core_unlink(struct k_obj_core *obj_core)
51 {
52 k_spinlock_key_t key = k_spin_lock(&lock);
53
54 sys_slist_find_and_remove(&obj_core->type->list, &obj_core->node);
55
56 k_spin_unlock(&lock, key);
57 }
58
k_obj_type_find(uint32_t type_id)59 struct k_obj_type *k_obj_type_find(uint32_t type_id)
60 {
61 struct k_obj_type *type;
62 struct k_obj_type *rv = NULL;
63 sys_snode_t *node;
64
65 k_spinlock_key_t key = k_spin_lock(&lock);
66
67 SYS_SLIST_FOR_EACH_NODE(&z_obj_type_list, node) {
68 type = CONTAINER_OF(node, struct k_obj_type, node);
69 if (type->id == type_id) {
70 rv = type;
71 break;
72 }
73 }
74
75 k_spin_unlock(&lock, key);
76
77 return rv;
78 }
79
k_obj_type_walk_locked(struct k_obj_type * type,int (* func)(struct k_obj_core *,void *),void * data)80 int k_obj_type_walk_locked(struct k_obj_type *type,
81 int (*func)(struct k_obj_core *, void *),
82 void *data)
83 {
84 k_spinlock_key_t key;
85 struct k_obj_core *obj_core;
86 sys_snode_t *node;
87 int status = 0;
88
89 key = k_spin_lock(&lock);
90
91 SYS_SLIST_FOR_EACH_NODE(&type->list, node) {
92 obj_core = CONTAINER_OF(node, struct k_obj_core, node);
93 status = func(obj_core, data);
94 if (status != 0) {
95 break;
96 }
97 }
98
99 k_spin_unlock(&lock, key);
100
101 return status;
102 }
103
k_obj_type_walk_unlocked(struct k_obj_type * type,int (* func)(struct k_obj_core *,void *),void * data)104 int k_obj_type_walk_unlocked(struct k_obj_type *type,
105 int (*func)(struct k_obj_core *, void *),
106 void *data)
107 {
108 struct k_obj_core *obj_core;
109 sys_snode_t *node;
110 sys_snode_t *next;
111 int status = 0;
112
113 SYS_SLIST_FOR_EACH_NODE_SAFE(&type->list, node, next) {
114 obj_core = CONTAINER_OF(node, struct k_obj_core, node);
115 status = func(obj_core, data);
116 if (status != 0) {
117 break;
118 }
119 }
120
121 return status;
122 }
123
124 #ifdef CONFIG_OBJ_CORE_STATS
k_obj_core_stats_register(struct k_obj_core * obj_core,void * stats,size_t stats_len)125 int k_obj_core_stats_register(struct k_obj_core *obj_core, void *stats,
126 size_t stats_len)
127 {
128 k_spinlock_key_t key = k_spin_lock(&lock);
129
130 if (obj_core->type->stats_desc == NULL) {
131
132 /* Object type not configured for statistics. */
133
134 k_spin_unlock(&lock, key);
135 return -ENOTSUP;
136 }
137
138 if (obj_core->type->stats_desc->raw_size != stats_len) {
139
140 /* Buffer size mismatch */
141
142 k_spin_unlock(&lock, key);
143 return -EINVAL;
144 }
145
146 obj_core->stats = stats;
147 k_spin_unlock(&lock, key);
148
149 return 0;
150 }
151
k_obj_core_stats_deregister(struct k_obj_core * obj_core)152 int k_obj_core_stats_deregister(struct k_obj_core *obj_core)
153 {
154 k_spinlock_key_t key = k_spin_lock(&lock);
155
156 if (obj_core->type->stats_desc == NULL) {
157
158 /* Object type not configured for statistics. */
159
160 k_spin_unlock(&lock, key);
161 return -ENOTSUP;
162 }
163
164 obj_core->stats = NULL;
165 k_spin_unlock(&lock, key);
166
167 return 0;
168 }
169
k_obj_core_stats_raw(struct k_obj_core * obj_core,void * stats,size_t stats_len)170 int k_obj_core_stats_raw(struct k_obj_core *obj_core, void *stats,
171 size_t stats_len)
172 {
173 int rv;
174 struct k_obj_core_stats_desc *desc;
175
176 k_spinlock_key_t key = k_spin_lock(&lock);
177
178 desc = obj_core->type->stats_desc;
179 if ((desc == NULL) || (desc->raw == NULL)) {
180
181 /* The object type is not configured for this operation */
182
183 k_spin_unlock(&lock, key);
184 return -ENOTSUP;
185 }
186
187 if ((desc->raw_size != stats_len) || (obj_core->stats == NULL)) {
188
189 /*
190 * Either the size of the stats buffer is wrong or
191 * the kernel object was not registered for statistics.
192 */
193
194 k_spin_unlock(&lock, key);
195 return -EINVAL;
196 }
197
198 rv = desc->raw(obj_core, stats);
199 k_spin_unlock(&lock, key);
200
201 return rv;
202 }
203
k_obj_core_stats_query(struct k_obj_core * obj_core,void * stats,size_t stats_len)204 int k_obj_core_stats_query(struct k_obj_core *obj_core, void *stats,
205 size_t stats_len)
206 {
207 int rv;
208 struct k_obj_core_stats_desc *desc;
209
210 k_spinlock_key_t key = k_spin_lock(&lock);
211
212 desc = obj_core->type->stats_desc;
213 if ((desc == NULL) || (desc->query == NULL)) {
214
215 /* The object type is not configured for this operation */
216
217 k_spin_unlock(&lock, key);
218 return -ENOTSUP;
219 }
220
221 if ((desc->query_size != stats_len) || (obj_core->stats == NULL)) {
222
223 /*
224 * Either the size of the stats buffer is wrong or
225 * the kernel object was not registered for statistics.
226 */
227
228 k_spin_unlock(&lock, key);
229 return -EINVAL;
230 }
231
232 rv = desc->query(obj_core, stats);
233 k_spin_unlock(&lock, key);
234
235 return rv;
236 }
237
k_obj_core_stats_reset(struct k_obj_core * obj_core)238 int k_obj_core_stats_reset(struct k_obj_core *obj_core)
239 {
240 int rv;
241 struct k_obj_core_stats_desc *desc;
242
243 k_spinlock_key_t key = k_spin_lock(&lock);
244
245 desc = obj_core->type->stats_desc;
246 if ((desc == NULL) || (desc->reset == NULL)) {
247
248 /* The object type is not configured for this operation */
249
250 k_spin_unlock(&lock, key);
251 return -ENOTSUP;
252 }
253
254 if (obj_core->stats == NULL) {
255
256 /* This kernel object is not configured for statistics */
257
258 k_spin_unlock(&lock, key);
259 return -EINVAL;
260 }
261
262 rv = desc->reset(obj_core);
263 k_spin_unlock(&lock, key);
264
265 return rv;
266 }
267
k_obj_core_stats_disable(struct k_obj_core * obj_core)268 int k_obj_core_stats_disable(struct k_obj_core *obj_core)
269 {
270 int rv;
271 struct k_obj_core_stats_desc *desc;
272
273 k_spinlock_key_t key = k_spin_lock(&lock);
274
275 desc = obj_core->type->stats_desc;
276 if ((desc == NULL) || (desc->disable == NULL)) {
277
278 /* The object type is not configured for this operation */
279
280 k_spin_unlock(&lock, key);
281 return -ENOTSUP;
282 }
283
284 if (obj_core->stats == NULL) {
285
286 /* This kernel object is not configured for statistics */
287
288 k_spin_unlock(&lock, key);
289 return -EINVAL;
290 }
291
292 rv = desc->disable(obj_core);
293 k_spin_unlock(&lock, key);
294
295 return rv;
296 }
297
k_obj_core_stats_enable(struct k_obj_core * obj_core)298 int k_obj_core_stats_enable(struct k_obj_core *obj_core)
299 {
300 int rv;
301 struct k_obj_core_stats_desc *desc;
302
303 k_spinlock_key_t key = k_spin_lock(&lock);
304
305 desc = obj_core->type->stats_desc;
306 if ((desc == NULL) || (desc->enable == NULL)) {
307
308 /* The object type is not configured for this operation */
309
310 k_spin_unlock(&lock, key);
311 return -ENOTSUP;
312 }
313
314 if (obj_core->stats == NULL) {
315
316 /* This kernel object is not configured for statistics */
317
318 k_spin_unlock(&lock, key);
319 return -EINVAL;
320 }
321
322 rv = desc->enable(obj_core);
323 k_spin_unlock(&lock, key);
324
325 return rv;
326 }
327 #endif
328