17
17
#include "timerlat.h"
18
18
#include "timerlat_aa.h"
19
19
#include "timerlat_u.h"
20
+ #include "timerlat_bpf.h"
20
21
21
22
struct timerlat_hist_cpu {
22
23
int * irq ;
@@ -193,6 +194,89 @@ timerlat_hist_handler(struct trace_seq *s, struct tep_record *record,
193
194
return 0 ;
194
195
}
195
196
197
+ /*
198
+ * timerlat_hist_bpf_pull_data - copy data from BPF maps into userspace
199
+ */
200
+ static int timerlat_hist_bpf_pull_data (struct osnoise_tool * tool )
201
+ {
202
+ struct timerlat_hist_data * data = tool -> data ;
203
+ int i , j , err ;
204
+ long long value_irq [data -> nr_cpus ],
205
+ value_thread [data -> nr_cpus ],
206
+ value_user [data -> nr_cpus ];
207
+
208
+ /* Pull histogram */
209
+ for (i = 0 ; i < data -> entries ; i ++ ) {
210
+ err = timerlat_bpf_get_hist_value (i , value_irq , value_thread ,
211
+ value_user , data -> nr_cpus );
212
+ if (err )
213
+ return err ;
214
+ for (j = 0 ; j < data -> nr_cpus ; j ++ ) {
215
+ data -> hist [j ].irq [i ] = value_irq [j ];
216
+ data -> hist [j ].thread [i ] = value_thread [j ];
217
+ data -> hist [j ].user [i ] = value_user [j ];
218
+ }
219
+ }
220
+
221
+ /* Pull summary */
222
+ err = timerlat_bpf_get_summary_value (SUMMARY_COUNT ,
223
+ value_irq , value_thread , value_user ,
224
+ data -> nr_cpus );
225
+ if (err )
226
+ return err ;
227
+ for (i = 0 ; i < data -> nr_cpus ; i ++ ) {
228
+ data -> hist [i ].irq_count = value_irq [i ];
229
+ data -> hist [i ].thread_count = value_thread [i ];
230
+ data -> hist [i ].user_count = value_user [i ];
231
+ }
232
+
233
+ err = timerlat_bpf_get_summary_value (SUMMARY_MIN ,
234
+ value_irq , value_thread , value_user ,
235
+ data -> nr_cpus );
236
+ if (err )
237
+ return err ;
238
+ for (i = 0 ; i < data -> nr_cpus ; i ++ ) {
239
+ data -> hist [i ].min_irq = value_irq [i ];
240
+ data -> hist [i ].min_thread = value_thread [i ];
241
+ data -> hist [i ].min_user = value_user [i ];
242
+ }
243
+
244
+ err = timerlat_bpf_get_summary_value (SUMMARY_MAX ,
245
+ value_irq , value_thread , value_user ,
246
+ data -> nr_cpus );
247
+ if (err )
248
+ return err ;
249
+ for (i = 0 ; i < data -> nr_cpus ; i ++ ) {
250
+ data -> hist [i ].max_irq = value_irq [i ];
251
+ data -> hist [i ].max_thread = value_thread [i ];
252
+ data -> hist [i ].max_user = value_user [i ];
253
+ }
254
+
255
+ err = timerlat_bpf_get_summary_value (SUMMARY_SUM ,
256
+ value_irq , value_thread , value_user ,
257
+ data -> nr_cpus );
258
+ if (err )
259
+ return err ;
260
+ for (i = 0 ; i < data -> nr_cpus ; i ++ ) {
261
+ data -> hist [i ].sum_irq = value_irq [i ];
262
+ data -> hist [i ].sum_thread = value_thread [i ];
263
+ data -> hist [i ].sum_user = value_user [i ];
264
+ }
265
+
266
+ err = timerlat_bpf_get_summary_value (SUMMARY_OVERFLOW ,
267
+ value_irq , value_thread , value_user ,
268
+ data -> nr_cpus );
269
+ if (err )
270
+ return err ;
271
+ for (i = 0 ; i < data -> nr_cpus ; i ++ ) {
272
+ data -> hist [i ].irq [data -> entries ] = value_irq [i ];
273
+ data -> hist [i ].thread [data -> entries ] = value_thread [i ];
274
+ data -> hist [i ].user [data -> entries ] = value_user [i ];
275
+ }
276
+
277
+ return 0 ;
278
+ }
279
+
196
280
/*
197
281
* timerlat_hist_header - print the header of the tracer to the output
198
282
*/
@@ -1152,6 +1236,7 @@ int timerlat_hist_main(int argc, char *argv[])
1152
1236
pthread_t timerlat_u ;
1153
1237
int retval ;
1154
1238
int nr_cpus , i ;
1239
+ bool no_bpf = false;
1155
1240
1156
1241
params = timerlat_hist_parse_args (argc , argv );
1157
1242
if (!params )
@@ -1177,6 +1262,24 @@ int timerlat_hist_main(int argc, char *argv[])
1177
1262
*/
1178
1263
hist_inst = trace ;
1179
1264
1265
+ if (getenv ("RTLA_NO_BPF" ) && strncmp (getenv ("RTLA_NO_BPF" ), "1" , 2 ) == 0 ) {
1266
+ debug_msg ("RTLA_NO_BPF set, disabling BPF\n" );
1267
+ no_bpf = true;
1268
+ }
1269
+
1270
+ if (!no_bpf && !tep_find_event_by_name (trace -> tep , "osnoise" , "timerlat_sample" )) {
1271
+ debug_msg ("osnoise:timerlat_sample missing, disabling BPF\n" );
1272
+ no_bpf = true;
1273
+ }
1274
+
1275
+ if (!no_bpf ) {
1276
+ retval = timerlat_bpf_init (params );
1277
+ if (retval ) {
1278
+ debug_msg ("Could not enable BPF\n" );
1279
+ no_bpf = true;
1280
+ }
1281
+ }
1282
+
1180
1283
retval = enable_timerlat (trace );
1181
1284
if (retval ) {
1182
1285
err_msg ("Failed to enable timerlat tracer\n" );
@@ -1304,35 +1407,55 @@ int timerlat_hist_main(int argc, char *argv[])
1304
1407
trace_instance_start (& record -> trace );
1305
1408
if (!params -> no_aa )
1306
1409
trace_instance_start (& aa -> trace );
1307
- trace_instance_start (trace );
1410
+ if (no_bpf ) {
1411
+ trace_instance_start (trace );
1412
+ } else {
1413
+ retval = timerlat_bpf_attach ();
1414
+ if (retval ) {
1415
+ err_msg ("Error attaching BPF program\n" );
1416
+ goto out_hist ;
1417
+ }
1418
+ }
1308
1419
1309
1420
tool -> start_time = time (NULL );
1310
1421
timerlat_hist_set_signals (params );
1311
1422
1312
- while (!stop_tracing ) {
1313
- sleep (params -> sleep_time );
1314
-
1315
- retval = tracefs_iterate_raw_events (trace -> tep ,
1316
- trace -> inst ,
1317
- NULL ,
1318
- 0 ,
1319
- collect_registered_events ,
1320
- trace );
1321
- if (retval < 0 ) {
1322
- err_msg ("Error iterating on events\n" );
1323
- goto out_hist ;
1324
- }
1325
-
1326
- if (osnoise_trace_is_off (tool , record ))
1327
- break ;
1423
+ if (no_bpf ) {
1424
+ while (!stop_tracing ) {
1425
+ sleep (params -> sleep_time );
1426
+
1427
+ retval = tracefs_iterate_raw_events (trace -> tep ,
1428
+ trace -> inst ,
1429
+ NULL ,
1430
+ 0 ,
1431
+ collect_registered_events ,
1432
+ trace );
1433
+ if (retval < 0 ) {
1434
+ err_msg ("Error iterating on events\n" );
1435
+ goto out_hist ;
1436
+ }
1328
1437
1329
- /* is there still any user-threads ? */
1330
- if (params -> user_workload ) {
1331
- if (params_u .stopped_running ) {
1332
- debug_msg ("timerlat user-space threads stopped!\n" );
1438
+ if (osnoise_trace_is_off (tool , record ))
1333
1439
break ;
1440
+
1441
+ /* is there still any user-threads ? */
1442
+ if (params -> user_workload ) {
1443
+ if (params_u .stopped_running ) {
1444
+ debug_msg ("timerlat user-space threads stopped!\n" );
1445
+ break ;
1446
+ }
1334
1447
}
1335
1448
}
1449
+ } else
1450
+ timerlat_bpf_wait (-1 );
1451
+
1452
+ if (!no_bpf ) {
1453
+ timerlat_bpf_detach ();
1454
+ retval = timerlat_hist_bpf_pull_data (tool );
1455
+ if (retval ) {
1456
+ err_msg ("Error pulling BPF data\n" );
1457
+ goto out_hist ;
1458
+ }
1336
1459
}
1337
1460
1338
1461
if (params -> user_workload && !params_u .stopped_running ) {
@@ -1376,6 +1499,8 @@ int timerlat_hist_main(int argc, char *argv[])
1376
1499
osnoise_destroy_tool (tool );
1377
1500
free (params );
1378
1501
free_cpu_idle_disable_states ();
1502
+ if (!no_bpf )
1503
+ timerlat_bpf_destroy ();
1379
1504
out_exit :
1380
1505
exit (return_value );
1381
1506
}
0 commit comments