1 /*
2  * Copyright (c) 2023, Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef __KERNEL_OBJ_CORE_H__
8 #define __KERNEL_OBJ_CORE_H__
9 
10 #include <zephyr/sys/slist.h>
11 
12 /**
13  * @defgroup obj_core_apis Object Core APIs
14  * @ingroup kernel_apis
15  * @{
16  */
17 
18 /**
19  * @brief Convert kernel object pointer into its object core pointer
20  */
21 #define K_OBJ_CORE(kobj)  (&((kobj)->obj_core))
22 
23 /**
24  * @brief Generate new object type IDs based on a 4 letter string
25  */
26 #define K_OBJ_TYPE_ID_GEN(s)     ((s[0] << 24) | (s[1] << 16) | (s[2] << 8) | (s[3]))
27 
28 /* Known kernel object types */
29 
30 /** Condition variable object type */
31 #define K_OBJ_TYPE_CONDVAR_ID    K_OBJ_TYPE_ID_GEN("COND")
32 /** CPU object type */
33 #define K_OBJ_TYPE_CPU_ID        K_OBJ_TYPE_ID_GEN("CPU_")
34 /** Event object type */
35 #define K_OBJ_TYPE_EVENT_ID      K_OBJ_TYPE_ID_GEN("EVNT")
36 /** FIFO object type */
37 #define K_OBJ_TYPE_FIFO_ID       K_OBJ_TYPE_ID_GEN("FIFO")
38 /** Kernel object type */
39 #define K_OBJ_TYPE_KERNEL_ID     K_OBJ_TYPE_ID_GEN("KRNL")
40 /** LIFO object type */
41 #define K_OBJ_TYPE_LIFO_ID       K_OBJ_TYPE_ID_GEN("LIFO")
42 /** Memory block object type */
43 #define K_OBJ_TYPE_MEM_BLOCK_ID  K_OBJ_TYPE_ID_GEN("MBLK")
44 /** Mailbox object type */
45 #define K_OBJ_TYPE_MBOX_ID       K_OBJ_TYPE_ID_GEN("MBOX")
46 /** Memory slab object type */
47 #define K_OBJ_TYPE_MEM_SLAB_ID   K_OBJ_TYPE_ID_GEN("SLAB")
48 /** Message queue object type */
49 #define K_OBJ_TYPE_MSGQ_ID       K_OBJ_TYPE_ID_GEN("MSGQ")
50 /** Mutex object type */
51 #define K_OBJ_TYPE_MUTEX_ID      K_OBJ_TYPE_ID_GEN("MUTX")
52 /** Pipe object type */
53 #define K_OBJ_TYPE_PIPE_ID       K_OBJ_TYPE_ID_GEN("PIPE")
54 /** Semaphore object type */
55 #define K_OBJ_TYPE_SEM_ID        K_OBJ_TYPE_ID_GEN("SEM4")
56 /** Stack object type */
57 #define K_OBJ_TYPE_STACK_ID      K_OBJ_TYPE_ID_GEN("STCK")
58 /** Thread object type */
59 #define K_OBJ_TYPE_THREAD_ID     K_OBJ_TYPE_ID_GEN("THRD")
60 /** Timer object type */
61 #define K_OBJ_TYPE_TIMER_ID      K_OBJ_TYPE_ID_GEN("TIMR")
62 
63 struct k_obj_type;
64 struct k_obj_core;
65 
66 /**
67  * @cond INTERNAL_HIDDEN
68  */
69 
70 #ifdef CONFIG_OBJ_CORE
71 #define K_OBJ_CORE_INIT(_objp, _obj_type)   \
72 	extern struct k_obj_type _obj_type; \
73 	k_obj_core_init(_objp, &_obj_type)
74 
75 #define K_OBJ_CORE_LINK(objp) k_obj_core_link(objp)
76 #else
77 #define K_OBJ_CORE_INIT(objp, type)   do { } while (0)
78 #define K_OBJ_CORE_LINK(objp)         do { } while (0)
79 #endif
80 
81 /**
82  * INTERNAL_HIDDEN @endcond
83  */
84 
85 /**
86  * Tools may use this list as an entry point to identify all registered
87  * object types and the object cores linked to them.
88  */
89 extern sys_slist_t z_obj_type_list;
90 
91 /** Object core statistics descriptor */
92 struct k_obj_core_stats_desc {
93 	size_t  raw_size;   /**< Internal representation stats buffer size */
94 	size_t  query_size; /**< Stats buffer size used for reporting */
95 
96 	/** Function pointer to retrieve internal representation of stats */
97 	int (*raw)(struct k_obj_core *obj_core, void *stats);
98 	/** Function pointer to retrieve reported statistics */
99 	int (*query)(struct k_obj_core *obj_core, void *stats);
100 	/** Function pointer to reset object's statistics */
101 	int (*reset)(struct k_obj_core *obj_core);
102 	/** Function pointer to disable object's statistics gathering */
103 	int (*disable)(struct k_obj_core *obj_core);
104 	/** Function pointer to enable object's statistics gathering */
105 	int (*enable)(struct k_obj_core *obj_core);
106 };
107 
108 /** Object type structure */
109 struct k_obj_type {
110 	sys_snode_t    node;   /**< Node within list of object types */
111 	sys_slist_t    list;   /**< List of objects of this object type */
112 	uint32_t       id;     /**< Unique type ID */
113 	size_t         obj_core_offset;  /**< Offset to obj_core field */
114 #ifdef CONFIG_OBJ_CORE_STATS
115 	/** Pointer to object core statistics descriptor */
116 	struct k_obj_core_stats_desc *stats_desc;
117 #endif
118 };
119 
120 /** Object core structure */
121 struct k_obj_core {
122 	sys_snode_t        node;   /**< Object node within object type's list */
123 	struct k_obj_type *type;   /**< Object type to which object belongs */
124 #ifdef CONFIG_OBJ_CORE_STATS
125 	void  *stats;              /**< Pointer to kernel object's stats */
126 #endif
127 };
128 
129 /**
130  * @brief Initialize a specific object type
131  *
132  * Initializes a specific object type and links it into the object core
133  * framework.
134  *
135  * @param type Pointer to the object type to initialize
136  * @param id A means to identify the object type
137  * @param off Offset of object core within the structure
138  *
139  * @retval Pointer to initialized object type
140  */
141 struct k_obj_type *z_obj_type_init(struct k_obj_type *type,
142 				   uint32_t id, size_t off);
143 
144 /**
145  * @brief Find a specific object type by ID
146  *
147  * Given an object type ID, this function searches for the object type that
148  * is associated with the specified type ID @a type_id.
149  *
150  * @param type_id  Type ID associated with object type
151  *
152  * @retval NULL if object type not found
153  * @retval Pointer to object type if found
154  */
155 struct k_obj_type *k_obj_type_find(uint32_t type_id);
156 
157 /**
158  * @brief Walk the object type's list of object cores
159  *
160  * This function takes a global spinlock and walks the object type's list
161  * of object cores and invokes the callback function on each element while
162  * holding that lock. Although this will ensure that the list is not modified,
163  * one can expect a significant penalty in terms of performance and latency.
164  *
165  * The callback function shall either return non-zero to stop further walking,
166  * or it shall return 0 to continue walking.
167  *
168  * @param type  Pointer to the object type
169  * @param func  Callback to invoke on each object core of the object type
170  * @param data  Custom data passed to the callback
171  *
172  * @retval non-zero if walk is terminated by the callback; otherwise 0
173  */
174 int k_obj_type_walk_locked(struct k_obj_type *type,
175 			   int (*func)(struct k_obj_core *, void *),
176 				  void *data);
177 
178 /**
179  * @brief Walk the object type's list of object cores
180  *
181  * This function is similar to k_obj_type_walk_locked() except that it walks
182  * the list without obtaining the global spinlock. No synchronization is
183  * provided here. Mutation of the list of objects while this function is in
184  * progress must be prevented at the application layer, otherwise
185  * undefined/unreliable behavior, corruption and/or crashes may result.
186  *
187  * The callback function shall either return non-zero to stop further walking,
188  * or it shall return 0 to continue walking.
189  *
190  * @param type  Pointer to the object type
191  * @param func  Callback to invoke on each object core of the object type
192  * @param data  Custom data passed to the callback
193  *
194  * @retval non-zero if walk is terminated by the callback; otherwise 0
195  */
196 int k_obj_type_walk_unlocked(struct k_obj_type *type,
197 			     int (*func)(struct k_obj_core *, void *),
198 			     void *data);
199 
200 /**
201  * @brief Initialize the core of the kernel object
202  *
203  * Initializing the kernel object core associates it with the specified
204  * kernel object type.
205  *
206  * @param obj_core Pointer to the kernel object to initialize
207  * @param type Pointer to the kernel object type
208  */
209 void k_obj_core_init(struct k_obj_core *obj_core, struct k_obj_type *type);
210 
211 /**
212  * @brief Link the kernel object to the kernel object type list
213  *
214  * A kernel object can be optionally linked into the kernel object type's
215  * list of objects. A kernel object must have been initialized before it
216  * can be linked. Linked kernel objects can be traversed and have information
217  * extracted from them by system tools.
218  *
219  * @param obj_core Pointer to the kernel object
220  */
221 void k_obj_core_link(struct k_obj_core *obj_core);
222 
223 /**
224  * @brief Automatically link the kernel object after initializing it
225  *
226  * A useful wrapper to both initialize the core of the kernel object and
227  * automatically link it into the kernel object type's list of objects.
228  *
229  * @param obj_core Pointer to the kernel object to initialize
230  * @param type Pointer to the kernel object type
231  */
232 void k_obj_core_init_and_link(struct k_obj_core *obj_core,
233 			      struct k_obj_type *type);
234 
235 /**
236  * @brief Unlink the kernel object from the kernel object type list
237  *
238  * Kernel objects can be unlinked from their respective kernel object type
239  * lists. If on a list, it must be done at the end of the kernel object's life
240  * cycle.
241  *
242  * @param obj_core Pointer to the kernel object
243  */
244 void k_obj_core_unlink(struct k_obj_core *obj_core);
245 
246 /** @} */
247 
248 /**
249  * @defgroup obj_core_stats_apis Object Core Statistics APIs
250  * @ingroup kernel_apis
251  * @{
252  */
253 
254 #ifdef CONFIG_OBJ_CORE_STATS
255 /**
256  * @brief Initialize the object type's stats descriptor
257  *
258  * This routine initializes the object type's stats descriptor.
259  *
260  * @param type Pointer to the object type
261  * @param stats_desc Pointer to the object core statistics descriptor
262  */
k_obj_type_stats_init(struct k_obj_type * type,struct k_obj_core_stats_desc * stats_desc)263 static inline void k_obj_type_stats_init(struct k_obj_type *type,
264 					 struct k_obj_core_stats_desc *stats_desc)
265 {
266 	type->stats_desc = stats_desc;
267 }
268 
269 /**
270  * @brief Initialize the object core for statistics
271  *
272  * This routine initializes the object core to operate within the object core
273  * statistics framework.
274  *
275  * @param obj_core Pointer to the object core
276  * @param stats Pointer to the object's raw statistics
277  */
k_obj_core_stats_init(struct k_obj_core * obj_core,void * stats)278 static inline void k_obj_core_stats_init(struct k_obj_core *obj_core,
279 					 void *stats)
280 {
281 	obj_core->stats = stats;
282 }
283 #endif
284 
285 /**
286  * @brief Register kernel object for gathering statistics
287  *
288  * Before a kernel object can gather statistics, it must be registered to do
289  * so. Registering will also automatically enable the kernel object to gather
290  * its statistics.
291  *
292  * @param obj_core Pointer to kernel object core
293  * @param stats Pointer to raw kernel statistics
294  * @param stats_len Size of raw kernel statistics buffer
295  *
296  * @retval 0 on success
297  * @retval -errno on failure
298  */
299 int k_obj_core_stats_register(struct k_obj_core *obj_core, void *stats,
300 			      size_t stats_len);
301 
302 /**
303  * @brief Deregister kernel object from gathering statistics
304  *
305  * Deregistering a kernel object core from gathering statistics prevents it
306  * from gathering any more statistics. It is expected to be invoked at the end
307  * of a kernel object's life cycle.
308  *
309  * @param obj_core Pointer to kernel object core
310  *
311  * @retval 0 on success
312  * @retval -errno on failure
313  */
314 int k_obj_core_stats_deregister(struct k_obj_core *obj_core);
315 
316 /**
317  * @brief Retrieve the raw statistics associated with the kernel object
318  *
319  * This function copies the raw statistics associated with the kernel object
320  * core specified by @a obj_core into the buffer @a stats. Note that the size
321  * of the buffer (@a stats_len) must match the size specified by the kernel
322  * object type's statistics descriptor.
323  *
324  * @param obj_core Pointer to kernel object core
325  * @param stats Pointer to memory buffer into which to copy raw stats
326  * @param stats_len Length of the memory buffer
327  *
328  * @retval 0 on success
329  * @retval -errno on failure
330  */
331 int k_obj_core_stats_raw(struct k_obj_core *obj_core, void *stats,
332 			 size_t stats_len);
333 
334 /**
335  * @brief Retrieve the statistics associated with the kernel object
336  *
337  * This function copies the statistics associated with the kernel object core
338  * specified by @a obj_core into the buffer @a stats. Unlike the raw statistics
339  * this may report calculated values such as averages.  Note that the size of
340  * the buffer (@a stats_len) must match the size specified by the kernel object
341  * type's statistics descriptor.
342  *
343  * @param obj_core Pointer to kernel object core
344  * @param stats Pointer to memory buffer into which to copy the queried stats
345  * @param stats_len Length of the memory buffer
346  *
347  * @retval 0 on success
348  * @retval -errno on failure
349  */
350 int k_obj_core_stats_query(struct k_obj_core *obj_core, void *stats,
351 			   size_t stats_len);
352 
353 /**
354  * @brief Reset the stats associated with the kernel object
355  *
356  * This function resets the statistics associated with the kernel object core
357  * specified by @a obj_core.
358  *
359  * @param obj_core Pointer to kernel object core
360  *
361  * @retval 0 on success
362  * @retval -errno on failure
363  */
364 int k_obj_core_stats_reset(struct k_obj_core *obj_core);
365 
366 /**
367  * @brief Stop gathering the stats associated with the kernel object
368  *
369  * This function temporarily stops the gathering of statistics associated with
370  * the kernel object core specified by @a obj_core. The gathering of statistics
371  * can be resumed by invoking :c:func :`k_obj_core_stats_enable`.
372  *
373  * @param obj_core Pointer to kernel object core
374  *
375  * @retval 0 on success
376  * @retval -errno on failure
377  */
378 int k_obj_core_stats_disable(struct k_obj_core *obj_core);
379 
380 /**
381  * @brief Reset the stats associated with the kernel object
382  *
383  * This function resumes the gathering of statistics associated with the kernel
384  * object core specified by @a obj_core.
385  *
386  * @param obj_core Pointer to kernel object core
387  *
388  * @retval 0 on success
389  * @retval -errno on failure
390  */
391 int k_obj_core_stats_enable(struct k_obj_core *obj_core);
392 
393 /** @} */
394 #endif /* __KERNEL_OBJ_CORE_H__ */
395