1 /* 2 ProcessController © 2000, Georges-Edouard Berenger, All Rights Reserved. 3 Copyright (C) 2004 beunited.org 4 Copyright (c) 2006-2009, Haiku, Inc. All rights reserved. 5 6 This library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 This library is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with this library; if not, write to the Free Software 18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21 22 #include "ProcessController.h" 23 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 28 #include <AboutWindow.h> 29 #include <Alert.h> 30 #include <Bitmap.h> 31 #include <Catalog.h> 32 #include <debugger.h> 33 #include <Deskbar.h> 34 #include <Directory.h> 35 #include <Dragger.h> 36 #include <File.h> 37 #include <FindDirectory.h> 38 #include <MessageRunner.h> 39 #include <Path.h> 40 #include <PopUpMenu.h> 41 #include <Roster.h> 42 #include <Screen.h> 43 #include <TextView.h> 44 45 #include <syscalls.h> 46 47 #include "AutoIcon.h" 48 #include "Colors.h" 49 #include "IconMenuItem.h" 50 #include "MemoryBarMenu.h" 51 #include "MemoryBarMenuItem.h" 52 #include "PCWorld.h" 53 #include "Preferences.h" 54 #include "QuitMenu.h" 55 #include "TeamBarMenu.h" 56 #include "TeamBarMenuItem.h" 57 #include "ThreadBarMenu.h" 58 #include "Utilities.h" 59 60 61 #undef B_TRANSLATE_CONTEXT 62 #define B_TRANSLATE_CONTEXT "ProcessController" 63 64 65 const char* kDeskbarItemName = "ProcessController"; 66 const char* kClassName = "ProcessController"; 67 68 const char* kFrameColorPref = "deskbar_frame_color"; 69 const char* kIdleColorPref = "deskbar_idle_color"; 70 const char* kActiveColorPref = "deskbar_active_color"; 71 72 const rgb_color kKernelBlue = {20, 20, 231, 255}; 73 const rgb_color kIdleGreen = {110, 190,110, 255}; 74 75 ProcessController* gPCView; 76 int32 gCPUcount; 77 rgb_color gUserColor; 78 rgb_color gUserColorSelected; 79 rgb_color gIdleColor; 80 rgb_color gIdleColorSelected; 81 rgb_color gKernelColor; 82 rgb_color gKernelColorSelected; 83 rgb_color gFrameColor; 84 rgb_color gFrameColorSelected; 85 rgb_color gMenuBackColorSelected; 86 rgb_color gMenuBackColor; 87 rgb_color gWhiteSelected; 88 ThreadBarMenu* gCurrentThreadBarMenu; 89 bool gInDeskbar = false; 90 91 #define addtopbottom(x) if (top) popup->AddItem(x); else popup->AddItem(x, 0) 92 93 long thread_popup(void *arg); 94 95 int32 gPopupFlag = 0; 96 thread_id gPopupThreadID = 0; 97 98 typedef struct { 99 BPoint where; 100 BRect clickToOpenRect; 101 bool top; 102 } Tpopup_param; 103 104 #define DEBUG_THREADS 1 105 106 long thread_quit_application(void *arg); 107 long thread_debug_thread(void *arg); 108 109 typedef struct { 110 thread_id thread; 111 sem_id sem; 112 time_t totalTime; 113 } Tdebug_thead_param; 114 115 // Bar layout depending on number of CPUs 116 117 typedef struct { 118 float cpu_width; 119 float cpu_inter; 120 float mem_width; 121 } layoutT; 122 123 layoutT layout[] = { 124 { 1, 1, 1 }, 125 { 5, 1, 5 }, // 1 126 { 3, 1, 4 }, // 2 127 { 1, 1, 1 }, 128 { 2, 0, 3 }, // 4 129 { 1, 1, 1 }, 130 { 1, 1, 1 }, 131 { 1, 1, 1 }, 132 { 1, 0, 3 } // 8 133 }; 134 135 136 extern "C" _EXPORT BView *instantiate_deskbar_item(void); 137 138 extern "C" _EXPORT BView * 139 instantiate_deskbar_item(void) 140 { 141 gInDeskbar = true; 142 return new ProcessController(); 143 } 144 145 146 // #pragma mark - 147 148 149 ProcessController::ProcessController(BRect frame, bool temp) 150 : BView(frame, kDeskbarItemName, B_FOLLOW_TOP_BOTTOM, 151 B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE), 152 fProcessControllerIcon(kSignature), 153 fProcessorIcon(k_cpu_mini), 154 fTrackerIcon(kTrackerSig), 155 fDeskbarIcon(kDeskbarSig), 156 fTerminalIcon(kTerminalSig), 157 fTemp(temp) 158 { 159 if (!temp) { 160 Init(); 161 162 frame.OffsetTo(B_ORIGIN); 163 frame.top = frame.bottom - 7; 164 frame.left = frame.right - 7; 165 BDragger* dragger = new BDragger(frame, this, B_FOLLOW_BOTTOM); 166 AddChild(dragger); 167 } 168 } 169 170 ProcessController::ProcessController(BMessage *data) 171 : BView(data), 172 fProcessControllerIcon(kSignature), 173 fProcessorIcon(k_cpu_mini), 174 fTrackerIcon(kTrackerSig), 175 fDeskbarIcon(kDeskbarSig), 176 fTerminalIcon(kTerminalSig), 177 fTemp(false) 178 { 179 Init(); 180 } 181 182 183 ProcessController::ProcessController() 184 : BView(BRect (0, 0, 15, 15), kDeskbarItemName, B_FOLLOW_NONE, B_WILL_DRAW), 185 fProcessControllerIcon(kSignature), 186 fProcessorIcon(k_cpu_mini), 187 fTrackerIcon(kTrackerSig), 188 fDeskbarIcon(kDeskbarSig), 189 fTerminalIcon(kTerminalSig), 190 fTemp(false) 191 { 192 Init(); 193 } 194 195 196 ProcessController::~ProcessController() 197 { 198 if (!fTemp) { 199 if (gPopupThreadID) { 200 status_t return_value; 201 wait_for_thread (gPopupThreadID, &return_value); 202 } 203 } 204 205 delete fMessageRunner; 206 gPCView = NULL; 207 } 208 209 210 void 211 ProcessController::Init() 212 { 213 gPCView = this; 214 fMessageRunner = NULL; 215 memset(fLastBarHeight, 0, sizeof(fLastBarHeight)); 216 fLastMemoryHeight = 0; 217 memset(fCPUTimes, 0, sizeof(fCPUTimes)); 218 memset(fPrevActive, 0, sizeof(fPrevActive)); 219 fPrevTime = 0; 220 } 221 222 223 ProcessController * 224 ProcessController::Instantiate(BMessage *data) 225 { 226 if (!validate_instantiation(data, kClassName)) 227 return NULL; 228 229 return new ProcessController(data); 230 } 231 232 233 status_t 234 ProcessController::Archive(BMessage *data, bool deep) const 235 { 236 BView::Archive(data, deep); 237 data->AddString("add_on", kSignature); 238 data->AddString("class", kClassName); 239 return B_OK; 240 } 241 242 243 void 244 ProcessController::MessageReceived(BMessage *message) 245 { 246 team_id team; 247 thread_id thread; 248 BAlert *alert; 249 char question[1000]; 250 switch (message->what) { 251 case 'Puls': 252 Update (); 253 DoDraw (false); 254 break; 255 256 case 'QtTm': 257 if (message->FindInt32("team", &team) == B_OK) { 258 resume_thread(spawn_thread(thread_quit_application, 259 B_TRANSLATE("Quit application"), B_NORMAL_PRIORITY, 260 (void*) team)); 261 } 262 break; 263 264 case 'KlTm': 265 if (message->FindInt32("team", &team) == B_OK) { 266 info_pack infos; 267 if (get_team_info(team, &infos.team_info) == B_OK) { 268 get_team_name_and_icon(infos); 269 snprintf(question, sizeof(question), 270 B_TRANSLATE("Do you really want to kill the team \"%s\"?"), 271 infos.team_name); 272 alert = new BAlert(B_TRANSLATE("Please confirm"), question, 273 B_TRANSLATE("Cancel"), B_TRANSLATE("Yes, kill this team!"), 274 NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); 275 alert->SetShortcut(0, B_ESCAPE); 276 if (alert->Go()) 277 kill_team(team); 278 } else { 279 alert = new BAlert(B_TRANSLATE("Info"), 280 B_TRANSLATE("This team is already gone"B_UTF8_ELLIPSIS), 281 B_TRANSLATE("Ok!"), NULL, NULL, B_WIDTH_AS_USUAL, 282 B_STOP_ALERT); 283 alert->SetShortcut(0, B_ESCAPE); 284 alert->Go(); 285 } 286 } 287 break; 288 289 case 'KlTh': 290 if (message->FindInt32("thread", &thread) == B_OK) { 291 thread_info thinfo; 292 if (get_thread_info(thread, &thinfo) == B_OK) { 293 #if DEBUG_THREADS 294 snprintf(question, sizeof(question), 295 B_TRANSLATE("What do you want to do " 296 "with the thread \"%s\"?"), thinfo.name); 297 alert = new BAlert(B_TRANSLATE("Please confirm"), question, 298 B_TRANSLATE("Cancel"), B_TRANSLATE("Debug this thread!"), 299 B_TRANSLATE("Kill this thread!"), B_WIDTH_AS_USUAL, 300 B_STOP_ALERT); 301 #define KILL 2 302 #else 303 snprintf(question, sizeof(question), 304 B_TRANSLATE("Are you sure you want " 305 "to kill the thread \"%s\"?"), thinfo.name); 306 alert = new BAlert(B_TRANSLATE("Please confirm"), question, 307 B_TRANSLATE("Cancel"), B_TRANSLATE("Kill this thread!"), 308 NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); 309 #define KILL 1 310 #endif 311 alert->SetShortcut(0, B_ESCAPE); 312 int r = alert->Go(); 313 if (r == KILL) 314 kill_thread(thread); 315 #if DEBUG_THREADS 316 else if (r == 1) { 317 Tdebug_thead_param* param = new Tdebug_thead_param; 318 param->thread = thread; 319 if (thinfo.state == B_THREAD_WAITING) 320 param->sem = thinfo.sem; 321 else 322 param->sem = -1; 323 param->totalTime = thinfo.user_time+thinfo.kernel_time; 324 resume_thread(spawn_thread(thread_debug_thread, 325 B_TRANSLATE("Debug thread"), B_NORMAL_PRIORITY, param)); 326 } 327 #endif 328 } else { 329 alert = new BAlert(B_TRANSLATE("Info"), 330 B_TRANSLATE("This thread is already gone"B_UTF8_ELLIPSIS), 331 B_TRANSLATE("Ok!"), NULL, NULL, 332 B_WIDTH_AS_USUAL, B_STOP_ALERT); 333 alert->SetShortcut(0, B_ESCAPE); 334 alert->Go(); 335 } 336 } 337 break; 338 339 case 'PrTh': 340 if (message->FindInt32("thread", &thread) == B_OK) { 341 long new_priority; 342 if (message->FindInt32("priority", &new_priority) == B_OK) 343 set_thread_priority(thread, new_priority); 344 } 345 break; 346 347 case 'Trac': 348 launch(kTrackerSig, "/boot/system/Tracker"); 349 break; 350 351 case 'Dbar': 352 launch(kDeskbarSig, "/boot/system/Deskbar"); 353 break; 354 355 case 'Term': 356 launch(kTerminalSig, "/boot/system/apps/Terminal"); 357 break; 358 359 case 'AlDb': 360 { 361 if (!be_roster->IsRunning(kDeskbarSig)) 362 launch(kDeskbarSig, "/boot/system/Deskbar"); 363 BDeskbar deskbar; 364 if (gInDeskbar || deskbar.HasItem (kDeskbarItemName)) 365 deskbar.RemoveItem (kDeskbarItemName); 366 else 367 move_to_deskbar(deskbar); 368 break; 369 } 370 371 case 'CPU ': 372 { 373 int32 cpu; 374 if (message->FindInt32 ("cpu", &cpu) == B_OK) { 375 bool last = true; 376 for (int p = 0; p < gCPUcount; p++) { 377 if (p != cpu && _kern_cpu_enabled(p)) { 378 last = false; 379 break; 380 } 381 } 382 if (last) { 383 alert = new BAlert(B_TRANSLATE("Info"), 384 B_TRANSLATE("This is the last active processor...\n" 385 "You can't turn it off!"), 386 B_TRANSLATE("That's no Fun!"), NULL, NULL, 387 B_WIDTH_AS_USUAL, B_WARNING_ALERT); 388 alert->SetShortcut(0, B_ESCAPE); 389 alert->Go(); 390 } else 391 _kern_set_cpu_enabled(cpu, !_kern_cpu_enabled(cpu)); 392 } 393 break; 394 } 395 396 case B_ABOUT_REQUESTED: 397 AboutRequested(); 398 break; 399 400 default: 401 BView::MessageReceived(message); 402 } 403 } 404 405 406 void 407 ProcessController::AboutRequested() 408 { 409 const char* authors[] = { 410 "Georges-Edouard Berenger", 411 NULL 412 }; 413 414 BAboutWindow about(B_TRANSLATE_SYSTEM_NAME("ProcessController"), 2007, authors, 415 "Copyright 1997-2001\n" 416 "Georges-Edouard Berenger."); 417 about.Show(); 418 } 419 420 421 void 422 ProcessController::DefaultColors() 423 { 424 swap_color.red = 203; 425 swap_color.green = 0; 426 swap_color.blue = 0; 427 swap_color.alpha = 255; 428 bool set = false; 429 430 if (!set) { 431 active_color = kKernelBlue; 432 active_color = tint_color (active_color, B_LIGHTEN_2_TINT); 433 idle_color = active_color; 434 idle_color.green /= 3; 435 idle_color.red /= 3; 436 idle_color.blue /= 3; 437 frame_color = kBlack; 438 mix_colors (memory_color, active_color, swap_color, 0.2); 439 } 440 } 441 442 443 void 444 ProcessController::AttachedToWindow() 445 { 446 BView::AttachedToWindow(); 447 if (Parent()) 448 SetViewColor(B_TRANSPARENT_COLOR); 449 else 450 SetViewColor(kBlack); 451 452 Preferences tPreferences(kPreferencesFileName, NULL, false); 453 DefaultColors(); 454 455 system_info info; 456 get_system_info(&info); 457 gCPUcount = info.cpu_count; 458 Update(); 459 460 gIdleColor = kIdleGreen; 461 gIdleColorSelected = tint_color(gIdleColor, B_HIGHLIGHT_BACKGROUND_TINT); 462 gKernelColor = kKernelBlue; 463 gKernelColorSelected = tint_color(gKernelColor, B_HIGHLIGHT_BACKGROUND_TINT); 464 gUserColor = tint_color(gKernelColor, B_LIGHTEN_2_TINT); 465 gUserColorSelected = tint_color(gUserColor, B_HIGHLIGHT_BACKGROUND_TINT); 466 gFrameColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 467 B_HIGHLIGHT_BACKGROUND_TINT); 468 gFrameColorSelected = tint_color(gFrameColor, B_HIGHLIGHT_BACKGROUND_TINT); 469 gMenuBackColor = ui_color(B_MENU_BACKGROUND_COLOR); 470 gMenuBackColorSelected = ui_color(B_MENU_SELECTION_BACKGROUND_COLOR); 471 gWhiteSelected = tint_color(kWhite, B_HIGHLIGHT_BACKGROUND_TINT); 472 473 BMessenger messenger(this); 474 BMessage message('Puls'); 475 fMessageRunner = new BMessageRunner(messenger, &message, 250000, -1); 476 } 477 478 479 480 void 481 ProcessController::MouseDown(BPoint where) 482 { 483 if (atomic_add(&gPopupFlag, 1) > 0) { 484 atomic_add(&gPopupFlag, -1); 485 return; 486 } 487 488 Tpopup_param* param = new Tpopup_param; 489 ConvertToScreen(&where); 490 param->where = where; 491 param->clickToOpenRect = Frame (); 492 ConvertToScreen (¶m->clickToOpenRect); 493 param->top = where.y < BScreen(this->Window()).Frame().bottom-50; 494 495 gPopupThreadID = spawn_thread(thread_popup, "Popup holder thread", 496 B_URGENT_DISPLAY_PRIORITY, param); 497 resume_thread(gPopupThreadID); 498 } 499 500 501 void 502 ProcessController::Draw(BRect) 503 { 504 SetDrawingMode(B_OP_COPY); 505 DoDraw(true); 506 } 507 508 509 void 510 ProcessController::DoDraw(bool force) 511 { 512 BRect bounds(Bounds()); 513 514 float h = floorf(bounds.Height ()) - 2; 515 float top = 1, left = 1; 516 float bottom = top + h; 517 float barWidth = layout[gCPUcount].cpu_width; 518 // interspace 519 float right = left + gCPUcount * (barWidth + layout[gCPUcount].cpu_inter) 520 - layout[gCPUcount].cpu_inter; // right of CPU frame... 521 if (force && Parent()) { 522 SetHighColor(Parent()->ViewColor ()); 523 FillRect(BRect(right + 1, top - 1, right + 2, bottom + 1)); 524 } 525 526 if (force) { 527 SetHighColor(frame_color); 528 StrokeRect(BRect(left - 1, top - 1, right, bottom + 1)); 529 if (gCPUcount == 2) { 530 StrokeLine(BPoint(left + barWidth, top), BPoint(left + barWidth, 531 bottom)); 532 } 533 } 534 float leftMem = bounds.Width() - layout[gCPUcount].mem_width; 535 if (force) 536 StrokeRect(BRect(leftMem - 1, top - 1, 537 leftMem + layout[gCPUcount].mem_width, bottom + 1)); 538 539 for (int x = 0; x < gCPUcount; x++) { 540 right = left + barWidth - 1; 541 float rem = fCPUTimes[x] * (h + 1); 542 float barHeight = floorf (rem); 543 rem -= barHeight; 544 float limit = bottom - barHeight; // horizontal line 545 float previousLimit = bottom - fLastBarHeight[x]; 546 float idleTop = top; 547 548 if (!force && previousLimit > top) 549 idleTop = previousLimit - 1; 550 if (limit > idleTop) { 551 SetHighColor(idle_color); 552 FillRect(BRect(left, idleTop, right, limit - 1)); 553 } 554 if (barHeight <= h) { 555 rgb_color fraction_color; 556 mix_colors(fraction_color, idle_color, active_color, rem); 557 SetHighColor(fraction_color); 558 StrokeLine(BPoint(left, bottom - barHeight), BPoint(right, 559 bottom - barHeight)); 560 } 561 float active_bottom = bottom; 562 if (!force && previousLimit < bottom) 563 active_bottom = previousLimit + 1; 564 if (limit < active_bottom) { 565 SetHighColor(active_color); 566 FillRect(BRect(left, limit + 1, right, active_bottom)); 567 } 568 left += layout[gCPUcount].cpu_width + layout[gCPUcount].cpu_inter; 569 fLastBarHeight[x] = barHeight; 570 } 571 572 float rightMem = bounds.Width () - 1; 573 float rem = fMemoryUsage * (h + 1); 574 float barHeight = floorf (rem); 575 rem -= barHeight; 576 577 rgb_color used_memory_color; 578 float sq = fMemoryUsage * fMemoryUsage; 579 sq *= sq; 580 sq *= sq; 581 mix_colors(used_memory_color, memory_color, swap_color, sq); 582 583 float limit = bottom - barHeight; // horizontal line 584 float previousLimit = bottom - fLastMemoryHeight; 585 float free_top = top; 586 if (!force && previousLimit > top) 587 free_top = previousLimit - 1; 588 if (limit > free_top) { 589 SetHighColor (idle_color); 590 FillRect(BRect(leftMem, free_top, rightMem, limit - 1)); 591 } 592 if (barHeight <= h) { 593 rgb_color fraction_color; 594 mix_colors(fraction_color, idle_color, used_memory_color, rem); 595 SetHighColor(fraction_color); 596 StrokeLine(BPoint(leftMem, bottom - barHeight), BPoint(rightMem, 597 bottom - barHeight)); 598 } 599 float usedBottom = bottom; 600 // if (!force && previousLimit < bottom) 601 // usedBottom = previousLimit + 1; 602 if (limit < usedBottom) { 603 SetHighColor(used_memory_color); 604 FillRect(BRect(leftMem, limit + 1, rightMem, usedBottom)); 605 } 606 fLastMemoryHeight = barHeight; 607 } 608 609 610 void 611 ProcessController::Update() 612 { 613 system_info info; 614 get_system_info(&info); 615 bigtime_t now = system_time(); 616 617 fMemoryUsage = float(info.used_pages) / float(info.max_pages); 618 // Calculate work done since last call to Update() for each CPU 619 for (int x = 0; x < gCPUcount; x++) { 620 bigtime_t load = info.cpu_infos[x].active_time - fPrevActive[x]; 621 bigtime_t passed = now - fPrevTime; 622 float cpuTime = float(load) / float(passed); 623 624 fPrevActive[x] = info.cpu_infos[x].active_time; 625 if (load > passed) 626 fPrevActive[x] -= load - passed; // save overload for next period... 627 if (cpuTime < 0) 628 cpuTime = 0; 629 if (cpuTime > 1) 630 cpuTime = 1; 631 fCPUTimes[x] = cpuTime; 632 } 633 fPrevTime = now; 634 } 635 636 637 // #pragma mark - 638 639 640 long 641 thread_popup(void *arg) 642 { 643 Tpopup_param* param = (Tpopup_param*) arg; 644 int32 mcookie, hcookie; 645 long m, h; 646 BMenuItem* item; 647 bool top = param->top; 648 649 system_info systemInfo; 650 get_system_info(&systemInfo); 651 info_pack* infos = new info_pack[systemInfo.used_teams]; 652 // TODO: this doesn't necessarily get all teams 653 for (m = 0, mcookie = 0; m < systemInfo.used_teams; m++) { 654 infos[m].team_icon = NULL; 655 infos[m].team_name[0] = 0; 656 infos[m].thread_info = NULL; 657 if (get_next_team_info(&mcookie, &infos[m].team_info) == B_OK) { 658 infos[m].thread_info = new thread_info[infos[m].team_info.thread_count]; 659 for (h = 0, hcookie = 0; h < infos[m].team_info.thread_count; h++) { 660 if (get_next_thread_info(infos[m].team_info.team, &hcookie, 661 &infos[m].thread_info[h]) != B_OK) 662 infos[m].thread_info[h].thread = -1; 663 } 664 get_team_name_and_icon(infos[m], true); 665 } else { 666 systemInfo.used_teams = m; 667 infos[m].team_info.team = -1; 668 } 669 } 670 671 BPopUpMenu* popup = new BPopUpMenu("Global Popup", false, false); 672 popup->SetFont(be_plain_font); 673 674 // Quit section 675 BMenu* QuitPopup = new QuitMenu(B_TRANSLATE("Quit an application"), 676 infos, systemInfo.used_teams); 677 QuitPopup->SetFont(be_plain_font); 678 popup->AddItem(QuitPopup); 679 680 // Memory Usage section 681 MemoryBarMenu* MemoryPopup = new MemoryBarMenu(B_TRANSLATE("Memory usage"), 682 infos, systemInfo); 683 int commitedMemory = int(systemInfo.used_pages * B_PAGE_SIZE / 1024); 684 for (m = 0; m < systemInfo.used_teams; m++) { 685 if (infos[m].team_info.team >= 0) { 686 MemoryBarMenuItem* memoryItem = 687 new MemoryBarMenuItem(infos[m].team_name, 688 infos[m].team_info.team, infos[m].team_icon, false, NULL); 689 MemoryPopup->AddItem(memoryItem); 690 memoryItem->UpdateSituation(commitedMemory); 691 } 692 } 693 694 addtopbottom(MemoryPopup); 695 696 // CPU Load section 697 TeamBarMenu* CPUPopup = new TeamBarMenu(B_TRANSLATE("Threads and CPU " 698 "usage"), infos, systemInfo.used_teams); 699 for (m = 0; m < systemInfo.used_teams; m++) { 700 if (infos[m].team_info.team >= 0) { 701 ThreadBarMenu* TeamPopup = new ThreadBarMenu(infos[m].team_name, 702 infos[m].team_info.team, infos[m].team_info.thread_count); 703 BMessage* kill_team = new BMessage('KlTm'); 704 kill_team->AddInt32("team", infos[m].team_info.team); 705 TeamBarMenuItem* item = new TeamBarMenuItem(TeamPopup, kill_team, 706 infos[m].team_info.team, infos[m].team_icon, false); 707 item->SetTarget(gPCView); 708 CPUPopup->AddItem(item); 709 } 710 } 711 712 addtopbottom(CPUPopup); 713 addtopbottom(new BSeparatorItem()); 714 715 // CPU on/off section 716 if (gCPUcount > 1) { 717 for (int i = 0; i < gCPUcount; i++) { 718 char item_name[32]; 719 sprintf (item_name, B_TRANSLATE("Processor %d"), i + 1); 720 BMessage* m = new BMessage ('CPU '); 721 m->AddInt32 ("cpu", i); 722 item = new IconMenuItem (gPCView->fProcessorIcon, item_name, m); 723 if (_kern_cpu_enabled(i)) 724 item->SetMarked (true); 725 item->SetTarget(gPCView); 726 addtopbottom(item); 727 } 728 addtopbottom (new BSeparatorItem ()); 729 } 730 731 if (!be_roster->IsRunning(kTrackerSig)) { 732 item = new IconMenuItem(gPCView->fTrackerIcon, 733 B_TRANSLATE("Restart Tracker"), new BMessage('Trac')); 734 item->SetTarget(gPCView); 735 addtopbottom(item); 736 } 737 if (!be_roster->IsRunning(kDeskbarSig)) { 738 item = new IconMenuItem(gPCView->fDeskbarIcon, 739 B_TRANSLATE("Restart Deskbar"), new BMessage('Dbar')); 740 item->SetTarget(gPCView); 741 addtopbottom(item); 742 } 743 744 item = new IconMenuItem(gPCView->fTerminalIcon, 745 B_TRANSLATE("New Terminal"), new BMessage('Term')); 746 item->SetTarget(gPCView); 747 addtopbottom(item); 748 749 addtopbottom(new BSeparatorItem()); 750 751 if (be_roster->IsRunning(kDeskbarSig)) { 752 item = new BMenuItem(B_TRANSLATE("Live in the Deskbar"), 753 new BMessage('AlDb')); 754 BDeskbar deskbar; 755 item->SetMarked(gInDeskbar || deskbar.HasItem(kDeskbarItemName)); 756 item->SetTarget(gPCView); 757 addtopbottom(item); 758 addtopbottom(new BSeparatorItem ()); 759 } 760 761 item = new IconMenuItem(gPCView->fProcessControllerIcon, 762 B_TRANSLATE("About ProcessController"B_UTF8_ELLIPSIS), 763 new BMessage(B_ABOUT_REQUESTED)); 764 item->SetTarget(gPCView); 765 addtopbottom(item); 766 767 param->where.x -= 5; 768 param->where.y -= 8; 769 popup->Go(param->where, true, true, param->clickToOpenRect); 770 771 delete popup; 772 for (m = 0; m < systemInfo.used_teams; m++) { 773 if (infos[m].team_info.team >= 0) { 774 delete[] infos[m].thread_info; 775 delete infos[m].team_icon; 776 } 777 } 778 delete[] infos; 779 delete param; 780 atomic_add (&gPopupFlag, -1); 781 gPopupThreadID = 0; 782 783 return B_OK; 784 } 785 786 787 long 788 thread_quit_application(void *arg) 789 { 790 BMessenger messenger(NULL, (team_id)arg); 791 messenger.SendMessage(B_QUIT_REQUESTED); 792 return B_OK; 793 } 794 795 796 long 797 thread_debug_thread(void *arg) 798 { 799 Tdebug_thead_param* param = (Tdebug_thead_param*) arg; 800 #ifdef __HAIKU__ 801 debug_thread(param->thread); 802 #else // !__HAIKU__ 803 thread_info thinfo; 804 get_thread_info(param->thread, &thinfo); 805 char text[4096]; 806 sprintf(text, "db %d", int(param->thread)); 807 system(text); 808 if (param->sem >= 0 && thinfo.state == B_THREAD_WAITING && param->sem 809 == thinfo.sem) { 810 snooze(1000000); 811 get_thread_info(param->thread, &thinfo); 812 if (thinfo.state == B_THREAD_WAITING 813 && param->sem == thinfo.sem 814 && param->totalTime == thinfo.user_time + thinfo.kernel_time) { 815 // the thread has been waiting for this semaphore since the before 816 // the alert, not doing anything... Let's push it out of there! 817 sem_info sinfo; 818 thread_info thinfo; 819 info_pack infos; 820 821 if (get_sem_info(param->sem, &sinfo) == B_OK 822 && get_thread_info(param->thread, &thinfo) == B_OK 823 && get_team_info(thinfo.team, &infos.team_info) == B_OK) { 824 sprintf (text, "This thread is waiting for the " 825 "semaphore called \"%s\". As long as it waits for this " 826 "semaphore, you won't be able to debug that thread.\n", 827 sinfo.name); 828 if (sinfo.team == thinfo.team) 829 strcat(text, "This semaphore belongs to the " 830 "thread's team.\n\nShould I release this semaphore?\n"); 831 else { 832 get_team_name_and_icon(infos); 833 char moreText[1024]; 834 sprintf(moreText, "\nWARNING! This semaphore " 835 "belongs to the team \"%s\"!\n\nShould I release this " 836 "semaphore anyway?\n", 837 infos.team_name); 838 strcat(text, moreText); 839 } 840 841 BAlert* alert = new BAlert("", text, "Cancel", "Release", 842 NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); 843 alert->SetShortcut(0, B_ESCAPE); 844 if (alert->Go()) { 845 get_thread_info (param->thread, &thinfo); 846 if (thinfo.state == B_THREAD_WAITING && param->sem 847 == thinfo.sem 848 && param->totalTime == thinfo.user_time 849 + thinfo.kernel_time) 850 release_sem(param->sem); 851 else { 852 alert = new BAlert("", "The semaphore wasn't released, " 853 "because it wasn't necessary anymore!", 854 "OK", NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); 855 alert->Go(); 856 } 857 } 858 } 859 } 860 } 861 #endif // !__HAIKU__ 862 delete param; 863 return B_OK; 864 } 865