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 { 349 BPath trackerPath; 350 if (find_directory(B_SYSTEM_DIRECTORY, &trackerPath) == B_OK 351 && trackerPath.Append("Tracker") == B_OK) { 352 launch(kTrackerSig, trackerPath.Path()); 353 } 354 break; 355 } 356 357 case 'Dbar': 358 { 359 BPath deskbarPath; 360 if (find_directory(B_SYSTEM_DIRECTORY, &deskbarPath) == B_OK 361 && deskbarPath.Append("Deskbar") == B_OK) { 362 launch(kDeskbarSig, deskbarPath.Path()); 363 } 364 break; 365 } 366 367 case 'Term': 368 { 369 BPath terminalPath; 370 if (find_directory(B_SYSTEM_APPS_DIRECTORY, &terminalPath) == B_OK 371 && terminalPath.Append("Deskbar") == B_OK) { 372 launch(kTerminalSig, terminalPath.Path()); 373 } 374 launch(kTerminalSig, terminalPath.Path()); 375 break; 376 } 377 378 case 'AlDb': 379 { 380 if (!be_roster->IsRunning(kDeskbarSig)) { 381 BPath deskbarPath; 382 if (find_directory(B_SYSTEM_DIRECTORY, &deskbarPath) == B_OK 383 && deskbarPath.Append("Deskbar") == B_OK) { 384 launch(kDeskbarSig, deskbarPath.Path()); 385 } 386 } 387 BDeskbar deskbar; 388 if (gInDeskbar || deskbar.HasItem (kDeskbarItemName)) 389 deskbar.RemoveItem (kDeskbarItemName); 390 else 391 move_to_deskbar(deskbar); 392 break; 393 } 394 395 case 'CPU ': 396 { 397 int32 cpu; 398 if (message->FindInt32 ("cpu", &cpu) == B_OK) { 399 bool last = true; 400 for (int p = 0; p < gCPUcount; p++) { 401 if (p != cpu && _kern_cpu_enabled(p)) { 402 last = false; 403 break; 404 } 405 } 406 if (last) { 407 alert = new BAlert(B_TRANSLATE("Info"), 408 B_TRANSLATE("This is the last active processor...\n" 409 "You can't turn it off!"), 410 B_TRANSLATE("That's no Fun!"), NULL, NULL, 411 B_WIDTH_AS_USUAL, B_WARNING_ALERT); 412 alert->SetShortcut(0, B_ESCAPE); 413 alert->Go(); 414 } else 415 _kern_set_cpu_enabled(cpu, !_kern_cpu_enabled(cpu)); 416 } 417 break; 418 } 419 420 case B_ABOUT_REQUESTED: 421 AboutRequested(); 422 break; 423 424 default: 425 BView::MessageReceived(message); 426 } 427 } 428 429 430 void 431 ProcessController::AboutRequested() 432 { 433 const char* authors[] = { 434 "Georges-Edouard Berenger", 435 NULL 436 }; 437 438 BAboutWindow about(B_TRANSLATE_SYSTEM_NAME("ProcessController"), 2007, authors, 439 "Copyright 1997-2001\n" 440 "Georges-Edouard Berenger."); 441 about.Show(); 442 } 443 444 445 void 446 ProcessController::DefaultColors() 447 { 448 swap_color.red = 203; 449 swap_color.green = 0; 450 swap_color.blue = 0; 451 swap_color.alpha = 255; 452 bool set = false; 453 454 if (!set) { 455 active_color = kKernelBlue; 456 active_color = tint_color (active_color, B_LIGHTEN_2_TINT); 457 idle_color = active_color; 458 idle_color.green /= 3; 459 idle_color.red /= 3; 460 idle_color.blue /= 3; 461 frame_color = kBlack; 462 mix_colors (memory_color, active_color, swap_color, 0.2); 463 } 464 } 465 466 467 void 468 ProcessController::AttachedToWindow() 469 { 470 BView::AttachedToWindow(); 471 if (Parent()) 472 SetViewColor(B_TRANSPARENT_COLOR); 473 else 474 SetViewColor(kBlack); 475 476 Preferences tPreferences(kPreferencesFileName, NULL, false); 477 DefaultColors(); 478 479 system_info info; 480 get_system_info(&info); 481 gCPUcount = info.cpu_count; 482 Update(); 483 484 gIdleColor = kIdleGreen; 485 gIdleColorSelected = tint_color(gIdleColor, B_HIGHLIGHT_BACKGROUND_TINT); 486 gKernelColor = kKernelBlue; 487 gKernelColorSelected = tint_color(gKernelColor, B_HIGHLIGHT_BACKGROUND_TINT); 488 gUserColor = tint_color(gKernelColor, B_LIGHTEN_2_TINT); 489 gUserColorSelected = tint_color(gUserColor, B_HIGHLIGHT_BACKGROUND_TINT); 490 gFrameColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 491 B_HIGHLIGHT_BACKGROUND_TINT); 492 gFrameColorSelected = tint_color(gFrameColor, B_HIGHLIGHT_BACKGROUND_TINT); 493 gMenuBackColor = ui_color(B_MENU_BACKGROUND_COLOR); 494 gMenuBackColorSelected = ui_color(B_MENU_SELECTION_BACKGROUND_COLOR); 495 gWhiteSelected = tint_color(kWhite, B_HIGHLIGHT_BACKGROUND_TINT); 496 497 BMessenger messenger(this); 498 BMessage message('Puls'); 499 fMessageRunner = new BMessageRunner(messenger, &message, 250000, -1); 500 } 501 502 503 504 void 505 ProcessController::MouseDown(BPoint where) 506 { 507 if (atomic_add(&gPopupFlag, 1) > 0) { 508 atomic_add(&gPopupFlag, -1); 509 return; 510 } 511 512 Tpopup_param* param = new Tpopup_param; 513 ConvertToScreen(&where); 514 param->where = where; 515 param->clickToOpenRect = Frame (); 516 ConvertToScreen (¶m->clickToOpenRect); 517 param->top = where.y < BScreen(this->Window()).Frame().bottom-50; 518 519 gPopupThreadID = spawn_thread(thread_popup, "Popup holder thread", 520 B_URGENT_DISPLAY_PRIORITY, param); 521 resume_thread(gPopupThreadID); 522 } 523 524 525 void 526 ProcessController::Draw(BRect) 527 { 528 SetDrawingMode(B_OP_COPY); 529 DoDraw(true); 530 } 531 532 533 void 534 ProcessController::DoDraw(bool force) 535 { 536 BRect bounds(Bounds()); 537 538 float h = floorf(bounds.Height ()) - 2; 539 float top = 1, left = 1; 540 float bottom = top + h; 541 float barWidth = layout[gCPUcount].cpu_width; 542 // interspace 543 float right = left + gCPUcount * (barWidth + layout[gCPUcount].cpu_inter) 544 - layout[gCPUcount].cpu_inter; // right of CPU frame... 545 if (force && Parent()) { 546 SetHighColor(Parent()->ViewColor ()); 547 FillRect(BRect(right + 1, top - 1, right + 2, bottom + 1)); 548 } 549 550 if (force) { 551 SetHighColor(frame_color); 552 StrokeRect(BRect(left - 1, top - 1, right, bottom + 1)); 553 if (gCPUcount == 2) { 554 StrokeLine(BPoint(left + barWidth, top), BPoint(left + barWidth, 555 bottom)); 556 } 557 } 558 float leftMem = bounds.Width() - layout[gCPUcount].mem_width; 559 if (force) 560 StrokeRect(BRect(leftMem - 1, top - 1, 561 leftMem + layout[gCPUcount].mem_width, bottom + 1)); 562 563 for (int x = 0; x < gCPUcount; x++) { 564 right = left + barWidth - 1; 565 float rem = fCPUTimes[x] * (h + 1); 566 float barHeight = floorf (rem); 567 rem -= barHeight; 568 float limit = bottom - barHeight; // horizontal line 569 float previousLimit = bottom - fLastBarHeight[x]; 570 float idleTop = top; 571 572 if (!force && previousLimit > top) 573 idleTop = previousLimit - 1; 574 if (limit > idleTop) { 575 SetHighColor(idle_color); 576 FillRect(BRect(left, idleTop, right, limit - 1)); 577 } 578 if (barHeight <= h) { 579 rgb_color fraction_color; 580 mix_colors(fraction_color, idle_color, active_color, rem); 581 SetHighColor(fraction_color); 582 StrokeLine(BPoint(left, bottom - barHeight), BPoint(right, 583 bottom - barHeight)); 584 } 585 float active_bottom = bottom; 586 if (!force && previousLimit < bottom) 587 active_bottom = previousLimit + 1; 588 if (limit < active_bottom) { 589 SetHighColor(active_color); 590 FillRect(BRect(left, limit + 1, right, active_bottom)); 591 } 592 left += layout[gCPUcount].cpu_width + layout[gCPUcount].cpu_inter; 593 fLastBarHeight[x] = barHeight; 594 } 595 596 float rightMem = bounds.Width () - 1; 597 float rem = fMemoryUsage * (h + 1); 598 float barHeight = floorf (rem); 599 rem -= barHeight; 600 601 rgb_color used_memory_color; 602 float sq = fMemoryUsage * fMemoryUsage; 603 sq *= sq; 604 sq *= sq; 605 mix_colors(used_memory_color, memory_color, swap_color, sq); 606 607 float limit = bottom - barHeight; // horizontal line 608 float previousLimit = bottom - fLastMemoryHeight; 609 float free_top = top; 610 if (!force && previousLimit > top) 611 free_top = previousLimit - 1; 612 if (limit > free_top) { 613 SetHighColor (idle_color); 614 FillRect(BRect(leftMem, free_top, rightMem, limit - 1)); 615 } 616 if (barHeight <= h) { 617 rgb_color fraction_color; 618 mix_colors(fraction_color, idle_color, used_memory_color, rem); 619 SetHighColor(fraction_color); 620 StrokeLine(BPoint(leftMem, bottom - barHeight), BPoint(rightMem, 621 bottom - barHeight)); 622 } 623 float usedBottom = bottom; 624 // if (!force && previousLimit < bottom) 625 // usedBottom = previousLimit + 1; 626 if (limit < usedBottom) { 627 SetHighColor(used_memory_color); 628 FillRect(BRect(leftMem, limit + 1, rightMem, usedBottom)); 629 } 630 fLastMemoryHeight = barHeight; 631 } 632 633 634 void 635 ProcessController::Update() 636 { 637 system_info info; 638 get_system_info(&info); 639 bigtime_t now = system_time(); 640 641 fMemoryUsage = float(info.used_pages) / float(info.max_pages); 642 // Calculate work done since last call to Update() for each CPU 643 for (int x = 0; x < gCPUcount; x++) { 644 bigtime_t load = info.cpu_infos[x].active_time - fPrevActive[x]; 645 bigtime_t passed = now - fPrevTime; 646 float cpuTime = float(load) / float(passed); 647 648 fPrevActive[x] = info.cpu_infos[x].active_time; 649 if (load > passed) 650 fPrevActive[x] -= load - passed; // save overload for next period... 651 if (cpuTime < 0) 652 cpuTime = 0; 653 if (cpuTime > 1) 654 cpuTime = 1; 655 fCPUTimes[x] = cpuTime; 656 } 657 fPrevTime = now; 658 } 659 660 661 // #pragma mark - 662 663 664 long 665 thread_popup(void *arg) 666 { 667 Tpopup_param* param = (Tpopup_param*) arg; 668 int32 mcookie, hcookie; 669 long m, h; 670 BMenuItem* item; 671 bool top = param->top; 672 673 system_info systemInfo; 674 get_system_info(&systemInfo); 675 info_pack* infos = new info_pack[systemInfo.used_teams]; 676 // TODO: this doesn't necessarily get all teams 677 for (m = 0, mcookie = 0; m < systemInfo.used_teams; m++) { 678 infos[m].team_icon = NULL; 679 infos[m].team_name[0] = 0; 680 infos[m].thread_info = NULL; 681 if (get_next_team_info(&mcookie, &infos[m].team_info) == B_OK) { 682 infos[m].thread_info = new thread_info[infos[m].team_info.thread_count]; 683 for (h = 0, hcookie = 0; h < infos[m].team_info.thread_count; h++) { 684 if (get_next_thread_info(infos[m].team_info.team, &hcookie, 685 &infos[m].thread_info[h]) != B_OK) 686 infos[m].thread_info[h].thread = -1; 687 } 688 get_team_name_and_icon(infos[m], true); 689 } else { 690 systemInfo.used_teams = m; 691 infos[m].team_info.team = -1; 692 } 693 } 694 695 BPopUpMenu* popup = new BPopUpMenu("Global Popup", false, false); 696 popup->SetFont(be_plain_font); 697 698 // Quit section 699 BMenu* QuitPopup = new QuitMenu(B_TRANSLATE("Quit an application"), 700 infos, systemInfo.used_teams); 701 QuitPopup->SetFont(be_plain_font); 702 popup->AddItem(QuitPopup); 703 704 // Memory Usage section 705 MemoryBarMenu* MemoryPopup = new MemoryBarMenu(B_TRANSLATE("Memory usage"), 706 infos, systemInfo); 707 int commitedMemory = int(systemInfo.used_pages * B_PAGE_SIZE / 1024); 708 for (m = 0; m < systemInfo.used_teams; m++) { 709 if (infos[m].team_info.team >= 0) { 710 MemoryBarMenuItem* memoryItem = 711 new MemoryBarMenuItem(infos[m].team_name, 712 infos[m].team_info.team, infos[m].team_icon, false, NULL); 713 MemoryPopup->AddItem(memoryItem); 714 memoryItem->UpdateSituation(commitedMemory); 715 } 716 } 717 718 addtopbottom(MemoryPopup); 719 720 // CPU Load section 721 TeamBarMenu* CPUPopup = new TeamBarMenu(B_TRANSLATE("Threads and CPU " 722 "usage"), infos, systemInfo.used_teams); 723 for (m = 0; m < systemInfo.used_teams; m++) { 724 if (infos[m].team_info.team >= 0) { 725 ThreadBarMenu* TeamPopup = new ThreadBarMenu(infos[m].team_name, 726 infos[m].team_info.team, infos[m].team_info.thread_count); 727 BMessage* kill_team = new BMessage('KlTm'); 728 kill_team->AddInt32("team", infos[m].team_info.team); 729 TeamBarMenuItem* item = new TeamBarMenuItem(TeamPopup, kill_team, 730 infos[m].team_info.team, infos[m].team_icon, false); 731 item->SetTarget(gPCView); 732 CPUPopup->AddItem(item); 733 } 734 } 735 736 addtopbottom(CPUPopup); 737 addtopbottom(new BSeparatorItem()); 738 739 // CPU on/off section 740 if (gCPUcount > 1) { 741 for (int i = 0; i < gCPUcount; i++) { 742 char item_name[32]; 743 sprintf (item_name, B_TRANSLATE("Processor %d"), i + 1); 744 BMessage* m = new BMessage ('CPU '); 745 m->AddInt32 ("cpu", i); 746 item = new IconMenuItem (gPCView->fProcessorIcon, item_name, m); 747 if (_kern_cpu_enabled(i)) 748 item->SetMarked (true); 749 item->SetTarget(gPCView); 750 addtopbottom(item); 751 } 752 addtopbottom (new BSeparatorItem ()); 753 } 754 755 if (!be_roster->IsRunning(kTrackerSig)) { 756 item = new IconMenuItem(gPCView->fTrackerIcon, 757 B_TRANSLATE("Restart Tracker"), new BMessage('Trac')); 758 item->SetTarget(gPCView); 759 addtopbottom(item); 760 } 761 if (!be_roster->IsRunning(kDeskbarSig)) { 762 item = new IconMenuItem(gPCView->fDeskbarIcon, 763 B_TRANSLATE("Restart Deskbar"), new BMessage('Dbar')); 764 item->SetTarget(gPCView); 765 addtopbottom(item); 766 } 767 768 item = new IconMenuItem(gPCView->fTerminalIcon, 769 B_TRANSLATE("New Terminal"), new BMessage('Term')); 770 item->SetTarget(gPCView); 771 addtopbottom(item); 772 773 addtopbottom(new BSeparatorItem()); 774 775 if (be_roster->IsRunning(kDeskbarSig)) { 776 item = new BMenuItem(B_TRANSLATE("Live in the Deskbar"), 777 new BMessage('AlDb')); 778 BDeskbar deskbar; 779 item->SetMarked(gInDeskbar || deskbar.HasItem(kDeskbarItemName)); 780 item->SetTarget(gPCView); 781 addtopbottom(item); 782 addtopbottom(new BSeparatorItem ()); 783 } 784 785 item = new IconMenuItem(gPCView->fProcessControllerIcon, 786 B_TRANSLATE("About ProcessController"B_UTF8_ELLIPSIS), 787 new BMessage(B_ABOUT_REQUESTED)); 788 item->SetTarget(gPCView); 789 addtopbottom(item); 790 791 param->where.x -= 5; 792 param->where.y -= 8; 793 popup->Go(param->where, true, true, param->clickToOpenRect); 794 795 delete popup; 796 for (m = 0; m < systemInfo.used_teams; m++) { 797 if (infos[m].team_info.team >= 0) { 798 delete[] infos[m].thread_info; 799 delete infos[m].team_icon; 800 } 801 } 802 delete[] infos; 803 delete param; 804 atomic_add (&gPopupFlag, -1); 805 gPopupThreadID = 0; 806 807 return B_OK; 808 } 809 810 811 long 812 thread_quit_application(void *arg) 813 { 814 BMessenger messenger(NULL, (team_id)arg); 815 messenger.SendMessage(B_QUIT_REQUESTED); 816 return B_OK; 817 } 818 819 820 long 821 thread_debug_thread(void *arg) 822 { 823 Tdebug_thead_param* param = (Tdebug_thead_param*) arg; 824 #ifdef __HAIKU__ 825 debug_thread(param->thread); 826 #else // !__HAIKU__ 827 thread_info thinfo; 828 get_thread_info(param->thread, &thinfo); 829 char text[4096]; 830 sprintf(text, "db %d", int(param->thread)); 831 system(text); 832 if (param->sem >= 0 && thinfo.state == B_THREAD_WAITING && param->sem 833 == thinfo.sem) { 834 snooze(1000000); 835 get_thread_info(param->thread, &thinfo); 836 if (thinfo.state == B_THREAD_WAITING 837 && param->sem == thinfo.sem 838 && param->totalTime == thinfo.user_time + thinfo.kernel_time) { 839 // the thread has been waiting for this semaphore since the before 840 // the alert, not doing anything... Let's push it out of there! 841 sem_info sinfo; 842 thread_info thinfo; 843 info_pack infos; 844 845 if (get_sem_info(param->sem, &sinfo) == B_OK 846 && get_thread_info(param->thread, &thinfo) == B_OK 847 && get_team_info(thinfo.team, &infos.team_info) == B_OK) { 848 sprintf (text, "This thread is waiting for the " 849 "semaphore called \"%s\". As long as it waits for this " 850 "semaphore, you won't be able to debug that thread.\n", 851 sinfo.name); 852 if (sinfo.team == thinfo.team) 853 strcat(text, "This semaphore belongs to the " 854 "thread's team.\n\nShould I release this semaphore?\n"); 855 else { 856 get_team_name_and_icon(infos); 857 char moreText[1024]; 858 sprintf(moreText, "\nWARNING! This semaphore " 859 "belongs to the team \"%s\"!\n\nShould I release this " 860 "semaphore anyway?\n", 861 infos.team_name); 862 strcat(text, moreText); 863 } 864 865 BAlert* alert = new BAlert("", text, "Cancel", "Release", 866 NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); 867 alert->SetShortcut(0, B_ESCAPE); 868 if (alert->Go()) { 869 get_thread_info (param->thread, &thinfo); 870 if (thinfo.state == B_THREAD_WAITING && param->sem 871 == thinfo.sem 872 && param->totalTime == thinfo.user_time 873 + thinfo.kernel_time) 874 release_sem(param->sem); 875 else { 876 alert = new BAlert("", "The semaphore wasn't released, " 877 "because it wasn't necessary anymore!", 878 "OK", NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); 879 alert->Go(); 880 } 881 } 882 } 883 } 884 } 885 #endif // !__HAIKU__ 886 delete param; 887 return B_OK; 888 } 889