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