oprof_start.cpp revision cc2ee177dbb3befca43e36cfc56778b006c3d050
1/** 2 * @file oprof_start.cpp 3 * The GUI start main class 4 * 5 * @remark Copyright 2002 OProfile authors 6 * @remark Read the file COPYING 7 * 8 * @author Philippe Elie 9 * @author John Levon 10 */ 11 12#include <sys/stat.h> 13#include <unistd.h> 14 15#include <ctime> 16#include <cstdio> 17#include <cmath> 18#include <sstream> 19#include <iostream> 20#include <fstream> 21#include <algorithm> 22 23#include <qlineedit.h> 24#include <qlistview.h> 25#include <qcombobox.h> 26#include <qlistbox.h> 27#include <qfiledialog.h> 28#include <qbuttongroup.h> 29#include <qcheckbox.h> 30#include <qtabwidget.h> 31#include <qmessagebox.h> 32#include <qvalidator.h> 33#include <qlabel.h> 34#include <qpushbutton.h> 35#include <qheader.h> 36 37#include "config.h" 38#include "oprof_start.h" 39#include "op_config.h" 40#include "op_config_24.h" 41#include "string_manip.h" 42#include "op_cpufreq.h" 43#include "op_alloc_counter.h" 44#include "oprof_start_util.h" 45 46#include "op_hw_config.h" 47 48using namespace std; 49 50static char const * green_xpm[] = { 51"16 16 2 1", 52" c None", 53". c #00FF00", 54" ....... ", 55" ........... ", 56" ............. ", 57" ............. ", 58"............... ", 59"............... ", 60"............... ", 61"............... ", 62"............... ", 63"............... ", 64"............... ", 65" ............. ", 66" ............. ", 67" ........... ", 68" ....... ", 69" " }; 70 71static char const * red_xpm[] = { 72"16 16 2 1", 73" c None", 74". c #FF0000", 75" ....... ", 76" ........... ", 77" ............. ", 78" ............. ", 79"............... ", 80"............... ", 81"............... ", 82"............... ", 83"............... ", 84"............... ", 85"............... ", 86" ............. ", 87" ............. ", 88" ........... ", 89" ....... ", 90" " }; 91 92static QPixmap * green_pixmap; 93static QPixmap * red_pixmap; 94 95 96op_event_descr::op_event_descr() 97 : 98 counter_mask(0), 99 val(0), 100 unit(0), 101 min_count(0) 102{ 103} 104 105 106oprof_start::oprof_start() 107 : 108 oprof_start_base(0, 0, false, 0), 109 event_count_validator(new QIntValidator(event_count_edit)), 110 current_event(0), 111 cpu_speed(op_cpu_frequency()), 112 total_nr_interrupts(0) 113{ 114 green_pixmap = new QPixmap(green_xpm); 115 red_pixmap = new QPixmap(red_xpm); 116 vector<string> args; 117 args.push_back("--init"); 118 119 if (do_exec_command(OP_BINDIR "/opcontrol", args)) 120 exit(EXIT_FAILURE); 121 122 cpu_type = op_get_cpu_type(); 123 op_nr_counters = op_get_nr_counters(cpu_type); 124 125 if (cpu_type == CPU_TIMER_INT) { 126 setup_config_tab->removePage(counter_setup_page); 127 } else { 128 fill_events(); 129 } 130 131 op_interface interface = op_get_interface(); 132 if (interface == OP_INTERFACE_NO_GOOD) { 133 QMessageBox::warning(this, 0, "Couldn't determine kernel" 134 " interface version"); 135 exit(EXIT_FAILURE); 136 } 137 bool is_26 = interface == OP_INTERFACE_26; 138 139 if (is_26) { 140 note_table_size_edit->hide(); 141 note_table_size_label->hide(); 142 // FIXME: can adapt to 2.6 ... 143 buffer_size_edit->hide(); 144 buffer_size_label->hide(); 145 } 146 147 // setup the configuration page. 148 kernel_filename_edit->setText(config.kernel_filename.c_str()); 149 150 no_vmlinux->setChecked(config.no_kernel); 151 152 buffer_size_edit->setText(QString().setNum(config.buffer_size)); 153 note_table_size_edit->setText(QString().setNum(config.note_table_size)); 154 verbose->setChecked(config.verbose); 155 separate_lib_cb->setChecked(config.separate_lib); 156 separate_kernel_cb->setChecked(config.separate_kernel); 157 separate_cpu_cb->setChecked(config.separate_cpu); 158 separate_thread_cb->setChecked(config.separate_thread); 159 160 // the unit mask check boxes 161 hide_masks(); 162 163 event_count_edit->setValidator(event_count_validator); 164 QIntValidator * iv; 165 iv = new QIntValidator(OP_MIN_BUF_SIZE, OP_MAX_BUF_SIZE, buffer_size_edit); 166 buffer_size_edit->setValidator(iv); 167 iv = new QIntValidator(OP_MIN_NOTE_TABLE_SIZE, OP_MAX_NOTE_TABLE_SIZE, note_table_size_edit); 168 note_table_size_edit->setValidator(iv); 169 170 // daemon status timer 171 startTimer(5000); 172 timerEvent(0); 173 174 resize(minimumSizeHint()); 175 176 // force the pixmap re-draw 177 event_selected(); 178} 179 180 181void oprof_start::fill_events() 182{ 183 // we need to build the event descr stuff before loading the 184 // configuration because we use locate_event to get an event descr 185 // from its name. 186 struct list_head * pos; 187 struct list_head * events = op_events(cpu_type); 188 189 list_for_each(pos, events) { 190 struct op_event * event = list_entry(pos, struct op_event, event_next); 191 192 op_event_descr descr; 193 194 descr.counter_mask = event->counter_mask; 195 descr.val = event->val; 196 if (event->unit->num) { 197 descr.unit = event->unit; 198 } else { 199 descr.unit = 0; 200 } 201 202 descr.name = event->name; 203 descr.help_str = event->desc; 204 descr.min_count = event->min_count; 205 206 for (uint ctr = 0; ctr < op_nr_counters; ++ctr) { 207 uint count; 208 209 if (!(descr.counter_mask & (1 << ctr))) 210 continue; 211 212 if (cpu_type == CPU_RTC) { 213 count = 1024; 214 } else { 215 /* setting to cpu Hz / 2000 gives a safe value for 216 * all events, and a good one for most. 217 */ 218 if (cpu_speed) 219 count = int(cpu_speed * 500); 220 else 221 count = descr.min_count * 100; 222 } 223 224 event_cfgs[descr.name].count = count; 225 event_cfgs[descr.name].umask = 0; 226 if (descr.unit) 227 event_cfgs[descr.name].umask = descr.unit->default_mask; 228 event_cfgs[descr.name].os_ring_count = 1; 229 event_cfgs[descr.name].user_ring_count = 1; 230 } 231 232 v_events.push_back(descr); 233 } 234 235 events_list->header()->hide(); 236 events_list->setSorting(-1); 237 238 fill_events_listbox(); 239 240 read_set_events(); 241 242 // FIXME: why this ? 243 if (cpu_type == CPU_RTC) 244 events_list->setCurrentItem(events_list->firstChild()); 245 246 load_config_file(); 247} 248 249 250namespace { 251 252/// find the first item with the given text in column 0 or return NULL 253QListViewItem * findItem(QListView * view, char const * name) 254{ 255 // Qt 2.3.1 does not have QListView::findItem() 256 QListViewItem * item = view->firstChild(); 257 258 while (item && strcmp(item->text(0).latin1(), name)) { 259 item = item->nextSibling(); 260 } 261 262 return item; 263} 264 265}; 266 267 268void oprof_start::setup_default_event() 269{ 270 struct op_default_event_descr descr; 271 op_default_event(cpu_type, &descr); 272 273 event_cfgs[descr.name].umask = descr.um; 274 event_cfgs[descr.name].count = descr.count; 275 event_cfgs[descr.name].user_ring_count = 1; 276 event_cfgs[descr.name].os_ring_count = 1; 277 278 QListViewItem * item = findItem(events_list, descr.name); 279 if (item) 280 item->setSelected(true); 281} 282 283 284void oprof_start::read_set_events() 285{ 286 string name = get_user_filename(".oprofile/daemonrc"); 287 288 ifstream in(name.c_str()); 289 290 if (!in) { 291 setup_default_event(); 292 return; 293 } 294 295 string str; 296 297 bool one_enabled = false; 298 299 while (getline(in, str)) { 300 string const val = split(str, '='); 301 string const name = str; 302 303 if (!is_prefix(name, "CHOSEN_EVENTS[")) 304 continue; 305 306 one_enabled = true; 307 308 // CHOSEN_EVENTS[0]=CPU_CLK_UNHALTED:10000:0:1:1 309 vector<string> parts = separate_token(val, ':'); 310 311 if (parts.size() != 5 && parts.size() != 2) { 312 cerr << "invalid configuration file\n"; 313 // FIXME 314 exit(EXIT_FAILURE); 315 } 316 317 string ev_name = parts[0]; 318 event_cfgs[ev_name].count = 319 op_lexical_cast<unsigned int>(parts[1]); 320 321 // CPU_CLK_UNHALTED:10000 is also valid 322 if (parts.size() == 5) { 323 event_cfgs[ev_name].umask = 324 op_lexical_cast<unsigned int>(parts[2]); 325 event_cfgs[ev_name].user_ring_count = 326 op_lexical_cast<unsigned int>(parts[3]); 327 event_cfgs[ev_name].os_ring_count = 328 op_lexical_cast<unsigned int>(parts[4]); 329 } else { 330 event_cfgs[ev_name].umask = 0; 331 event_cfgs[ev_name].user_ring_count = 1; 332 event_cfgs[ev_name].os_ring_count = 1; 333 } 334 335 QListViewItem * item = findItem(events_list, ev_name.c_str()); 336 if (item) 337 item->setSelected(true); 338 } 339 340 // use default event if none set 341 if (!one_enabled) 342 setup_default_event(); 343} 344 345 346void oprof_start::load_config_file() 347{ 348 string name = get_user_filename(".oprofile/daemonrc"); 349 350 ifstream in(name.c_str()); 351 if (!in) { 352 if (!check_and_create_config_dir()) 353 return; 354 355 ofstream out(name.c_str()); 356 if (!out) { 357 QMessageBox::warning(this, 0, "Unable to open configuration " 358 "file ~/.oprofile/daemonrc"); 359 } 360 return; 361 } 362 363 in >> config; 364} 365 366 367// user request a "normal" exit so save the config file. 368void oprof_start::accept() 369{ 370 // record the previous settings 371 record_selected_event_config(); 372 373 save_config(); 374 375 QDialog::accept(); 376} 377 378 379void oprof_start::closeEvent(QCloseEvent *) 380{ 381 accept(); 382} 383 384 385void oprof_start::timerEvent(QTimerEvent *) 386{ 387 static time_t last = time(0); 388 389 daemon_status dstat; 390 391 flush_profiler_data_btn->setEnabled(dstat.running); 392 stop_profiler_btn->setEnabled(dstat.running); 393 start_profiler_btn->setEnabled(!dstat.running); 394 395 if (!dstat.running) { 396 daemon_label->setText("Profiler is not running."); 397 return; 398 } 399 400 ostringstream ss; 401 ss << "Profiler running:"; 402 403 time_t curr = time(0); 404 total_nr_interrupts += dstat.nr_interrupts; 405 406 if (curr - last) 407 ss << " (" << dstat.nr_interrupts / (curr - last) << " interrupts / second, total " << total_nr_interrupts << ")"; 408 409 daemon_label->setText(ss.str().c_str()); 410 411 last = curr; 412} 413 414 415void oprof_start::fill_events_listbox() 416{ 417 setUpdatesEnabled(false); 418 419 for (vector<op_event_descr>::reverse_iterator cit = v_events.rbegin(); 420 cit != v_events.rend(); ++cit) { 421 new QListViewItem(events_list, cit->name.c_str()); 422 } 423 424 setUpdatesEnabled(true); 425 update(); 426} 427 428 429void oprof_start::display_event(op_event_descr const & descr) 430{ 431 setUpdatesEnabled(false); 432 433 setup_unit_masks(descr); 434 os_ring_count_cb->setEnabled(true); 435 user_ring_count_cb->setEnabled(true); 436 event_count_edit->setEnabled(true); 437 438 event_setting & cfg = event_cfgs[descr.name]; 439 440 os_ring_count_cb->setChecked(cfg.os_ring_count); 441 user_ring_count_cb->setChecked(cfg.user_ring_count); 442 QString count_text; 443 count_text.setNum(cfg.count); 444 event_count_edit->setText(count_text); 445 event_count_validator->setRange(descr.min_count, max_perf_count()); 446 447 setUpdatesEnabled(true); 448 update(); 449} 450 451 452bool oprof_start::is_selectable_event(QListViewItem * item) 453{ 454 if (item->isSelected()) 455 return true; 456 457 selected_events.insert(item); 458 459 bool ret = false; 460 if (alloc_selected_events()) 461 ret = true; 462 463 selected_events.erase(item); 464 465 return ret; 466} 467 468 469void oprof_start::draw_event_list() 470{ 471 QListViewItem * cur; 472 for (cur = events_list->firstChild(); cur; cur = cur->nextSibling()) { 473 if (is_selectable_event(cur)) 474 cur->setPixmap(0, *green_pixmap); 475 else 476 cur->setPixmap(0, *red_pixmap); 477 } 478} 479 480 481bool oprof_start::alloc_selected_events() const 482{ 483 vector<op_event const *> events; 484 485 set<QListViewItem *>::const_iterator it; 486 for (it = selected_events.begin(); it != selected_events.end(); ++it) { 487 events.push_back(find_event_by_name((*it)->text(0).latin1())); 488 } 489 490 size_t * map = 491 map_event_to_counter(&events[0], events.size(), cpu_type); 492 493 if (!map) 494 return false; 495 496 free(map); 497 return true; 498} 499 500void oprof_start::event_selected() 501{ 502 // The deal is simple: QT lack of a way to know what item was the last 503 // (de)selected item so we record a set of selected items and diff 504 // it in the appropriate way with the previous list of selected items. 505 506 set<QListViewItem *> current_selection; 507 QListViewItem * cur; 508 for (cur = events_list->firstChild(); cur; cur = cur->nextSibling()) { 509 if (cur->isSelected()) { 510 current_selection.insert(cur); 511 } 512 } 513 514 // First remove the deselected item. 515 vector<QListViewItem *> new_deselected; 516 set_difference(selected_events.begin(), selected_events.end(), 517 current_selection.begin(), current_selection.end(), 518 back_inserter(new_deselected)); 519 vector<QListViewItem *>::const_iterator it; 520 for (it = new_deselected.begin(); it != new_deselected.end(); ++it) { 521 selected_events.erase(*it); 522 } 523 524 // Now try to add the newly selected item if enough HW resource exists 525 vector<QListViewItem *> new_selected; 526 set_difference(current_selection.begin(), current_selection.end(), 527 selected_events.begin(), selected_events.end(), 528 back_inserter(new_selected)); 529 for (it = new_selected.begin(); it != new_selected.end(); ++it) { 530 selected_events.insert(*it); 531 if (!alloc_selected_events()) { 532 (*it)->setSelected(false); 533 selected_events.erase(*it); 534 } else { 535 current_event = *it; 536 } 537 } 538 539 draw_event_list(); 540 541 if (current_event) 542 display_event(locate_event(current_event->text(0).latin1())); 543} 544 545 546void oprof_start::event_over(QListViewItem * item) 547{ 548 op_event_descr const & descr = locate_event(item->text(0).latin1()); 549 550 string help_str = descr.help_str.c_str(); 551 if (!is_selectable_event(item)) { 552 help_str += " conflicts with:"; 553 554 set<QListViewItem *>::const_iterator it; 555 for (it = selected_events.begin(); 556 it != selected_events.end(); ) { 557 QListViewItem * temp = *it; 558 selected_events.erase(it++); 559 if (is_selectable_event(item)) { 560 help_str += " "; 561 help_str += temp->text(0).latin1(); 562 } 563 selected_events.insert(temp); 564 } 565 } 566 567 event_help_label->setText(help_str.c_str()); 568} 569 570 571/// select the kernel image filename 572void oprof_start::choose_kernel_filename() 573{ 574 string name = kernel_filename_edit->text().latin1(); 575 string result = do_open_file_or_dir(name, false); 576 577 if (!result.empty()) 578 kernel_filename_edit->setText(result.c_str()); 579} 580 581 582// this record the current selected event setting in the event_cfg[] stuff. 583// FIXME: need validation? 584void oprof_start::record_selected_event_config() 585{ 586 if (!current_event) 587 return; 588 589 string name(current_event->text(0).latin1()); 590 591 event_setting & cfg = event_cfgs[name]; 592 op_event_descr const & curr = locate_event(name); 593 594 cfg.count = event_count_edit->text().toUInt(); 595 cfg.os_ring_count = os_ring_count_cb->isChecked(); 596 cfg.user_ring_count = user_ring_count_cb->isChecked(); 597 cfg.umask = get_unit_mask(curr); 598} 599 600 601// validate and save the configuration (The qt validator installed 602// are not sufficient to do the validation) 603bool oprof_start::record_config() 604{ 605 config.kernel_filename = kernel_filename_edit->text().latin1(); 606 config.no_kernel = no_vmlinux->isChecked(); 607 608 QString const t = buffer_size_edit->text(); 609 uint temp = t.toUInt(); 610 if (temp < OP_MIN_BUF_SIZE || temp > OP_MAX_BUF_SIZE) { 611 ostringstream error; 612 613 error << "buffer size out of range: " << temp 614 << " valid range is [" << OP_MIN_BUF_SIZE << ", " 615 << OP_MAX_BUF_SIZE << "]"; 616 617 QMessageBox::warning(this, 0, error.str().c_str()); 618 619 return false; 620 } 621 config.buffer_size = temp; 622 623 temp = note_table_size_edit->text().toUInt(); 624 if (temp < OP_MIN_NOTE_TABLE_SIZE || temp > OP_MAX_NOTE_TABLE_SIZE) { 625 ostringstream error; 626 627 error << "note table size out of range: " << temp 628 << " valid range is [" << OP_MIN_NOTE_TABLE_SIZE << ", " 629 << OP_MAX_NOTE_TABLE_SIZE << "]"; 630 631 QMessageBox::warning(this, 0, error.str().c_str()); 632 633 return false; 634 } 635 config.note_table_size = temp; 636 637 config.verbose = verbose->isChecked(); 638 config.separate_lib = separate_lib_cb->isChecked(); 639 config.separate_kernel = separate_kernel_cb->isChecked(); 640 config.separate_cpu = separate_cpu_cb->isChecked(); 641 config.separate_thread = separate_thread_cb->isChecked(); 642 643 return true; 644} 645 646 647void oprof_start::get_unit_mask_part(op_event_descr const & descr, uint num, 648 bool selected, uint & mask) 649{ 650 if (!selected) 651 return; 652 if (num >= descr.unit->num) 653 return; 654 655 if (descr.unit->unit_type_mask == utm_bitmask) 656 mask |= descr.unit->um[num].value; 657 else 658 mask = descr.unit->um[num].value; 659} 660 661 662// return the unit mask selected through the unit mask check box 663uint oprof_start::get_unit_mask(op_event_descr const & descr) 664{ 665 uint mask = 0; 666 667 if (!descr.unit) 668 return 0; 669 670 // mandatory mask is transparent for user. 671 if (descr.unit->unit_type_mask == utm_mandatory) { 672 mask = descr.unit->default_mask; 673 return mask; 674 } 675 676 get_unit_mask_part(descr, 0, check0->isChecked(), mask); 677 get_unit_mask_part(descr, 1, check1->isChecked(), mask); 678 get_unit_mask_part(descr, 2, check2->isChecked(), mask); 679 get_unit_mask_part(descr, 3, check3->isChecked(), mask); 680 get_unit_mask_part(descr, 4, check4->isChecked(), mask); 681 get_unit_mask_part(descr, 5, check5->isChecked(), mask); 682 get_unit_mask_part(descr, 6, check6->isChecked(), mask); 683 get_unit_mask_part(descr, 7, check7->isChecked(), mask); 684 get_unit_mask_part(descr, 8, check8->isChecked(), mask); 685 get_unit_mask_part(descr, 9, check9->isChecked(), mask); 686 get_unit_mask_part(descr, 10, check10->isChecked(), mask); 687 get_unit_mask_part(descr, 11, check11->isChecked(), mask); 688 get_unit_mask_part(descr, 12, check12->isChecked(), mask); 689 get_unit_mask_part(descr, 13, check13->isChecked(), mask); 690 get_unit_mask_part(descr, 14, check14->isChecked(), mask); 691 get_unit_mask_part(descr, 15, check15->isChecked(), mask); 692 return mask; 693} 694 695 696void oprof_start::hide_masks() 697{ 698 check0->hide(); 699 check1->hide(); 700 check2->hide(); 701 check3->hide(); 702 check4->hide(); 703 check5->hide(); 704 check6->hide(); 705 check7->hide(); 706 check8->hide(); 707 check9->hide(); 708 check10->hide(); 709 check11->hide(); 710 check12->hide(); 711 check13->hide(); 712 check14->hide(); 713 check15->hide(); 714} 715 716 717void oprof_start::setup_unit_masks(op_event_descr const & descr) 718{ 719 op_unit_mask const * um = descr.unit; 720 721 hide_masks(); 722 723 if (!um || um->unit_type_mask == utm_mandatory) 724 return; 725 726 event_setting & cfg = event_cfgs[descr.name]; 727 728 unit_mask_group->setExclusive(um->unit_type_mask == utm_exclusive); 729 730 for (size_t i = 0; i < um->num ; ++i) { 731 QCheckBox * check = 0; 732 switch (i) { 733 case 0: check = check0; break; 734 case 1: check = check1; break; 735 case 2: check = check2; break; 736 case 3: check = check3; break; 737 case 4: check = check4; break; 738 case 5: check = check5; break; 739 case 6: check = check6; break; 740 case 7: check = check7; break; 741 case 8: check = check8; break; 742 case 9: check = check9; break; 743 case 10: check = check10; break; 744 case 11: check = check11; break; 745 case 12: check = check12; break; 746 case 13: check = check13; break; 747 case 14: check = check14; break; 748 case 15: check = check15; break; 749 } 750 check->setText(um->um[i].desc); 751 if (um->unit_type_mask == utm_exclusive) { 752 check->setChecked(cfg.umask == um->um[i].value); 753 } else { 754 // The last descriptor contains a mask that enable all 755 // value so we must enable the last check box only if 756 // all bits are on. 757 if (i == um->num - 1) { 758 check->setChecked(cfg.umask == um->um[i].value); 759 } else { 760 check->setChecked(cfg.umask & um->um[i].value); 761 } 762 } 763 check->show(); 764 } 765 unit_mask_group->setMinimumSize(unit_mask_group->sizeHint()); 766 setup_config_tab->setMinimumSize(setup_config_tab->sizeHint()); 767} 768 769 770uint oprof_start::max_perf_count() const 771{ 772 return cpu_type == CPU_RTC ? OP_MAX_RTC_COUNT : OP_MAX_PERF_COUNT; 773} 774 775 776void oprof_start::on_flush_profiler_data() 777{ 778 vector<string> args; 779 args.push_back("--dump"); 780 781 if (daemon_status().running) 782 do_exec_command(OP_BINDIR "/opcontrol", args); 783 else 784 QMessageBox::warning(this, 0, "The profiler is not started."); 785} 786 787 788// user is happy of its setting. 789void oprof_start::on_start_profiler() 790{ 791 // save the current settings 792 record_selected_event_config(); 793 794 bool one_enable = false; 795 796 QListViewItem * cur; 797 for (cur = events_list->firstChild(); cur; cur = cur->nextSibling()) { 798 if (!cur->isSelected()) 799 continue; 800 801 // the missing reference is intended: gcc 2.91.66 can compile 802 // "op_event_descr const & descr = ..." w/o a warning 803 op_event_descr const descr = 804 locate_event(cur->text(0).latin1()); 805 806 event_setting & cfg = event_cfgs[cur->text(0).latin1()]; 807 808 one_enable = true; 809 810 if (!cfg.os_ring_count && !cfg.user_ring_count) { 811 QMessageBox::warning(this, 0, "You must select to " 812 "profile at least one of user binaries/kernel"); 813 return; 814 } 815 816 if (cfg.count < descr.min_count || 817 cfg.count > max_perf_count()) { 818 ostringstream out; 819 820 out << "event " << descr.name << " count of range: " 821 << cfg.count << " must be in [ " 822 << descr.min_count << ", " 823 << max_perf_count() 824 << "]"; 825 826 QMessageBox::warning(this, 0, out.str().c_str()); 827 return; 828 } 829 830 if (descr.unit && 831 descr.unit->unit_type_mask == utm_bitmask && 832 cfg.umask == 0) { 833 ostringstream out; 834 835 out << "event " << descr.name << " invalid unit mask: " 836 << cfg.umask << endl; 837 838 QMessageBox::warning(this, 0, out.str().c_str()); 839 return; 840 } 841 } 842 843 if (one_enable == false && cpu_type != CPU_TIMER_INT) { 844 QMessageBox::warning(this, 0, "No counters enabled.\n"); 845 return; 846 } 847 848 if (daemon_status().running) { 849 // gcc 2.91 work around 850 int user_choice = 0; 851 user_choice = 852 QMessageBox::warning(this, 0, 853 "Profiler already started:\n\n" 854 "stop and restart it?", 855 "&Restart", "&Cancel", 0, 0, 1); 856 857 if (user_choice == 1) 858 return; 859 860 // this flush profiler data also. 861 on_stop_profiler(); 862 } 863 864 vector<string> args; 865 866 // save_config validate and setup the config 867 if (save_config()) { 868 // now actually start 869 args.push_back("--start"); 870 if (config.verbose) 871 args.push_back("--verbose"); 872 do_exec_command(OP_BINDIR "/opcontrol", args); 873 } 874 875 total_nr_interrupts = 0; 876 timerEvent(0); 877} 878 879 880bool oprof_start::save_config() 881{ 882 if (!record_config()) 883 return false; 884 885 vector<string> args; 886 887 // saving config is done by running opcontrol --setup with appropriate 888 // setted parameters so we use the same config file as command line 889 // tools 890 891 args.push_back("--setup"); 892 893 bool one_enabled = false; 894 895 vector<string> tmpargs; 896 tmpargs.push_back("--setup"); 897 898 QListViewItem * cur; 899 for (cur = events_list->firstChild(); cur; cur = cur->nextSibling()) { 900 if (!cur->isSelected()) 901 continue; 902 903 event_setting & cfg = event_cfgs[cur->text(0).latin1()]; 904 905 op_event_descr const & descr = 906 locate_event(cur->text(0).latin1()); 907 908 one_enabled = true; 909 910 string arg = "--event=" + descr.name; 911 arg += ":" + op_lexical_cast<string>(cfg.count); 912 arg += ":" + op_lexical_cast<string>(cfg.umask); 913 arg += ":" + op_lexical_cast<string>(cfg.os_ring_count); 914 arg += ":" + op_lexical_cast<string>(cfg.user_ring_count); 915 916 tmpargs.push_back(arg); 917 } 918 919 // only set counters if at least one is enabled 920 if (one_enabled) 921 args = tmpargs; 922 923 if (config.no_kernel) { 924 args.push_back("--no-vmlinux"); 925 } else { 926 args.push_back("--vmlinux=" + config.kernel_filename); 927 } 928 929 if (op_get_interface() == OP_INTERFACE_24) { 930 args.push_back("--buffer-size=" + 931 op_lexical_cast<string>(config.buffer_size)); 932 args.push_back("--note-table-size=" + 933 op_lexical_cast<string>(config.note_table_size)); 934 } 935 936 string sep = "--separate="; 937 938 if (config.separate_lib) 939 sep += "library,"; 940 if (config.separate_kernel) 941 sep += "kernel,"; 942 if (config.separate_cpu) 943 sep += "cpu,"; 944 if (config.separate_thread) 945 sep += "thread,"; 946 947 if (sep == "--separate=") 948 sep += "none"; 949 args.push_back(sep); 950 951 // 2.95 work-around, it didn't like return !do_exec_command() 952 bool ret = !do_exec_command(OP_BINDIR "/opcontrol", args); 953 return ret; 954} 955 956 957// flush and stop the profiler if it was started. 958void oprof_start::on_stop_profiler() 959{ 960 vector<string> args; 961 args.push_back("--shutdown"); 962 963 if (daemon_status().running) 964 do_exec_command(OP_BINDIR "/opcontrol", args); 965 else 966 QMessageBox::warning(this, 0, "The profiler is already stopped."); 967 968 timerEvent(0); 969} 970 971 972void oprof_start::on_separate_kernel_cb_changed(int state) 973{ 974 if (state == 2) 975 separate_lib_cb->setChecked(true); 976} 977 978 979/// function object for matching against name 980class event_name_eq { 981 string name_; 982public: 983 explicit event_name_eq(string const & s) : name_(s) {} 984 bool operator()(op_event_descr const & d) const { 985 return d.name == name_; 986 } 987}; 988 989 990// helper to retrieve an event descr through its name. 991op_event_descr const & oprof_start::locate_event(string const & name) const 992{ 993 return *(find_if(v_events.begin(), v_events.end(), event_name_eq(name))); 994} 995