00001
00012 #include <sys/stat.h>
00013 #include <unistd.h>
00014
00015 #include <ctime>
00016 #include <cstdio>
00017 #include <cmath>
00018 #include <sstream>
00019 #include <iostream>
00020 #include <fstream>
00021 #include <algorithm>
00022
00023 #if QT3_SUPPORT
00024 #include <Qt/qlineedit.h>
00025 #include <Qt/qcheckbox.h>
00026 #include <Qt/qtabwidget.h>
00027 #include <Qt/qmessagebox.h>
00028 #include <Qt/qvalidator.h>
00029 #include <Qt/qlabel.h>
00030 #include <Qt/qpushbutton.h>
00031 #include <Qt/q3listview.h>
00032 #include <Qt/q3combobox.h>
00033 #include <Qt/q3listbox.h>
00034 #include <Qt/q3filedialog.h>
00035 #include <Qt/q3buttongroup.h>
00036 #include <Qt/q3header.h>
00037 #else
00038 #include <qlineedit.h>
00039 #include <qcheckbox.h>
00040 #include <qtabwidget.h>
00041 #include <qmessagebox.h>
00042 #include <qvalidator.h>
00043 #include <qlabel.h>
00044 #include <qpushbutton.h>
00045 #include <qlistview.h>
00046 #include <qcombobox.h>
00047 #include <qlistbox.h>
00048 #include <qfiledialog.h>
00049 #include <qbuttongroup.h>
00050 #include <qheader.h>
00051 #define Q3ListView QListView
00052 #endif
00053
00054 #include "oprof_start.h"
00055 #include "op_config.h"
00056 #include "op_config_24.h"
00057 #include "string_manip.h"
00058 #include "op_cpufreq.h"
00059 #include "op_alloc_counter.h"
00060 #include "oprof_start_util.h"
00061 #include "file_manip.h"
00062
00063 #include "op_hw_config.h"
00064
00065 using namespace std;
00066
00067 static char const * green_xpm[] = {
00068 "16 16 2 1",
00069 " c None",
00070 ". c #00FF00",
00071 " ....... ",
00072 " ........... ",
00073 " ............. ",
00074 " ............. ",
00075 "............... ",
00076 "............... ",
00077 "............... ",
00078 "............... ",
00079 "............... ",
00080 "............... ",
00081 "............... ",
00082 " ............. ",
00083 " ............. ",
00084 " ........... ",
00085 " ....... ",
00086 " " };
00087
00088 static char const * red_xpm[] = {
00089 "16 16 2 1",
00090 " c None",
00091 ". c #FF0000",
00092 " ....... ",
00093 " ........... ",
00094 " ............. ",
00095 " ............. ",
00096 "............... ",
00097 "............... ",
00098 "............... ",
00099 "............... ",
00100 "............... ",
00101 "............... ",
00102 "............... ",
00103 " ............. ",
00104 " ............. ",
00105 " ........... ",
00106 " ....... ",
00107 " " };
00108
00109 static QPixmap * green_pixmap;
00110 static QPixmap * red_pixmap;
00111
00112
00113 op_event_descr::op_event_descr()
00114 :
00115 counter_mask(0),
00116 val(0),
00117 unit(0),
00118 min_count(0)
00119 {
00120 }
00121
00122
00123 oprof_start::oprof_start()
00124 :
00125 oprof_start_base(0, 0, false, 0),
00126 event_count_validator(new QIntValidator(event_count_edit)),
00127 current_event(0),
00128 cpu_speed(op_cpu_frequency()),
00129 total_nr_interrupts(0)
00130 {
00131 green_pixmap = new QPixmap(green_xpm);
00132 red_pixmap = new QPixmap(red_xpm);
00133 vector<string> args;
00134 args.push_back("--init");
00135
00136 if (do_exec_command(OP_BINDIR "/opcontrol", args))
00137 exit(EXIT_FAILURE);
00138
00139 cpu_type = op_get_cpu_type();
00140 op_nr_counters = op_get_nr_counters(cpu_type);
00141
00142 if (cpu_type == CPU_TIMER_INT) {
00143 setup_config_tab->removePage(counter_setup_page);
00144 } else {
00145 fill_events();
00146 }
00147
00148 op_interface interface = op_get_interface();
00149 if (interface == OP_INTERFACE_NO_GOOD) {
00150 QMessageBox::warning(this, 0, "Couldn't determine kernel"
00151 " interface version");
00152 exit(EXIT_FAILURE);
00153 }
00154 bool is_26 = interface == OP_INTERFACE_26;
00155
00156 if (is_26) {
00157 note_table_size_edit->hide();
00158 note_table_size_label->hide();
00159 if (!op_file_readable("/dev/oprofile/backtrace_depth")) {
00160 callgraph_depth_label->hide();
00161 callgraph_depth_edit->hide();
00162 }
00163 } else {
00164 callgraph_depth_label->hide();
00165 callgraph_depth_edit->hide();
00166 buffer_watershed_label->hide();
00167 buffer_watershed_edit->hide();
00168 cpu_buffer_size_label->hide();
00169 cpu_buffer_size_edit->hide();
00170 }
00171
00172
00173 kernel_filename_edit->setText(config.kernel_filename.c_str());
00174
00175 no_vmlinux->setChecked(config.no_kernel);
00176
00177 buffer_size_edit->setText(QString().setNum(config.buffer_size));
00178 buffer_watershed_edit->setText(QString().setNum(config.buffer_watershed));
00179 cpu_buffer_size_edit->setText(QString().setNum(config.cpu_buffer_size));
00180 note_table_size_edit->setText(QString().setNum(config.note_table_size));
00181 callgraph_depth_edit->setText(QString().setNum(config.callgraph_depth));
00182 verbose->setChecked(config.verbose);
00183 separate_lib_cb->setChecked(config.separate_lib);
00184 separate_kernel_cb->setChecked(config.separate_kernel);
00185 separate_cpu_cb->setChecked(config.separate_cpu);
00186 separate_thread_cb->setChecked(config.separate_thread);
00187
00188
00189 hide_masks();
00190
00191 event_count_edit->setValidator(event_count_validator);
00192 QIntValidator * iv;
00193 iv = new QIntValidator(OP_MIN_BUF_SIZE, OP_MAX_BUF_SIZE, buffer_size_edit);
00194 buffer_size_edit->setValidator(iv);
00195 iv = new QIntValidator(OP_MIN_NOTE_TABLE_SIZE, OP_MAX_NOTE_TABLE_SIZE, note_table_size_edit);
00196 note_table_size_edit->setValidator(iv);
00197 iv = new QIntValidator(0, INT_MAX, callgraph_depth_edit);
00198 callgraph_depth_edit->setValidator(iv);
00199 iv = new QIntValidator(0, INT_MAX, buffer_watershed_edit);
00200 buffer_watershed_edit->setValidator(iv);
00201 iv = new QIntValidator(0, OP_MAX_CPU_BUF_SIZE, cpu_buffer_size_edit);
00202 cpu_buffer_size_edit->setValidator(iv);
00203
00204
00205 startTimer(5000);
00206 timerEvent(0);
00207
00208 resize(minimumSizeHint());
00209
00210
00211 event_selected();
00212 }
00213
00214
00215 void oprof_start::fill_events()
00216 {
00217
00218
00219
00220 struct list_head * pos;
00221 struct list_head * events = op_events(cpu_type);
00222
00223 list_for_each(pos, events) {
00224 struct op_event * event = list_entry(pos, struct op_event, event_next);
00225
00226 op_event_descr descr;
00227
00228 descr.counter_mask = event->counter_mask;
00229 descr.val = event->val;
00230 if (event->unit->num) {
00231 descr.unit = event->unit;
00232 } else {
00233 descr.unit = 0;
00234 }
00235
00236 descr.name = event->name;
00237 descr.help_str = event->desc;
00238 descr.min_count = event->min_count;
00239
00240 for (uint ctr = 0; ctr < op_nr_counters; ++ctr) {
00241 uint count;
00242
00243 if (!(descr.counter_mask & (1 << ctr)))
00244 continue;
00245
00246 if (cpu_type == CPU_RTC) {
00247 count = 1024;
00248 } else {
00249
00250
00251
00252 if (cpu_speed)
00253 count = int(cpu_speed * 500);
00254 else
00255 count = descr.min_count * 100;
00256 }
00257
00258 event_cfgs[descr.name].count = count;
00259 event_cfgs[descr.name].umask = 0;
00260 if (descr.unit)
00261 event_cfgs[descr.name].umask = descr.unit->default_mask;
00262 event_cfgs[descr.name].os_ring_count = 1;
00263 event_cfgs[descr.name].user_ring_count = 1;
00264 }
00265
00266 v_events.push_back(descr);
00267 }
00268
00269 events_list->header()->hide();
00270 events_list->setSorting(-1);
00271
00272 fill_events_listbox();
00273
00274 read_set_events();
00275
00276
00277 if (cpu_type == CPU_RTC)
00278 events_list->setCurrentItem(events_list->firstChild());
00279
00280 load_config_file();
00281 }
00282
00283
00284 namespace {
00285
00287 Q3ListViewItem * findItem(Q3ListView * view, char const * name)
00288 {
00289
00290 Q3ListViewItem * item = view->firstChild();
00291
00292 while (item && strcmp(item->text(0).latin1(), name))
00293 item = item->nextSibling();
00294
00295 return item;
00296 }
00297
00298 };
00299
00300
00301 void oprof_start::setup_default_event()
00302 {
00303 struct op_default_event_descr descr;
00304 op_default_event(cpu_type, &descr);
00305
00306 event_cfgs[descr.name].umask = descr.um;
00307 event_cfgs[descr.name].count = descr.count;
00308 event_cfgs[descr.name].user_ring_count = 1;
00309 event_cfgs[descr.name].os_ring_count = 1;
00310
00311 Q3ListViewItem * item = findItem(events_list, descr.name);
00312 if (item)
00313 item->setSelected(true);
00314 }
00315
00316
00317 void oprof_start::read_set_events()
00318 {
00319 string name = get_config_filename(".oprofile/daemonrc");
00320
00321 ifstream in(name.c_str());
00322
00323 if (!in) {
00324 setup_default_event();
00325 return;
00326 }
00327
00328 string str;
00329
00330 bool one_enabled = false;
00331
00332 while (getline(in, str)) {
00333 string const val = split(str, '=');
00334 string const name = str;
00335
00336 if (!is_prefix(name, "CHOSEN_EVENTS_"))
00337 continue;
00338
00339 one_enabled = true;
00340
00341
00342 vector<string> parts = separate_token(val, ':');
00343
00344 if (parts.size() != 5 && parts.size() != 2) {
00345 cerr << "invalid configuration file\n";
00346
00347 exit(EXIT_FAILURE);
00348 }
00349
00350 string ev_name = parts[0];
00351 event_cfgs[ev_name].count =
00352 op_lexical_cast<unsigned int>(parts[1]);
00353
00354
00355 if (parts.size() == 5) {
00356 event_cfgs[ev_name].umask =
00357 op_lexical_cast<unsigned int>(parts[2]);
00358 event_cfgs[ev_name].user_ring_count =
00359 op_lexical_cast<unsigned int>(parts[3]);
00360 event_cfgs[ev_name].os_ring_count =
00361 op_lexical_cast<unsigned int>(parts[4]);
00362 } else {
00363 event_cfgs[ev_name].umask = 0;
00364 event_cfgs[ev_name].user_ring_count = 1;
00365 event_cfgs[ev_name].os_ring_count = 1;
00366 }
00367
00368 Q3ListViewItem * item = findItem(events_list, ev_name.c_str());
00369 if (item)
00370 item->setSelected(true);
00371 }
00372
00373
00374 if (!one_enabled)
00375 setup_default_event();
00376 }
00377
00378
00379 void oprof_start::load_config_file()
00380 {
00381 string name = get_config_filename(".oprofile/daemonrc");
00382
00383 ifstream in(name.c_str());
00384 if (!in) {
00385 if (!check_and_create_config_dir())
00386 return;
00387
00388 ofstream out(name.c_str());
00389 if (!out) {
00390 QMessageBox::warning(this, 0, "Unable to open configuration "
00391 "file ~/.oprofile/daemonrc");
00392 }
00393 return;
00394 }
00395
00396 in >> config;
00397 }
00398
00399
00400
00401 void oprof_start::accept()
00402 {
00403
00404 record_selected_event_config();
00405
00406 save_config();
00407
00408 QDialog::accept();
00409 }
00410
00411
00412 void oprof_start::closeEvent(QCloseEvent *)
00413 {
00414 accept();
00415 }
00416
00417
00418 void oprof_start::timerEvent(QTimerEvent *)
00419 {
00420 static time_t last = time(0);
00421
00422 daemon_status dstat;
00423
00424 flush_profiler_data_btn->setEnabled(dstat.running);
00425 stop_profiler_btn->setEnabled(dstat.running);
00426 start_profiler_btn->setEnabled(!dstat.running);
00427 reset_sample_files_btn->setEnabled(!dstat.running);
00428
00429 if (!dstat.running) {
00430 daemon_label->setText("Profiler is not running.");
00431 return;
00432 }
00433
00434 ostringstream ss;
00435 ss << "Profiler running:";
00436
00437 time_t curr = time(0);
00438 total_nr_interrupts += dstat.nr_interrupts;
00439
00440 if (curr - last)
00441 ss << " (" << dstat.nr_interrupts / (curr - last) << " interrupts / second, total " << total_nr_interrupts << ")";
00442
00443 daemon_label->setText(ss.str().c_str());
00444
00445 last = curr;
00446 }
00447
00448
00449 void oprof_start::fill_events_listbox()
00450 {
00451 setUpdatesEnabled(false);
00452
00453 for (vector<op_event_descr>::reverse_iterator cit = v_events.rbegin();
00454 cit != v_events.rend(); ++cit) {
00455 new Q3ListViewItem(events_list, cit->name.c_str());
00456 }
00457
00458 setUpdatesEnabled(true);
00459 update();
00460 }
00461
00462
00463 void oprof_start::display_event(op_event_descr const & descr)
00464 {
00465 setUpdatesEnabled(false);
00466
00467 setup_unit_masks(descr);
00468 os_ring_count_cb->setEnabled(true);
00469 user_ring_count_cb->setEnabled(true);
00470 event_count_edit->setEnabled(true);
00471
00472 event_setting & cfg = event_cfgs[descr.name];
00473
00474 os_ring_count_cb->setChecked(cfg.os_ring_count);
00475 user_ring_count_cb->setChecked(cfg.user_ring_count);
00476 QString count_text;
00477 count_text.setNum(cfg.count);
00478 event_count_edit->setText(count_text);
00479 event_count_validator->setRange(descr.min_count, max_perf_count());
00480
00481 setUpdatesEnabled(true);
00482 update();
00483 }
00484
00485
00486 bool oprof_start::is_selectable_event(Q3ListViewItem * item)
00487 {
00488 if (item->isSelected())
00489 return true;
00490
00491 selected_events.insert(item);
00492
00493 bool ret = false;
00494 if (alloc_selected_events())
00495 ret = true;
00496
00497 selected_events.erase(item);
00498
00499 return ret;
00500 }
00501
00502
00503 void oprof_start::draw_event_list()
00504 {
00505 Q3ListViewItem * cur;
00506 for (cur = events_list->firstChild(); cur; cur = cur->nextSibling()) {
00507 if (is_selectable_event(cur))
00508 cur->setPixmap(0, *green_pixmap);
00509 else
00510 cur->setPixmap(0, *red_pixmap);
00511 }
00512 }
00513
00514
00515 bool oprof_start::alloc_selected_events() const
00516 {
00517 vector<op_event const *> events;
00518
00519 set<Q3ListViewItem *>::const_iterator it;
00520 for (it = selected_events.begin(); it != selected_events.end(); ++it)
00521 events.push_back(find_event_by_name((*it)->text(0).latin1(),0,0));
00522
00523 size_t * map =
00524 map_event_to_counter(&events[0], events.size(), cpu_type);
00525
00526 if (!map)
00527 return false;
00528
00529 free(map);
00530 return true;
00531 }
00532
00533 void oprof_start::event_selected()
00534 {
00535
00536
00537
00538
00539 set<Q3ListViewItem *> current_selection;
00540 Q3ListViewItem * cur;
00541 for (cur = events_list->firstChild(); cur; cur = cur->nextSibling()) {
00542 if (cur->isSelected())
00543 current_selection.insert(cur);
00544 }
00545
00546
00547 vector<Q3ListViewItem *> new_deselected;
00548 set_difference(selected_events.begin(), selected_events.end(),
00549 current_selection.begin(), current_selection.end(),
00550 back_inserter(new_deselected));
00551 vector<Q3ListViewItem *>::const_iterator it;
00552 for (it = new_deselected.begin(); it != new_deselected.end(); ++it)
00553 selected_events.erase(*it);
00554
00555
00556 vector<Q3ListViewItem *> new_selected;
00557 set_difference(current_selection.begin(), current_selection.end(),
00558 selected_events.begin(), selected_events.end(),
00559 back_inserter(new_selected));
00560 for (it = new_selected.begin(); it != new_selected.end(); ++it) {
00561 selected_events.insert(*it);
00562 if (!alloc_selected_events()) {
00563 (*it)->setSelected(false);
00564 selected_events.erase(*it);
00565 } else {
00566 current_event = *it;
00567 }
00568 }
00569
00570 draw_event_list();
00571
00572 if (current_event)
00573 display_event(locate_event(current_event->text(0).latin1()));
00574 }
00575
00576
00577 void oprof_start::event_over(Q3ListViewItem * item)
00578 {
00579 op_event_descr const & descr = locate_event(item->text(0).latin1());
00580
00581 string help_str = descr.help_str.c_str();
00582 if (!is_selectable_event(item)) {
00583 help_str += " conflicts with:";
00584
00585 set<Q3ListViewItem *>::const_iterator it;
00586 for (it = selected_events.begin();
00587 it != selected_events.end(); ) {
00588 Q3ListViewItem * temp = *it;
00589 selected_events.erase(it++);
00590 if (is_selectable_event(item)) {
00591 help_str += " ";
00592 help_str += temp->text(0).latin1();
00593 }
00594 selected_events.insert(temp);
00595 }
00596 }
00597
00598 event_help_label->setText(help_str.c_str());
00599 }
00600
00601
00603 void oprof_start::choose_kernel_filename()
00604 {
00605 string name = kernel_filename_edit->text().latin1();
00606 string result = do_open_file_or_dir(name, false);
00607
00608 if (!result.empty())
00609 kernel_filename_edit->setText(result.c_str());
00610 }
00611
00612
00613
00614
00615 void oprof_start::record_selected_event_config()
00616 {
00617 if (!current_event)
00618 return;
00619
00620 string name(current_event->text(0).latin1());
00621
00622 event_setting & cfg = event_cfgs[name];
00623 op_event_descr const & curr = locate_event(name);
00624
00625 cfg.count = event_count_edit->text().toUInt();
00626 cfg.os_ring_count = os_ring_count_cb->isChecked();
00627 cfg.user_ring_count = user_ring_count_cb->isChecked();
00628 cfg.umask = get_unit_mask(curr);
00629 }
00630
00631
00632
00633
00634 bool oprof_start::record_config()
00635 {
00636 config.kernel_filename = kernel_filename_edit->text().latin1();
00637 config.no_kernel = no_vmlinux->isChecked();
00638
00639 uint temp = buffer_size_edit->text().toUInt();
00640 if (temp < OP_MIN_BUF_SIZE || temp > OP_MAX_BUF_SIZE) {
00641 ostringstream error;
00642
00643 error << "buffer size out of range: " << temp
00644 << " valid range is [" << OP_MIN_BUF_SIZE << ", "
00645 << OP_MAX_BUF_SIZE << "]";
00646
00647 QMessageBox::warning(this, 0, error.str().c_str());
00648
00649 return false;
00650 }
00651 config.buffer_size = temp;
00652
00653 temp = buffer_watershed_edit->text().toUInt();
00654
00655 if (temp > config.buffer_size / 2) {
00656 ostringstream error;
00657
00658 error << "buffer watershed out of range: " << temp
00659 << " valid range is [0 (use default), buffer size/2] "
00660 << "generally 0.25 * buffer size is fine";
00661
00662 QMessageBox::warning(this, 0, error.str().c_str());
00663
00664 return false;
00665 }
00666 config.buffer_watershed = temp;
00667
00668 temp = cpu_buffer_size_edit->text().toUInt();
00669 if ((temp != 0 && temp < OP_MIN_CPU_BUF_SIZE) ||
00670 temp > OP_MAX_CPU_BUF_SIZE) {
00671 ostringstream error;
00672
00673 error << "cpu buffer size out of range: " << temp
00674 << " valid range is [" << OP_MIN_CPU_BUF_SIZE << ", "
00675 << OP_MAX_CPU_BUF_SIZE << "] (size = 0: use default)";
00676
00677 QMessageBox::warning(this, 0, error.str().c_str());
00678
00679 return false;
00680 }
00681 config.cpu_buffer_size = temp;
00682
00683 temp = note_table_size_edit->text().toUInt();
00684 if (temp < OP_MIN_NOTE_TABLE_SIZE || temp > OP_MAX_NOTE_TABLE_SIZE) {
00685 ostringstream error;
00686
00687 error << "note table size out of range: " << temp
00688 << " valid range is [" << OP_MIN_NOTE_TABLE_SIZE << ", "
00689 << OP_MAX_NOTE_TABLE_SIZE << "]";
00690
00691 QMessageBox::warning(this, 0, error.str().c_str());
00692
00693 return false;
00694 }
00695 config.note_table_size = temp;
00696
00697 temp = callgraph_depth_edit->text().toUInt();
00698 if (temp > INT_MAX) {
00699 ostringstream error;
00700
00701 error << "callgraph depth out of range: " << temp
00702 << " valid range is [" << 0 << ", "
00703 << INT_MAX << "]";
00704
00705 QMessageBox::warning(this, 0, error.str().c_str());
00706
00707 return false;
00708 }
00709 config.callgraph_depth = temp;
00710
00711 config.verbose = verbose->isChecked();
00712 config.separate_lib = separate_lib_cb->isChecked();
00713 config.separate_kernel = separate_kernel_cb->isChecked();
00714 config.separate_cpu = separate_cpu_cb->isChecked();
00715 config.separate_thread = separate_thread_cb->isChecked();
00716
00717 return true;
00718 }
00719
00720
00721 void oprof_start::get_unit_mask_part(op_event_descr const & descr, uint num,
00722 bool selected, uint & mask)
00723 {
00724 if (!selected)
00725 return;
00726 if (num >= descr.unit->num)
00727 return;
00728
00729 if (descr.unit->unit_type_mask == utm_bitmask)
00730 mask |= descr.unit->um[num].value;
00731 else
00732 mask = descr.unit->um[num].value;
00733 }
00734
00735
00736
00737 uint oprof_start::get_unit_mask(op_event_descr const & descr)
00738 {
00739 uint mask = 0;
00740
00741 if (!descr.unit)
00742 return 0;
00743
00744
00745 if (descr.unit->unit_type_mask == utm_mandatory) {
00746 mask = descr.unit->default_mask;
00747 return mask;
00748 }
00749
00750 get_unit_mask_part(descr, 0, check0->isChecked(), mask);
00751 get_unit_mask_part(descr, 1, check1->isChecked(), mask);
00752 get_unit_mask_part(descr, 2, check2->isChecked(), mask);
00753 get_unit_mask_part(descr, 3, check3->isChecked(), mask);
00754 get_unit_mask_part(descr, 4, check4->isChecked(), mask);
00755 get_unit_mask_part(descr, 5, check5->isChecked(), mask);
00756 get_unit_mask_part(descr, 6, check6->isChecked(), mask);
00757 get_unit_mask_part(descr, 7, check7->isChecked(), mask);
00758 get_unit_mask_part(descr, 8, check8->isChecked(), mask);
00759 get_unit_mask_part(descr, 9, check9->isChecked(), mask);
00760 get_unit_mask_part(descr, 10, check10->isChecked(), mask);
00761 get_unit_mask_part(descr, 11, check11->isChecked(), mask);
00762 get_unit_mask_part(descr, 12, check12->isChecked(), mask);
00763 get_unit_mask_part(descr, 13, check13->isChecked(), mask);
00764 get_unit_mask_part(descr, 14, check14->isChecked(), mask);
00765 get_unit_mask_part(descr, 15, check15->isChecked(), mask);
00766 return mask;
00767 }
00768
00769
00770 void oprof_start::hide_masks()
00771 {
00772 check0->hide();
00773 check1->hide();
00774 check2->hide();
00775 check3->hide();
00776 check4->hide();
00777 check5->hide();
00778 check6->hide();
00779 check7->hide();
00780 check8->hide();
00781 check9->hide();
00782 check10->hide();
00783 check11->hide();
00784 check12->hide();
00785 check13->hide();
00786 check14->hide();
00787 check15->hide();
00788 }
00789
00790
00791 void oprof_start::setup_unit_masks(op_event_descr const & descr)
00792 {
00793 op_unit_mask const * um = descr.unit;
00794
00795 hide_masks();
00796
00797 if (!um || um->unit_type_mask == utm_mandatory)
00798 return;
00799
00800 event_setting & cfg = event_cfgs[descr.name];
00801
00802 unit_mask_group->setExclusive(um->unit_type_mask == utm_exclusive);
00803
00804 for (size_t i = 0; i < um->num ; ++i) {
00805 QCheckBox * check = 0;
00806 switch (i) {
00807 case 0: check = check0; break;
00808 case 1: check = check1; break;
00809 case 2: check = check2; break;
00810 case 3: check = check3; break;
00811 case 4: check = check4; break;
00812 case 5: check = check5; break;
00813 case 6: check = check6; break;
00814 case 7: check = check7; break;
00815 case 8: check = check8; break;
00816 case 9: check = check9; break;
00817 case 10: check = check10; break;
00818 case 11: check = check11; break;
00819 case 12: check = check12; break;
00820 case 13: check = check13; break;
00821 case 14: check = check14; break;
00822 case 15: check = check15; break;
00823 }
00824 check->setText(um->um[i].desc);
00825 if (um->unit_type_mask == utm_exclusive)
00826 check->setChecked(cfg.umask == um->um[i].value);
00827 else
00828 check->setChecked(cfg.umask & um->um[i].value);
00829
00830 check->show();
00831 }
00832 unit_mask_group->setMinimumSize(unit_mask_group->sizeHint());
00833 setup_config_tab->setMinimumSize(setup_config_tab->sizeHint());
00834 }
00835
00836
00837 uint oprof_start::max_perf_count() const
00838 {
00839 return cpu_type == CPU_RTC ? OP_MAX_RTC_COUNT : OP_MAX_PERF_COUNT;
00840 }
00841
00842
00843 void oprof_start::on_flush_profiler_data()
00844 {
00845 vector<string> args;
00846 args.push_back("--dump");
00847
00848 if (daemon_status().running)
00849 do_exec_command(OP_BINDIR "/opcontrol", args);
00850 else
00851 QMessageBox::warning(this, 0, "The profiler is not started.");
00852 }
00853
00854
00855
00856 void oprof_start::on_start_profiler()
00857 {
00858
00859 record_selected_event_config();
00860
00861 bool one_enable = false;
00862
00863 Q3ListViewItem * cur;
00864 for (cur = events_list->firstChild(); cur; cur = cur->nextSibling()) {
00865 if (!cur->isSelected())
00866 continue;
00867
00868
00869
00870 op_event_descr const descr =
00871 locate_event(cur->text(0).latin1());
00872
00873 event_setting & cfg = event_cfgs[cur->text(0).latin1()];
00874
00875 one_enable = true;
00876
00877 if (!cfg.os_ring_count && !cfg.user_ring_count) {
00878 QMessageBox::warning(this, 0, "You must select to "
00879 "profile at least one of user binaries/kernel");
00880 return;
00881 }
00882
00883 if (cfg.count < descr.min_count ||
00884 cfg.count > max_perf_count()) {
00885 ostringstream out;
00886
00887 out << "event " << descr.name << " count of range: "
00888 << cfg.count << " must be in [ "
00889 << descr.min_count << ", "
00890 << max_perf_count()
00891 << "]";
00892
00893 QMessageBox::warning(this, 0, out.str().c_str());
00894 return;
00895 }
00896
00897 if (descr.unit &&
00898 descr.unit->unit_type_mask == utm_bitmask &&
00899 cfg.umask == 0) {
00900 ostringstream out;
00901
00902 out << "event " << descr.name << " invalid unit mask: "
00903 << cfg.umask << endl;
00904
00905 QMessageBox::warning(this, 0, out.str().c_str());
00906 return;
00907 }
00908 }
00909
00910 if (one_enable == false && cpu_type != CPU_TIMER_INT) {
00911 QMessageBox::warning(this, 0, "No counters enabled.\n");
00912 return;
00913 }
00914
00915 if (daemon_status().running) {
00916
00917 int user_choice = 0;
00918 user_choice =
00919 QMessageBox::warning(this, 0,
00920 "Profiler already started:\n\n"
00921 "stop and restart it?",
00922 "&Restart", "&Cancel", 0, 0, 1);
00923
00924 if (user_choice == 1)
00925 return;
00926
00927
00928 on_stop_profiler();
00929 }
00930
00931 vector<string> args;
00932
00933
00934 if (save_config()) {
00935
00936 args.push_back("--start");
00937 if (config.verbose)
00938 args.push_back("--verbose");
00939 do_exec_command(OP_BINDIR "/opcontrol", args);
00940 }
00941
00942 total_nr_interrupts = 0;
00943 timerEvent(0);
00944 }
00945
00946
00947 bool oprof_start::save_config()
00948 {
00949 if (!record_config())
00950 return false;
00951
00952 vector<string> args;
00953
00954
00955
00956
00957
00958 args.push_back("--setup");
00959
00960 bool one_enabled = false;
00961
00962 vector<string> tmpargs;
00963 tmpargs.push_back("--setup");
00964
00965 Q3ListViewItem * cur;
00966 for (cur = events_list->firstChild(); cur; cur = cur->nextSibling()) {
00967 if (!cur->isSelected())
00968 continue;
00969
00970 event_setting & cfg = event_cfgs[cur->text(0).latin1()];
00971
00972 op_event_descr const & descr =
00973 locate_event(cur->text(0).latin1());
00974
00975 one_enabled = true;
00976
00977 string arg = "--event=" + descr.name;
00978 arg += ":" + op_lexical_cast<string>(cfg.count);
00979 arg += ":" + op_lexical_cast<string>(cfg.umask);
00980 arg += ":" + op_lexical_cast<string>(cfg.os_ring_count);
00981 arg += ":" + op_lexical_cast<string>(cfg.user_ring_count);
00982
00983 tmpargs.push_back(arg);
00984 }
00985
00986
00987 if (one_enabled)
00988 args = tmpargs;
00989
00990 if (config.no_kernel) {
00991 args.push_back("--no-vmlinux");
00992 } else {
00993 args.push_back("--vmlinux=" + config.kernel_filename);
00994 }
00995
00996 args.push_back("--buffer-size=" +
00997 op_lexical_cast<string>(config.buffer_size));
00998
00999 if (op_get_interface() == OP_INTERFACE_24) {
01000 args.push_back("--note-table-size=" +
01001 op_lexical_cast<string>(config.note_table_size));
01002 } else {
01003 args.push_back("--buffer-watershed=" +
01004 op_lexical_cast<string>(config.buffer_watershed));
01005 args.push_back("--cpu-buffer-size=" +
01006 op_lexical_cast<string>(config.cpu_buffer_size));
01007 if (op_file_readable("/dev/oprofile/backtrace_depth")) {
01008 args.push_back("--callgraph=" +
01009 op_lexical_cast<string>(config.callgraph_depth));
01010 }
01011 }
01012
01013 string sep = "--separate=";
01014
01015 if (config.separate_lib)
01016 sep += "library,";
01017 if (config.separate_kernel)
01018 sep += "kernel,";
01019 if (config.separate_cpu)
01020 sep += "cpu,";
01021 if (config.separate_thread)
01022 sep += "thread,";
01023
01024 if (sep == "--separate=")
01025 sep += "none";
01026 args.push_back(sep);
01027
01028
01029 bool ret = !do_exec_command(OP_BINDIR "/opcontrol", args);
01030 return ret;
01031 }
01032
01033
01034
01035 void oprof_start::on_stop_profiler()
01036 {
01037 vector<string> args;
01038 args.push_back("--shutdown");
01039
01040 if (daemon_status().running)
01041 do_exec_command(OP_BINDIR "/opcontrol", args);
01042 else
01043 QMessageBox::warning(this, 0, "The profiler is already stopped.");
01044
01045 timerEvent(0);
01046 }
01047
01048
01049 void oprof_start::on_separate_kernel_cb_changed(int state)
01050 {
01051 if (state == 2)
01052 separate_lib_cb->setChecked(true);
01053 }
01054
01055 void oprof_start::on_reset_sample_files()
01056 {
01057 int ret = QMessageBox::warning(this, 0, "Are you sure you want to "
01058 "reset your last profile session ?", "Yes", "No", 0, 0, 1);
01059 if (!ret) {
01060 vector<string> args;
01061 args.push_back("--reset");
01062 if (!do_exec_command(OP_BINDIR "/opcontrol", args))
01063
01064 daemon_label->setText("Last profile session reseted.");
01065 else
01066 QMessageBox::warning(this, 0,
01067 "Can't reset profiling session.");
01068 }
01069 }
01070
01071
01073 class event_name_eq {
01074 string name_;
01075 public:
01076 explicit event_name_eq(string const & s) : name_(s) {}
01077 bool operator()(op_event_descr const & d) const {
01078 return d.name == name_;
01079 }
01080 };
01081
01082
01083
01084 op_event_descr const & oprof_start::locate_event(string const & name) const
01085 {
01086 return *(find_if(v_events.begin(), v_events.end(), event_name_eq(name)));
01087 }