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