1*d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2*d30ea906Sjfb8856606  * Copyright(c) 2015 Intel Corporation
3a9643ea8Slogwang  */
4a9643ea8Slogwang #ifndef LTHREAD_DIAG_API_H_
5a9643ea8Slogwang #define LTHREAD_DIAG_API_H_
6a9643ea8Slogwang 
72bfe3f2eSlogwang #ifdef __cplusplus
82bfe3f2eSlogwang extern "C" {
92bfe3f2eSlogwang #endif
102bfe3f2eSlogwang 
11a9643ea8Slogwang #include <stdint.h>
12a9643ea8Slogwang #include <inttypes.h>
13a9643ea8Slogwang 
14a9643ea8Slogwang /*
15a9643ea8Slogwang  * Enable diagnostics
16a9643ea8Slogwang  * 0 = conditionally compiled out
17a9643ea8Slogwang  * 1 = compiled in and maskable at run time, see below for details
18a9643ea8Slogwang  */
19a9643ea8Slogwang #define LTHREAD_DIAG 0
20a9643ea8Slogwang 
21a9643ea8Slogwang /**
22a9643ea8Slogwang  *
23a9643ea8Slogwang  * @file lthread_diag_api.h
24a9643ea8Slogwang  *
25a9643ea8Slogwang  * @warning
26a9643ea8Slogwang  * @b EXPERIMENTAL: this API may change without prior notice
27a9643ea8Slogwang  *
28a9643ea8Slogwang  * lthread diagnostic interface
29a9643ea8Slogwang  *
30a9643ea8Slogwang  * If enabled via configuration file option ( tbd ) the lthread subsystem
31a9643ea8Slogwang  * can generate selected trace information, either RTE_LOG  (INFO) messages,
32a9643ea8Slogwang  * or else invoke a user supplied callback function when any of the events
33a9643ea8Slogwang  * listed below occur.
34a9643ea8Slogwang  *
35a9643ea8Slogwang  * Reporting of events can be selectively masked, the bit position in the
36a9643ea8Slogwang  * mask is determined by the corresponding event identifier listed below.
37a9643ea8Slogwang  *
38a9643ea8Slogwang  * Diagnostics are enabled by registering the callback function and mask
39a9643ea8Slogwang  * using the API lthread_diagnostic_enable().
40a9643ea8Slogwang  *
41a9643ea8Slogwang  * Various interesting parameters are passed to the callback, including the
42a9643ea8Slogwang  * time in cpu clks, the lthread id, the diagnostic event id, a user ref value,
43a9643ea8Slogwang  * event text string, object being traced, and two context dependent parameters
44a9643ea8Slogwang  * (p1 and p2). The meaning of the two parameters p1 and p2 depends on
45a9643ea8Slogwang  * the specific event.
46a9643ea8Slogwang  *
47a9643ea8Slogwang  * The events LT_DIAG_LTHREAD_CREATE, LT_DIAG_MUTEX_CREATE and
48a9643ea8Slogwang  * LT_DIAG_COND_CREATE are implicitly enabled if the event mask includes any of
49a9643ea8Slogwang  * the LT_DIAG_LTHREAD_XXX, LT_DIAG_MUTEX_XXX or LT_DIAG_COND_XXX events
50a9643ea8Slogwang  * respectively.
51a9643ea8Slogwang  *
52a9643ea8Slogwang  * These create events may also be included in the mask discreetly if it is
53a9643ea8Slogwang  * desired to monitor only create events.
54a9643ea8Slogwang  *
55a9643ea8Slogwang  * @param  time
56a9643ea8Slogwang  *  The time in cpu clks at which the event occurred
57a9643ea8Slogwang  *
58a9643ea8Slogwang  * @param  lthread
59a9643ea8Slogwang  *  The current lthread
60a9643ea8Slogwang  *
61a9643ea8Slogwang  * @param diag_event
62a9643ea8Slogwang  *  The diagnostic event id (bit position in the mask)
63a9643ea8Slogwang  *
64a9643ea8Slogwang  * @param  diag_ref
65a9643ea8Slogwang  *
66a9643ea8Slogwang  * For LT_DIAG_LTHREAD_CREATE, LT_DIAG_MUTEX_CREATE or LT_DIAG_COND_CREATE
67a9643ea8Slogwang  * this parameter is not used and set to 0.
68a9643ea8Slogwang  * All other events diag_ref contains the user ref value returned by the
69a9643ea8Slogwang  * callback function when lthread is created.
70a9643ea8Slogwang  *
71a9643ea8Slogwang  * The diag_ref values assigned to mutex and cond var can be retrieved
72a9643ea8Slogwang  * using the APIs lthread_mutex_diag_ref(), and lthread_cond_diag_ref()
73a9643ea8Slogwang  * respectively.
74a9643ea8Slogwang  *
75a9643ea8Slogwang  * @param p1
76a9643ea8Slogwang  *  see below
77a9643ea8Slogwang  *
78a9643ea8Slogwang  * @param p1
79a9643ea8Slogwang  *  see below
80a9643ea8Slogwang  *
81a9643ea8Slogwang  * @returns
82a9643ea8Slogwang  * For LT_DIAG_LTHREAD_CREATE, LT_DIAG_MUTEX_CREATE or LT_DIAG_COND_CREATE
83a9643ea8Slogwang  * expects a user diagnostic ref value that will be saved in the lthread, mutex
84a9643ea8Slogwang  * or cond var.
85a9643ea8Slogwang  *
86a9643ea8Slogwang  * For all other events return value is ignored.
87a9643ea8Slogwang  *
88a9643ea8Slogwang  *	LT_DIAG_SCHED_CREATE - Invoked when a scheduler is created
89a9643ea8Slogwang  *		p1 = the scheduler that was created
90a9643ea8Slogwang  *		p2 = not used
91a9643ea8Slogwang  *		return value will be ignored
92a9643ea8Slogwang  *
93a9643ea8Slogwang  *	LT_DIAG_SCHED_SHUTDOWN - Invoked when a shutdown request is received
94a9643ea8Slogwang  *		p1 = the scheduler to be shutdown
95a9643ea8Slogwang  *		p2 = not used
96a9643ea8Slogwang  *		return value will be ignored
97a9643ea8Slogwang  *
98a9643ea8Slogwang  *	LT_DIAG_LTHREAD_CREATE - Invoked when a thread is created
99a9643ea8Slogwang  *		p1 = the lthread that was created
100a9643ea8Slogwang  *		p2 = not used
101a9643ea8Slogwang  *		return value will be stored in the lthread
102a9643ea8Slogwang  *
103a9643ea8Slogwang  *	LT_DIAG_LTHREAD_EXIT - Invoked when a lthread exits
104a9643ea8Slogwang  *		p2 = 0 if the thread was already joined
105a9643ea8Slogwang  *		p2 = 1 if the thread was not already joined
106a9643ea8Slogwang  *		return val ignored
107a9643ea8Slogwang  *
108a9643ea8Slogwang  *	LT_DIAG_LTHREAD_JOIN - Invoked when a lthread exits
109a9643ea8Slogwang  *		p1 = the lthread that is being joined
110a9643ea8Slogwang  *		p2 = 0 if the thread was already exited
111a9643ea8Slogwang  *		p2 = 1 if the thread was not already exited
112a9643ea8Slogwang  *		return val ignored
113a9643ea8Slogwang  *
114a9643ea8Slogwang  *	LT_DIAG_LTHREAD_CANCELLED - Invoked when an lthread is cancelled
115a9643ea8Slogwang  *		p1 = not used
116a9643ea8Slogwang  *		p2 = not used
117a9643ea8Slogwang  *		return val ignored
118a9643ea8Slogwang  *
119a9643ea8Slogwang  *	LT_DIAG_LTHREAD_DETACH - Invoked when an lthread is detached
120a9643ea8Slogwang  *		p1 = not used
121a9643ea8Slogwang  *		p2 = not used
122a9643ea8Slogwang  *		return val ignored
123a9643ea8Slogwang  *
124a9643ea8Slogwang  *	LT_DIAG_LTHREAD_FREE - Invoked when an lthread is freed
125a9643ea8Slogwang  *		p1 = not used
126a9643ea8Slogwang  *		p2 = not used
127a9643ea8Slogwang  *		return val ignored
128a9643ea8Slogwang  *
129a9643ea8Slogwang  *	LT_DIAG_LTHREAD_SUSPENDED - Invoked when an lthread is suspended
130a9643ea8Slogwang  *		p1 = not used
131a9643ea8Slogwang  *		p2 = not used
132a9643ea8Slogwang  *		return val ignored
133a9643ea8Slogwang  *
134a9643ea8Slogwang  *	LT_DIAG_LTHREAD_YIELD - Invoked when an lthread explicitly yields
135a9643ea8Slogwang  *		p1 = not used
136a9643ea8Slogwang  *		p2 = not used
137a9643ea8Slogwang  *		return val ignored
138a9643ea8Slogwang  *
139a9643ea8Slogwang  *	LT_DIAG_LTHREAD_RESCHEDULED - Invoked when an lthread is rescheduled
140a9643ea8Slogwang  *		p1 = not used
141a9643ea8Slogwang  *		p2 = not used
142a9643ea8Slogwang  *		return val ignored
143a9643ea8Slogwang  *
144a9643ea8Slogwang  *	LT_DIAG_LTHREAD_RESUMED - Invoked when an lthread is resumed
145a9643ea8Slogwang  *		p1 = not used
146a9643ea8Slogwang  *		p2 = not used
147a9643ea8Slogwang  *		return val ignored
148a9643ea8Slogwang  *
149a9643ea8Slogwang  *	LT_DIAG_LTHREAD_AFFINITY - Invoked when an lthread is affinitised
150a9643ea8Slogwang  *		p1 = the destination lcore_id
151a9643ea8Slogwang  *		p2 = not used
152a9643ea8Slogwang  *		return val ignored
153a9643ea8Slogwang  *
154a9643ea8Slogwang  *	LT_DIAG_LTHREAD_TMR_START - Invoked when an lthread starts a timer
155a9643ea8Slogwang  *		p1 = address of timer node
156a9643ea8Slogwang  *		p2 = the timeout value
157a9643ea8Slogwang  *		return val ignored
158a9643ea8Slogwang  *
159a9643ea8Slogwang  *	LT_DIAG_LTHREAD_TMR_DELETE - Invoked when an lthread deletes a timer
160a9643ea8Slogwang  *		p1 = address of the timer node
161a9643ea8Slogwang  *		p2 = 0 the timer and the was successfully deleted
162a9643ea8Slogwang  *		p2 = not usee
163a9643ea8Slogwang  *		return val ignored
164a9643ea8Slogwang  *
165a9643ea8Slogwang  *	LT_DIAG_LTHREAD_TMR_EXPIRED - Invoked when an lthread timer expires
166a9643ea8Slogwang  *		p1 = address of scheduler the timer expired on
167a9643ea8Slogwang  *		p2 = the thread associated with the timer
168a9643ea8Slogwang  *		return val ignored
169a9643ea8Slogwang  *
170a9643ea8Slogwang  *	LT_DIAG_COND_CREATE - Invoked when a condition variable is created
171a9643ea8Slogwang  *		p1 = address of cond var that was created
172a9643ea8Slogwang  *		p2 = not used
173a9643ea8Slogwang  *		return diag ref value will be stored in the condition variable
174a9643ea8Slogwang  *
175a9643ea8Slogwang  *	LT_DIAG_COND_DESTROY - Invoked when a condition variable is destroyed
176a9643ea8Slogwang  *		p1 = not used
177a9643ea8Slogwang  *		p2 = not used
178a9643ea8Slogwang  *		return val ignored
179a9643ea8Slogwang  *
180a9643ea8Slogwang  *	LT_DIAG_COND_WAIT - Invoked when an lthread waits on a cond var
181a9643ea8Slogwang  *		p1 = the address of the condition variable
182a9643ea8Slogwang  *		p2 = not used
183a9643ea8Slogwang  *		return val ignored
184a9643ea8Slogwang  *
185a9643ea8Slogwang  *	LT_DIAG_COND_SIGNAL - Invoked when an lthread signals a cond var
186a9643ea8Slogwang  *		p1 = the address of the cond var
187a9643ea8Slogwang  *		p2 = the lthread that was signalled, or error code
188a9643ea8Slogwang  *		return val ignored
189a9643ea8Slogwang  *
190a9643ea8Slogwang  *	LT_DIAG_COND_BROADCAST - Invoked when an lthread broadcasts a cond var
191a9643ea8Slogwang  *		p1 = the address of the condition variable
192a9643ea8Slogwang  *		p2 = the lthread(s) that are signalled, or error code
193a9643ea8Slogwang  *
194a9643ea8Slogwang  *	LT_DIAG_MUTEX_CREATE - Invoked when a mutex is created
195a9643ea8Slogwang  *		p1 = address of muex
196a9643ea8Slogwang  *		p2 = not used
197a9643ea8Slogwang  *		return diag ref value will be stored in the mutex variable
198a9643ea8Slogwang  *
199a9643ea8Slogwang  *	LT_DIAG_MUTEX_DESTROY - Invoked when a mutex is destroyed
200a9643ea8Slogwang  *		p1 = address of mutex
201a9643ea8Slogwang  *		p2 = not used
202a9643ea8Slogwang  *		return val ignored
203a9643ea8Slogwang  *
204a9643ea8Slogwang  *	LT_DIAG_MUTEX_LOCK - Invoked when a mutex lock is obtained
205a9643ea8Slogwang  *		p1 = address of mutex
206a9643ea8Slogwang  *		p2 = function return value
207a9643ea8Slogwang  *		return val ignored
208a9643ea8Slogwang  *
209a9643ea8Slogwang  *	LT_DIAG_MUTEX_BLOCKED  - Invoked when an lthread blocks on a mutex
210a9643ea8Slogwang  *		p1 = address of mutex
211a9643ea8Slogwang  *		p2 = function return value
212a9643ea8Slogwang  *		return val ignored
213a9643ea8Slogwang  *
214a9643ea8Slogwang  *	LT_DIAG_MUTEX_TRYLOCK - Invoked when a mutex try lock is attempted
215a9643ea8Slogwang  *		p1 = address of mutex
216a9643ea8Slogwang  *		p2 = the function return value
217a9643ea8Slogwang  *		return val ignored
218a9643ea8Slogwang  *
219a9643ea8Slogwang  *	LT_DIAG_MUTEX_UNLOCKED - Invoked when a mutex is unlocked
220a9643ea8Slogwang  *		p1 = address of mutex
221a9643ea8Slogwang  *		p2 = the thread that was unlocked, or error code
222a9643ea8Slogwang  *		return val ignored
223a9643ea8Slogwang  */
224a9643ea8Slogwang typedef uint64_t (*diag_callback) (uint64_t time, struct lthread *lt,
225a9643ea8Slogwang 				  int diag_event, uint64_t diag_ref,
226a9643ea8Slogwang 				const char *text, uint64_t p1, uint64_t p2);
227a9643ea8Slogwang 
228a9643ea8Slogwang /*
229a9643ea8Slogwang  * Set user diagnostic callback and mask
230a9643ea8Slogwang  * If the callback function pointer is NULL the default
231a9643ea8Slogwang  * callback handler will be restored.
232a9643ea8Slogwang  */
233a9643ea8Slogwang void lthread_diagnostic_enable(diag_callback cb, uint64_t diag_mask);
234a9643ea8Slogwang 
235a9643ea8Slogwang /*
236a9643ea8Slogwang  * Set diagnostic mask
237a9643ea8Slogwang  */
238a9643ea8Slogwang void lthread_diagnostic_set_mask(uint64_t mask);
239a9643ea8Slogwang 
240a9643ea8Slogwang /*
241a9643ea8Slogwang  * lthread diagnostic callback
242a9643ea8Slogwang  */
243a9643ea8Slogwang enum lthread_diag_ev {
244a9643ea8Slogwang 	/* bits 0 - 14 lthread flag group */
245a9643ea8Slogwang 	LT_DIAG_LTHREAD_CREATE,		/* 00 mask 0x00000001 */
246a9643ea8Slogwang 	LT_DIAG_LTHREAD_EXIT,		/* 01 mask 0x00000002 */
247a9643ea8Slogwang 	LT_DIAG_LTHREAD_JOIN,		/* 02 mask 0x00000004 */
248a9643ea8Slogwang 	LT_DIAG_LTHREAD_CANCEL,		/* 03 mask 0x00000008 */
249a9643ea8Slogwang 	LT_DIAG_LTHREAD_DETACH,		/* 04 mask 0x00000010 */
250a9643ea8Slogwang 	LT_DIAG_LTHREAD_FREE,		/* 05 mask 0x00000020 */
251a9643ea8Slogwang 	LT_DIAG_LTHREAD_SUSPENDED,	/* 06 mask 0x00000040 */
252a9643ea8Slogwang 	LT_DIAG_LTHREAD_YIELD,		/* 07 mask 0x00000080 */
253a9643ea8Slogwang 	LT_DIAG_LTHREAD_RESCHEDULED,	/* 08 mask 0x00000100 */
254a9643ea8Slogwang 	LT_DIAG_LTHREAD_SLEEP,		/* 09 mask 0x00000200 */
255a9643ea8Slogwang 	LT_DIAG_LTHREAD_RESUMED,	/* 10 mask 0x00000400 */
256a9643ea8Slogwang 	LT_DIAG_LTHREAD_AFFINITY,	/* 11 mask 0x00000800 */
257a9643ea8Slogwang 	LT_DIAG_LTHREAD_TMR_START,	/* 12 mask 0x00001000 */
258a9643ea8Slogwang 	LT_DIAG_LTHREAD_TMR_DELETE,	/* 13 mask 0x00002000 */
259a9643ea8Slogwang 	LT_DIAG_LTHREAD_TMR_EXPIRED,	/* 14 mask 0x00004000 */
260a9643ea8Slogwang 	/* bits 15 - 19 conditional variable flag group */
261a9643ea8Slogwang 	LT_DIAG_COND_CREATE,		/* 15 mask 0x00008000 */
262a9643ea8Slogwang 	LT_DIAG_COND_DESTROY,		/* 16 mask 0x00010000 */
263a9643ea8Slogwang 	LT_DIAG_COND_WAIT,		/* 17 mask 0x00020000 */
264a9643ea8Slogwang 	LT_DIAG_COND_SIGNAL,		/* 18 mask 0x00040000 */
265a9643ea8Slogwang 	LT_DIAG_COND_BROADCAST,		/* 19 mask 0x00080000 */
266a9643ea8Slogwang 	/* bits 20 - 25 mutex flag group */
267a9643ea8Slogwang 	LT_DIAG_MUTEX_CREATE,		/* 20 mask 0x00100000 */
268a9643ea8Slogwang 	LT_DIAG_MUTEX_DESTROY,		/* 21 mask 0x00200000 */
269a9643ea8Slogwang 	LT_DIAG_MUTEX_LOCK,		/* 22 mask 0x00400000 */
270a9643ea8Slogwang 	LT_DIAG_MUTEX_TRYLOCK,		/* 23 mask 0x00800000 */
271a9643ea8Slogwang 	LT_DIAG_MUTEX_BLOCKED,		/* 24 mask 0x01000000 */
272a9643ea8Slogwang 	LT_DIAG_MUTEX_UNLOCKED,		/* 25 mask 0x02000000 */
273a9643ea8Slogwang 	/* bits 26 - 27 scheduler flag group - 8 bits */
274a9643ea8Slogwang 	LT_DIAG_SCHED_CREATE,		/* 26 mask 0x04000000 */
275a9643ea8Slogwang 	LT_DIAG_SCHED_SHUTDOWN,		/* 27 mask 0x08000000 */
276a9643ea8Slogwang 	LT_DIAG_EVENT_MAX
277a9643ea8Slogwang };
278a9643ea8Slogwang 
279a9643ea8Slogwang #define LT_DIAG_ALL 0xffffffffffffffff
280a9643ea8Slogwang 
281a9643ea8Slogwang 
282a9643ea8Slogwang /*
283a9643ea8Slogwang  * Display scheduler stats
284a9643ea8Slogwang  */
285a9643ea8Slogwang void
286a9643ea8Slogwang lthread_sched_stats_display(void);
287a9643ea8Slogwang 
288a9643ea8Slogwang /*
289a9643ea8Slogwang  * return the diagnostic ref val stored in a condition var
290a9643ea8Slogwang  */
291a9643ea8Slogwang uint64_t
292a9643ea8Slogwang lthread_cond_diag_ref(struct lthread_cond *c);
293a9643ea8Slogwang 
294a9643ea8Slogwang /*
295a9643ea8Slogwang  * return the diagnostic ref val stored in a mutex
296a9643ea8Slogwang  */
297a9643ea8Slogwang uint64_t
298a9643ea8Slogwang lthread_mutex_diag_ref(struct lthread_mutex *m);
299a9643ea8Slogwang 
3002bfe3f2eSlogwang #ifdef __cplusplus
3012bfe3f2eSlogwang }
3022bfe3f2eSlogwang #endif
3032bfe3f2eSlogwang 
304a9643ea8Slogwang #endif				/* LTHREAD_DIAG_API_H_ */
305