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