osnoise.c (22315B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2021 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org> 4 */ 5 6#include <sys/types.h> 7#include <sys/stat.h> 8#include <pthread.h> 9#include <stdlib.h> 10#include <string.h> 11#include <unistd.h> 12#include <errno.h> 13#include <fcntl.h> 14#include <stdio.h> 15 16#include "osnoise.h" 17#include "utils.h" 18 19/* 20 * osnoise_get_cpus - return the original "osnoise/cpus" content 21 * 22 * It also saves the value to be restored. 23 */ 24char *osnoise_get_cpus(struct osnoise_context *context) 25{ 26 if (context->curr_cpus) 27 return context->curr_cpus; 28 29 if (context->orig_cpus) 30 return context->orig_cpus; 31 32 context->orig_cpus = tracefs_instance_file_read(NULL, "osnoise/cpus", NULL); 33 34 /* 35 * The error value (NULL) is the same for tracefs_instance_file_read() 36 * and this functions, so: 37 */ 38 return context->orig_cpus; 39} 40 41/* 42 * osnoise_set_cpus - configure osnoise to run on *cpus 43 * 44 * "osnoise/cpus" file is used to set the cpus in which osnoise/timerlat 45 * will run. This function opens this file, saves the current value, 46 * and set the cpus passed as argument. 47 */ 48int osnoise_set_cpus(struct osnoise_context *context, char *cpus) 49{ 50 char *orig_cpus = osnoise_get_cpus(context); 51 char buffer[1024]; 52 int retval; 53 54 if (!orig_cpus) 55 return -1; 56 57 context->curr_cpus = strdup(cpus); 58 if (!context->curr_cpus) 59 return -1; 60 61 snprintf(buffer, 1024, "%s\n", cpus); 62 63 debug_msg("setting cpus to %s from %s", cpus, context->orig_cpus); 64 65 retval = tracefs_instance_file_write(NULL, "osnoise/cpus", buffer); 66 if (retval < 0) { 67 free(context->curr_cpus); 68 context->curr_cpus = NULL; 69 return -1; 70 } 71 72 return 0; 73} 74 75/* 76 * osnoise_restore_cpus - restore the original "osnoise/cpus" 77 * 78 * osnoise_set_cpus() saves the original data for the "osnoise/cpus" 79 * file. This function restore the original config it was previously 80 * modified. 81 */ 82void osnoise_restore_cpus(struct osnoise_context *context) 83{ 84 int retval; 85 86 if (!context->orig_cpus) 87 return; 88 89 if (!context->curr_cpus) 90 return; 91 92 /* nothing to do? */ 93 if (!strcmp(context->orig_cpus, context->curr_cpus)) 94 goto out_done; 95 96 debug_msg("restoring cpus to %s", context->orig_cpus); 97 98 retval = tracefs_instance_file_write(NULL, "osnoise/cpus", context->orig_cpus); 99 if (retval < 0) 100 err_msg("could not restore original osnoise cpus\n"); 101 102out_done: 103 free(context->curr_cpus); 104 context->curr_cpus = NULL; 105} 106 107/* 108 * osnoise_put_cpus - restore cpus config and cleanup data 109 */ 110void osnoise_put_cpus(struct osnoise_context *context) 111{ 112 osnoise_restore_cpus(context); 113 114 if (!context->orig_cpus) 115 return; 116 117 free(context->orig_cpus); 118 context->orig_cpus = NULL; 119} 120 121/* 122 * osnoise_read_ll_config - read a long long value from a config 123 * 124 * returns -1 on error. 125 */ 126static long long osnoise_read_ll_config(char *rel_path) 127{ 128 long long retval; 129 char *buffer; 130 131 buffer = tracefs_instance_file_read(NULL, rel_path, NULL); 132 if (!buffer) 133 return -1; 134 135 /* get_llong_from_str returns -1 on error */ 136 retval = get_llong_from_str(buffer); 137 138 debug_msg("reading %s returned %lld\n", rel_path, retval); 139 140 free(buffer); 141 142 return retval; 143} 144 145/* 146 * osnoise_write_ll_config - write a long long value to a config in rel_path 147 * 148 * returns -1 on error. 149 */ 150static long long osnoise_write_ll_config(char *rel_path, long long value) 151{ 152 char buffer[BUFF_U64_STR_SIZE]; 153 long long retval; 154 155 snprintf(buffer, sizeof(buffer), "%lld\n", value); 156 157 debug_msg("setting %s to %lld\n", rel_path, value); 158 159 retval = tracefs_instance_file_write(NULL, rel_path, buffer); 160 return retval; 161} 162 163/* 164 * osnoise_get_runtime - return the original "osnoise/runtime_us" value 165 * 166 * It also saves the value to be restored. 167 */ 168unsigned long long osnoise_get_runtime(struct osnoise_context *context) 169{ 170 long long runtime_us; 171 172 if (context->runtime_us != OSNOISE_TIME_INIT_VAL) 173 return context->runtime_us; 174 175 if (context->orig_runtime_us != OSNOISE_TIME_INIT_VAL) 176 return context->orig_runtime_us; 177 178 runtime_us = osnoise_read_ll_config("osnoise/runtime_us"); 179 if (runtime_us < 0) 180 goto out_err; 181 182 context->orig_runtime_us = runtime_us; 183 return runtime_us; 184 185out_err: 186 return OSNOISE_TIME_INIT_VAL; 187} 188 189/* 190 * osnoise_get_period - return the original "osnoise/period_us" value 191 * 192 * It also saves the value to be restored. 193 */ 194unsigned long long osnoise_get_period(struct osnoise_context *context) 195{ 196 long long period_us; 197 198 if (context->period_us != OSNOISE_TIME_INIT_VAL) 199 return context->period_us; 200 201 if (context->orig_period_us != OSNOISE_TIME_INIT_VAL) 202 return context->orig_period_us; 203 204 period_us = osnoise_read_ll_config("osnoise/period_us"); 205 if (period_us < 0) 206 goto out_err; 207 208 context->orig_period_us = period_us; 209 return period_us; 210 211out_err: 212 return OSNOISE_TIME_INIT_VAL; 213} 214 215static int __osnoise_write_runtime(struct osnoise_context *context, 216 unsigned long long runtime) 217{ 218 int retval; 219 220 if (context->orig_runtime_us == OSNOISE_TIME_INIT_VAL) 221 return -1; 222 223 retval = osnoise_write_ll_config("osnoise/runtime_us", runtime); 224 if (retval < 0) 225 return -1; 226 227 context->runtime_us = runtime; 228 return 0; 229} 230 231static int __osnoise_write_period(struct osnoise_context *context, 232 unsigned long long period) 233{ 234 int retval; 235 236 if (context->orig_period_us == OSNOISE_TIME_INIT_VAL) 237 return -1; 238 239 retval = osnoise_write_ll_config("osnoise/period_us", period); 240 if (retval < 0) 241 return -1; 242 243 context->period_us = period; 244 return 0; 245} 246 247/* 248 * osnoise_set_runtime_period - set osnoise runtime and period 249 * 250 * Osnoise's runtime and period are related as runtime <= period. 251 * Thus, this function saves the original values, and then tries 252 * to set the runtime and period if they are != 0. 253 */ 254int osnoise_set_runtime_period(struct osnoise_context *context, 255 unsigned long long runtime, 256 unsigned long long period) 257{ 258 unsigned long long curr_runtime_us; 259 unsigned long long curr_period_us; 260 int retval; 261 262 if (!period && !runtime) 263 return 0; 264 265 curr_runtime_us = osnoise_get_runtime(context); 266 curr_period_us = osnoise_get_period(context); 267 268 /* error getting any value? */ 269 if (curr_period_us == OSNOISE_TIME_INIT_VAL || curr_runtime_us == OSNOISE_TIME_INIT_VAL) 270 return -1; 271 272 if (!period) { 273 if (runtime > curr_period_us) 274 return -1; 275 return __osnoise_write_runtime(context, runtime); 276 } else if (!runtime) { 277 if (period < curr_runtime_us) 278 return -1; 279 return __osnoise_write_period(context, period); 280 } 281 282 if (runtime > curr_period_us) { 283 retval = __osnoise_write_period(context, period); 284 if (retval) 285 return -1; 286 retval = __osnoise_write_runtime(context, runtime); 287 if (retval) 288 return -1; 289 } else { 290 retval = __osnoise_write_runtime(context, runtime); 291 if (retval) 292 return -1; 293 retval = __osnoise_write_period(context, period); 294 if (retval) 295 return -1; 296 } 297 298 return 0; 299} 300 301/* 302 * osnoise_restore_runtime_period - restore the original runtime and period 303 */ 304void osnoise_restore_runtime_period(struct osnoise_context *context) 305{ 306 unsigned long long orig_runtime = context->orig_runtime_us; 307 unsigned long long orig_period = context->orig_period_us; 308 unsigned long long curr_runtime = context->runtime_us; 309 unsigned long long curr_period = context->period_us; 310 int retval; 311 312 if ((orig_runtime == OSNOISE_TIME_INIT_VAL) && (orig_period == OSNOISE_TIME_INIT_VAL)) 313 return; 314 315 if ((orig_period == curr_period) && (orig_runtime == curr_runtime)) 316 goto out_done; 317 318 retval = osnoise_set_runtime_period(context, orig_runtime, orig_period); 319 if (retval) 320 err_msg("Could not restore original osnoise runtime/period\n"); 321 322out_done: 323 context->runtime_us = OSNOISE_TIME_INIT_VAL; 324 context->period_us = OSNOISE_TIME_INIT_VAL; 325} 326 327/* 328 * osnoise_put_runtime_period - restore original values and cleanup data 329 */ 330void osnoise_put_runtime_period(struct osnoise_context *context) 331{ 332 osnoise_restore_runtime_period(context); 333 334 if (context->orig_runtime_us != OSNOISE_TIME_INIT_VAL) 335 context->orig_runtime_us = OSNOISE_TIME_INIT_VAL; 336 337 if (context->orig_period_us != OSNOISE_TIME_INIT_VAL) 338 context->orig_period_us = OSNOISE_TIME_INIT_VAL; 339} 340 341/* 342 * osnoise_get_timerlat_period_us - read and save the original "timerlat_period_us" 343 */ 344static long long 345osnoise_get_timerlat_period_us(struct osnoise_context *context) 346{ 347 long long timerlat_period_us; 348 349 if (context->timerlat_period_us != OSNOISE_TIME_INIT_VAL) 350 return context->timerlat_period_us; 351 352 if (context->orig_timerlat_period_us != OSNOISE_TIME_INIT_VAL) 353 return context->orig_timerlat_period_us; 354 355 timerlat_period_us = osnoise_read_ll_config("osnoise/timerlat_period_us"); 356 if (timerlat_period_us < 0) 357 goto out_err; 358 359 context->orig_timerlat_period_us = timerlat_period_us; 360 return timerlat_period_us; 361 362out_err: 363 return OSNOISE_TIME_INIT_VAL; 364} 365 366/* 367 * osnoise_set_timerlat_period_us - set "timerlat_period_us" 368 */ 369int osnoise_set_timerlat_period_us(struct osnoise_context *context, long long timerlat_period_us) 370{ 371 long long curr_timerlat_period_us = osnoise_get_timerlat_period_us(context); 372 int retval; 373 374 if (curr_timerlat_period_us == OSNOISE_TIME_INIT_VAL) 375 return -1; 376 377 retval = osnoise_write_ll_config("osnoise/timerlat_period_us", timerlat_period_us); 378 if (retval < 0) 379 return -1; 380 381 context->timerlat_period_us = timerlat_period_us; 382 383 return 0; 384} 385 386/* 387 * osnoise_restore_timerlat_period_us - restore "timerlat_period_us" 388 */ 389void osnoise_restore_timerlat_period_us(struct osnoise_context *context) 390{ 391 int retval; 392 393 if (context->orig_timerlat_period_us == OSNOISE_TIME_INIT_VAL) 394 return; 395 396 if (context->orig_timerlat_period_us == context->timerlat_period_us) 397 goto out_done; 398 399 retval = osnoise_write_ll_config("osnoise/timerlat_period_us", context->orig_timerlat_period_us); 400 if (retval < 0) 401 err_msg("Could not restore original osnoise timerlat_period_us\n"); 402 403out_done: 404 context->timerlat_period_us = OSNOISE_TIME_INIT_VAL; 405} 406 407/* 408 * osnoise_put_timerlat_period_us - restore original values and cleanup data 409 */ 410void osnoise_put_timerlat_period_us(struct osnoise_context *context) 411{ 412 osnoise_restore_timerlat_period_us(context); 413 414 if (context->orig_timerlat_period_us == OSNOISE_TIME_INIT_VAL) 415 return; 416 417 context->orig_timerlat_period_us = OSNOISE_TIME_INIT_VAL; 418} 419 420/* 421 * osnoise_get_stop_us - read and save the original "stop_tracing_us" 422 */ 423static long long 424osnoise_get_stop_us(struct osnoise_context *context) 425{ 426 long long stop_us; 427 428 if (context->stop_us != OSNOISE_OPTION_INIT_VAL) 429 return context->stop_us; 430 431 if (context->orig_stop_us != OSNOISE_OPTION_INIT_VAL) 432 return context->orig_stop_us; 433 434 stop_us = osnoise_read_ll_config("osnoise/stop_tracing_us"); 435 if (stop_us < 0) 436 goto out_err; 437 438 context->orig_stop_us = stop_us; 439 return stop_us; 440 441out_err: 442 return OSNOISE_OPTION_INIT_VAL; 443} 444 445/* 446 * osnoise_set_stop_us - set "stop_tracing_us" 447 */ 448int osnoise_set_stop_us(struct osnoise_context *context, long long stop_us) 449{ 450 long long curr_stop_us = osnoise_get_stop_us(context); 451 int retval; 452 453 if (curr_stop_us == OSNOISE_OPTION_INIT_VAL) 454 return -1; 455 456 retval = osnoise_write_ll_config("osnoise/stop_tracing_us", stop_us); 457 if (retval < 0) 458 return -1; 459 460 context->stop_us = stop_us; 461 462 return 0; 463} 464 465/* 466 * osnoise_restore_stop_us - restore the original "stop_tracing_us" 467 */ 468void osnoise_restore_stop_us(struct osnoise_context *context) 469{ 470 int retval; 471 472 if (context->orig_stop_us == OSNOISE_OPTION_INIT_VAL) 473 return; 474 475 if (context->orig_stop_us == context->stop_us) 476 goto out_done; 477 478 retval = osnoise_write_ll_config("osnoise/stop_tracing_us", context->orig_stop_us); 479 if (retval < 0) 480 err_msg("Could not restore original osnoise stop_us\n"); 481 482out_done: 483 context->stop_us = OSNOISE_OPTION_INIT_VAL; 484} 485 486/* 487 * osnoise_put_stop_us - restore original values and cleanup data 488 */ 489void osnoise_put_stop_us(struct osnoise_context *context) 490{ 491 osnoise_restore_stop_us(context); 492 493 if (context->orig_stop_us == OSNOISE_OPTION_INIT_VAL) 494 return; 495 496 context->orig_stop_us = OSNOISE_OPTION_INIT_VAL; 497} 498 499/* 500 * osnoise_get_stop_total_us - read and save the original "stop_tracing_total_us" 501 */ 502static long long 503osnoise_get_stop_total_us(struct osnoise_context *context) 504{ 505 long long stop_total_us; 506 507 if (context->stop_total_us != OSNOISE_OPTION_INIT_VAL) 508 return context->stop_total_us; 509 510 if (context->orig_stop_total_us != OSNOISE_OPTION_INIT_VAL) 511 return context->orig_stop_total_us; 512 513 stop_total_us = osnoise_read_ll_config("osnoise/stop_tracing_total_us"); 514 if (stop_total_us < 0) 515 goto out_err; 516 517 context->orig_stop_total_us = stop_total_us; 518 return stop_total_us; 519 520out_err: 521 return OSNOISE_OPTION_INIT_VAL; 522} 523 524/* 525 * osnoise_set_stop_total_us - set "stop_tracing_total_us" 526 */ 527int osnoise_set_stop_total_us(struct osnoise_context *context, long long stop_total_us) 528{ 529 long long curr_stop_total_us = osnoise_get_stop_total_us(context); 530 int retval; 531 532 if (curr_stop_total_us == OSNOISE_OPTION_INIT_VAL) 533 return -1; 534 535 retval = osnoise_write_ll_config("osnoise/stop_tracing_total_us", stop_total_us); 536 if (retval < 0) 537 return -1; 538 539 context->stop_total_us = stop_total_us; 540 541 return 0; 542} 543 544/* 545 * osnoise_restore_stop_total_us - restore the original "stop_tracing_total_us" 546 */ 547void osnoise_restore_stop_total_us(struct osnoise_context *context) 548{ 549 int retval; 550 551 if (context->orig_stop_total_us == OSNOISE_OPTION_INIT_VAL) 552 return; 553 554 if (context->orig_stop_total_us == context->stop_total_us) 555 goto out_done; 556 557 retval = osnoise_write_ll_config("osnoise/stop_tracing_total_us", 558 context->orig_stop_total_us); 559 if (retval < 0) 560 err_msg("Could not restore original osnoise stop_total_us\n"); 561 562out_done: 563 context->stop_total_us = OSNOISE_OPTION_INIT_VAL; 564} 565 566/* 567 * osnoise_put_stop_total_us - restore original values and cleanup data 568 */ 569void osnoise_put_stop_total_us(struct osnoise_context *context) 570{ 571 osnoise_restore_stop_total_us(context); 572 573 if (context->orig_stop_total_us == OSNOISE_OPTION_INIT_VAL) 574 return; 575 576 context->orig_stop_total_us = OSNOISE_OPTION_INIT_VAL; 577} 578 579/* 580 * osnoise_get_print_stack - read and save the original "print_stack" 581 */ 582static long long 583osnoise_get_print_stack(struct osnoise_context *context) 584{ 585 long long print_stack; 586 587 if (context->print_stack != OSNOISE_OPTION_INIT_VAL) 588 return context->print_stack; 589 590 if (context->orig_print_stack != OSNOISE_OPTION_INIT_VAL) 591 return context->orig_print_stack; 592 593 print_stack = osnoise_read_ll_config("osnoise/print_stack"); 594 if (print_stack < 0) 595 goto out_err; 596 597 context->orig_print_stack = print_stack; 598 return print_stack; 599 600out_err: 601 return OSNOISE_OPTION_INIT_VAL; 602} 603 604/* 605 * osnoise_set_print_stack - set "print_stack" 606 */ 607int osnoise_set_print_stack(struct osnoise_context *context, long long print_stack) 608{ 609 long long curr_print_stack = osnoise_get_print_stack(context); 610 int retval; 611 612 if (curr_print_stack == OSNOISE_OPTION_INIT_VAL) 613 return -1; 614 615 retval = osnoise_write_ll_config("osnoise/print_stack", print_stack); 616 if (retval < 0) 617 return -1; 618 619 context->print_stack = print_stack; 620 621 return 0; 622} 623 624/* 625 * osnoise_restore_print_stack - restore the original "print_stack" 626 */ 627void osnoise_restore_print_stack(struct osnoise_context *context) 628{ 629 int retval; 630 631 if (context->orig_print_stack == OSNOISE_OPTION_INIT_VAL) 632 return; 633 634 if (context->orig_print_stack == context->print_stack) 635 goto out_done; 636 637 retval = osnoise_write_ll_config("osnoise/print_stack", context->orig_print_stack); 638 if (retval < 0) 639 err_msg("Could not restore original osnoise print_stack\n"); 640 641out_done: 642 context->print_stack = OSNOISE_OPTION_INIT_VAL; 643} 644 645/* 646 * osnoise_put_print_stack - restore original values and cleanup data 647 */ 648void osnoise_put_print_stack(struct osnoise_context *context) 649{ 650 osnoise_restore_print_stack(context); 651 652 if (context->orig_print_stack == OSNOISE_OPTION_INIT_VAL) 653 return; 654 655 context->orig_print_stack = OSNOISE_OPTION_INIT_VAL; 656} 657 658/* 659 * osnoise_get_tracing_thresh - read and save the original "tracing_thresh" 660 */ 661static long long 662osnoise_get_tracing_thresh(struct osnoise_context *context) 663{ 664 long long tracing_thresh; 665 666 if (context->tracing_thresh != OSNOISE_OPTION_INIT_VAL) 667 return context->tracing_thresh; 668 669 if (context->orig_tracing_thresh != OSNOISE_OPTION_INIT_VAL) 670 return context->orig_tracing_thresh; 671 672 tracing_thresh = osnoise_read_ll_config("tracing_thresh"); 673 if (tracing_thresh < 0) 674 goto out_err; 675 676 context->orig_tracing_thresh = tracing_thresh; 677 return tracing_thresh; 678 679out_err: 680 return OSNOISE_OPTION_INIT_VAL; 681} 682 683/* 684 * osnoise_set_tracing_thresh - set "tracing_thresh" 685 */ 686int osnoise_set_tracing_thresh(struct osnoise_context *context, long long tracing_thresh) 687{ 688 long long curr_tracing_thresh = osnoise_get_tracing_thresh(context); 689 int retval; 690 691 if (curr_tracing_thresh == OSNOISE_OPTION_INIT_VAL) 692 return -1; 693 694 retval = osnoise_write_ll_config("tracing_thresh", tracing_thresh); 695 if (retval < 0) 696 return -1; 697 698 context->tracing_thresh = tracing_thresh; 699 700 return 0; 701} 702 703/* 704 * osnoise_restore_tracing_thresh - restore the original "tracing_thresh" 705 */ 706void osnoise_restore_tracing_thresh(struct osnoise_context *context) 707{ 708 int retval; 709 710 if (context->orig_tracing_thresh == OSNOISE_OPTION_INIT_VAL) 711 return; 712 713 if (context->orig_tracing_thresh == context->tracing_thresh) 714 goto out_done; 715 716 retval = osnoise_write_ll_config("tracing_thresh", context->orig_tracing_thresh); 717 if (retval < 0) 718 err_msg("Could not restore original tracing_thresh\n"); 719 720out_done: 721 context->tracing_thresh = OSNOISE_OPTION_INIT_VAL; 722} 723 724/* 725 * osnoise_put_tracing_thresh - restore original values and cleanup data 726 */ 727void osnoise_put_tracing_thresh(struct osnoise_context *context) 728{ 729 osnoise_restore_tracing_thresh(context); 730 731 if (context->orig_tracing_thresh == OSNOISE_OPTION_INIT_VAL) 732 return; 733 734 context->orig_tracing_thresh = OSNOISE_OPTION_INIT_VAL; 735} 736 737/* 738 * enable_osnoise - enable osnoise tracer in the trace_instance 739 */ 740int enable_osnoise(struct trace_instance *trace) 741{ 742 return enable_tracer_by_name(trace->inst, "osnoise"); 743} 744 745/* 746 * enable_timerlat - enable timerlat tracer in the trace_instance 747 */ 748int enable_timerlat(struct trace_instance *trace) 749{ 750 return enable_tracer_by_name(trace->inst, "timerlat"); 751} 752 753enum { 754 FLAG_CONTEXT_NEWLY_CREATED = (1 << 0), 755 FLAG_CONTEXT_DELETED = (1 << 1), 756}; 757 758/* 759 * osnoise_get_context - increase the usage of a context and return it 760 */ 761int osnoise_get_context(struct osnoise_context *context) 762{ 763 int ret; 764 765 if (context->flags & FLAG_CONTEXT_DELETED) { 766 ret = -1; 767 } else { 768 context->ref++; 769 ret = 0; 770 } 771 772 return ret; 773} 774 775/* 776 * osnoise_context_alloc - alloc an osnoise_context 777 * 778 * The osnoise context contains the information of the "osnoise/" configs. 779 * It is used to set and restore the config. 780 */ 781struct osnoise_context *osnoise_context_alloc(void) 782{ 783 struct osnoise_context *context; 784 785 context = calloc(1, sizeof(*context)); 786 if (!context) 787 return NULL; 788 789 context->orig_stop_us = OSNOISE_OPTION_INIT_VAL; 790 context->stop_us = OSNOISE_OPTION_INIT_VAL; 791 792 context->orig_stop_total_us = OSNOISE_OPTION_INIT_VAL; 793 context->stop_total_us = OSNOISE_OPTION_INIT_VAL; 794 795 context->orig_print_stack = OSNOISE_OPTION_INIT_VAL; 796 context->print_stack = OSNOISE_OPTION_INIT_VAL; 797 798 context->orig_tracing_thresh = OSNOISE_OPTION_INIT_VAL; 799 context->tracing_thresh = OSNOISE_OPTION_INIT_VAL; 800 801 osnoise_get_context(context); 802 803 return context; 804} 805 806/* 807 * osnoise_put_context - put the osnoise_put_context 808 * 809 * If there is no other user for the context, the original data 810 * is restored. 811 */ 812void osnoise_put_context(struct osnoise_context *context) 813{ 814 if (--context->ref < 1) 815 context->flags |= FLAG_CONTEXT_DELETED; 816 817 if (!(context->flags & FLAG_CONTEXT_DELETED)) 818 return; 819 820 osnoise_put_cpus(context); 821 osnoise_put_runtime_period(context); 822 osnoise_put_stop_us(context); 823 osnoise_put_stop_total_us(context); 824 osnoise_put_timerlat_period_us(context); 825 osnoise_put_print_stack(context); 826 osnoise_put_tracing_thresh(context); 827 828 free(context); 829} 830 831/* 832 * osnoise_destroy_tool - disable trace, restore configs and free data 833 */ 834void osnoise_destroy_tool(struct osnoise_tool *top) 835{ 836 if (!top) 837 return; 838 839 trace_instance_destroy(&top->trace); 840 841 if (top->context) 842 osnoise_put_context(top->context); 843 844 free(top); 845} 846 847/* 848 * osnoise_init_tool - init an osnoise tool 849 * 850 * It allocs data, create a context to store data and 851 * creates a new trace instance for the tool. 852 */ 853struct osnoise_tool *osnoise_init_tool(char *tool_name) 854{ 855 struct osnoise_tool *top; 856 int retval; 857 858 top = calloc(1, sizeof(*top)); 859 if (!top) 860 return NULL; 861 862 top->context = osnoise_context_alloc(); 863 if (!top->context) 864 goto out_err; 865 866 retval = trace_instance_init(&top->trace, tool_name); 867 if (retval) 868 goto out_err; 869 870 return top; 871out_err: 872 osnoise_destroy_tool(top); 873 return NULL; 874} 875 876/* 877 * osnoise_init_trace_tool - init a tracer instance to trace osnoise events 878 */ 879struct osnoise_tool *osnoise_init_trace_tool(char *tracer) 880{ 881 struct osnoise_tool *trace; 882 int retval; 883 884 trace = osnoise_init_tool("osnoise_trace"); 885 if (!trace) 886 return NULL; 887 888 retval = tracefs_event_enable(trace->trace.inst, "osnoise", NULL); 889 if (retval < 0 && !errno) { 890 err_msg("Could not find osnoise events\n"); 891 goto out_err; 892 } 893 894 retval = enable_tracer_by_name(trace->trace.inst, tracer); 895 if (retval) { 896 err_msg("Could not enable %s tracer for tracing\n", tracer); 897 goto out_err; 898 } 899 900 return trace; 901out_err: 902 osnoise_destroy_tool(trace); 903 return NULL; 904} 905 906static void osnoise_usage(void) 907{ 908 int i; 909 910 static const char *msg[] = { 911 "", 912 "osnoise version " VERSION, 913 "", 914 " usage: [rtla] osnoise [MODE] ...", 915 "", 916 " modes:", 917 " top - prints the summary from osnoise tracer", 918 " hist - prints a histogram of osnoise samples", 919 "", 920 "if no MODE is given, the top mode is called, passing the arguments", 921 NULL, 922 }; 923 924 for (i = 0; msg[i]; i++) 925 fprintf(stderr, "%s\n", msg[i]); 926 exit(1); 927} 928 929int osnoise_main(int argc, char *argv[]) 930{ 931 if (argc == 0) 932 goto usage; 933 934 /* 935 * if osnoise was called without any argument, run the 936 * default cmdline. 937 */ 938 if (argc == 1) { 939 osnoise_top_main(argc, argv); 940 exit(0); 941 } 942 943 if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) { 944 osnoise_usage(); 945 exit(0); 946 } else if (strncmp(argv[1], "-", 1) == 0) { 947 /* the user skipped the tool, call the default one */ 948 osnoise_top_main(argc, argv); 949 exit(0); 950 } else if (strcmp(argv[1], "top") == 0) { 951 osnoise_top_main(argc-1, &argv[1]); 952 exit(0); 953 } else if (strcmp(argv[1], "hist") == 0) { 954 osnoise_hist_main(argc-1, &argv[1]); 955 exit(0); 956 } 957 958usage: 959 osnoise_usage(); 960 exit(1); 961}