1 /* 2 * Some or all of this work - Copyright (c) 2006 - 2021, Intel Corp. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * Neither the name of Intel Corporation nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 /* 29 * SEE: 30 * ??????????? Multi-threading common definitions 31 * see: see structure and the name of this file also later !!!!!!!!!!!!!! 32 * ?????????????????????????????????????????????????????????????????????? 33 * 34 * 35 * NOTIONS and NOTATIONS: 36 * 37 * ID and Index of thread: 38 * 39 * each thread is identified by its ID (delivered from the underlying system) 40 * and its calculated unique index between all the threads participating in 41 * the test. 42 * 43 * Control Thread - the thread with index equal to 0 44 * Worker Threads - all other threads with the non-zero index 45 * 46 * Number of threads (total) - 47 * the value passed to AcpiExec Threads command 48 * as a number of threads parameter. 49 * 50 * Number of threads actually in work - 51 * number of threads actually participating the relevant test. 52 * Note: this value includes the Control Thread too. 53 */ 54 Name (Z147, 0x93) 55 /* 56 * Common data of threads 57 * 58 * Usage: 59 * 60 * command line: Threads 6 1 MAIN 61 * 6 - number of threads, it can be greater or less than 6 62 * 63 * redm - set it to zero to reduce the run time 64 * vb00-vb06 - use them to suppress the output 65 * 66 * FLG1 - the _TCI-based Initialization of multithreading interconnection 67 * (run command TCI_CMD_GET_ID_OF_THREADS to determine indexes of threads) 68 */ 69 /* 70 * Flags 71 */ 72 Name (CTL0, 0x00) /* the Control thread is ready */ 73 Name (REDM, 0x01) /* run tests in reduced mode */ 74 Name (GLDI, 0x00) /* global data initialized */ 75 /* 76 * Simple switch of the verbal mode 77 * 78 * 0 - silent 79 * otherwise - allow 80 * 81 * s-flags (defaults are given in comment (0/1)) 82 */ 83 Name (VB00, 0x00) /* (0) common messages */ 84 Name (VB02, 0x01) /* (1) trace Control thread */ 85 Name (VB03, 0x00) /* (0) trace Worker threads */ 86 Name (VB04, 0x01) /* (1) report statistics */ 87 Name (VB05, 0x00) /* (0) report warnings by worker-threads */ 88 Name (VB06, 0x01) /* (1) report errors by worker-threads */ 89 /* 90 * Multi-conditional switches of the verbal mode 91 * 92 * 0 - silent 93 * 1 - allow only for Control Thread to report 94 * 2 - allow only for Worker Threads to report 95 * 3 - allow for all threads to report 96 * 97 * mc-flags 98 */ 99 Name (VB01, 0x01) /* header of test */ 100 /* Sleep mode */ 101 102 Name (SL00, 0x32) /* Default milliseconds to sleep for Control thread */ 103 Name (SL01, 0x32) /* Default milliseconds to sleep for Worker threads */ 104 /* 105 * Default milliseconds to sleep for Control thread 106 * before to check hang status of worker threads on 107 * operations. 108 */ 109 Name (SL02, 0x01F4) 110 /* How many times maximum to repeat sl02 sleeping */ 111 112 Name (SL03, 0x01) 113 Name (SLM0, 0x00) /* Sleeping mode for worker threads */ 114 /* Milliseconds to sleep for non-zero slm0 */ 115 116 Name (I100, 0x32) 117 Name (I101, 0x64) 118 Name (I102, 0xC8) 119 Name (I103, 0x0190) 120 Name (I104, 0x01F4) 121 Name (I105, 0x4B) 122 Name (I106, 0x96) 123 Name (I107, 0xFA) 124 Name (I108, 0x012C) 125 /* Commands for workers */ 126 127 Name (C100, 0xF0) /* Idle thread */ 128 Name (C101, 0xF1) /* Exit the infinite loop */ 129 Name (C102, 0xF2) /* Sleep for the specified number of Milliseconds */ 130 Name (C103, 0xF3) /* Acquire/Sleep/Release */ 131 Name (C104, 0xF4) /* <Acquire/Sleep>(0-15 levels)/Release(15-0 levels) */ 132 Name (C105, 0xF5) /* Example 0 */ 133 Name (C106, 0xF6) /* Acquire specified set of mutexes */ 134 Name (C107, 0xF7) /* Release specified set of mutexes */ 135 Name (C108, 0xF8) /* Terminate thread */ 136 Name (C109, 0xF9) /* Invoke Serialized method */ 137 Name (C10A, 0xFA) /* Invoke non-Serialized method, use Mutex for exclusive access to critical section */ 138 Name (C10B, 0xFB) /* Non-serialized method is grabbed simultaneously */ 139 /* Responds of worker threads (not intersect with 'Commands for workers') */ 140 141 Name (RS00, 0x97) /* "I see zero do00" */ 142 /* Common use strategies provided by the Control thread */ 143 144 Name (CM01, 0x01) /* all workers to exit the infinite loop */ 145 Name (CM02, 0x02) /* all workers to sleep for the specified period */ 146 /* 147 * This buffer is to be filled by the control thread. 148 * It is filed with the commands to be fulfilled by the 149 * worker threads. 150 * 151 * The thread of i-th index takes the command from the 152 * i-th element of Buffer. 153 * 154 * It is read-only for worker threads. 155 */ 156 Name (BS00, Buffer (0x01) 157 { 158 0x00 // . 159 }) 160 /* 161 * This buffer is zeroed by the control thread and then to be 162 * filled by the worker threads with the commands they have been 163 * fulfilled. 164 */ 165 Name (BS01, Buffer (0x01) 166 { 167 0x00 // . 168 }) 169 /* 170 * This buffer is zeroed by the control thread and then to be 171 * filled by the worker threads when they see that do00 is zero. 172 * 173 * The control thread uses it to check that all the worker threads 174 * saw zero do00 (are idle) before to start the next command. 175 */ 176 Name (BS02, Buffer (0x01) 177 { 178 0x00 // . 179 }) 180 /* 181 * This buffer is zeroed by the control thread and then to 182 * be filled by the idle worker threads. 183 */ 184 Name (BS03, Buffer (0x01) 185 { 186 0x00 // . 187 }) 188 /* 189 * This buffer is zeroed by the control thread and then to be 190 * set up by the worker threads when they complete. 191 */ 192 Name (BS04, Buffer (0x01) 193 { 194 0x00 // . 195 }) 196 /* 197 * p10X - statistics 198 */ 199 /* 200 * These package are zeroed by the control thread, 201 * the worker threads accumulate there: 202 * - errors 203 * - number of errors 204 * - warnings 205 * - number of warnings 206 */ 207 Name (P100, Package (0x01) 208 { 209 0x00 210 }) /* scale of errors */ 211 Name (P101, Package (0x01) 212 { 213 0x00 214 }) /* number of errors */ 215 Name (P102, Package (0x01) 216 { 217 0x00 218 }) /* scale of warnings */ 219 Name (P103, Package (0x01) 220 { 221 0x00 222 }) /* number of warnings */ 223 /* Command statistics */ 224 225 Name (P104, Package (0x01) 226 { 227 0x00 228 }) /* number of Sleep */ 229 Name (P105, Package (0x01) 230 { 231 0x00 232 }) /* number of Acquire */ 233 Name (P106, Package (0x01) 234 { 235 0x00 236 }) /* number of Release */ 237 /* 238 * To be filled by the control thread, 239 * non-zero enables to fulfill the commands specified by bs00. 240 */ 241 Name (DO00, 0x00) 242 /* Opcodes of errors reported by worker threads */ 243 244 Name (ER00, 0x01) /* Acquire failed */ 245 Name (ER01, 0x02) /* Flag of mutex is already non-zero (set up by some thread(s)) */ 246 Name (ER02, 0x04) /* Invalid flag of mutex (changed by other thread while this one owned that mutex) */ 247 Name (ER03, 0x08) /* Unexpected exception */ 248 Name (ER04, 0x10) /* Improper exception (no exception, or unexpected opcode, or more than one exception) */ 249 Name (ER05, 0x20) /* Invalid command */ 250 Name (ER06, 0x40) /* Invalid Index of current thread */ 251 Name (ER07, 0x80) /* Too big Index of current thread */ 252 Name (ER08, 0x0100) /* Invalid counter of mutex owning */ 253 Name (ER09, 0x0200) /* Acquire returned zero but FAIL expected */ 254 Name (ER10, 0x0400) /* Serialized method doesn't provide exclusive call */ 255 Name (ER11, 0x0800) /* Serialized method doesn't provide exclusive call */ 256 Name (ER12, 0x1000) /* Non-serialized method thr-1 didn't get into method */ 257 Name (ER13, 0x2000) /* Non-serialized method thr-N didn't get into method */ 258 /* Opcodes of warnings reported by worker threads */ 259 260 Name (WN00, 0x01) /* Acquire repeatedly the same mutex by thread which already owns it */ 261 /* 262 * These packages are to be filled by the control thread. 263 * They are filed with the arguments of commands specified 264 * for the worker threads. 265 * 266 * The thread of i-th index takes the arguments from the 267 * i-th elements of Packages. 268 * 269 * These are read-only for worker threads. 270 * 271 * For Acquire/Release: 272 * 273 * p200 - starting level of mutex 274 * p201 - number of Levels of mutexes 275 * p202 - starting index of mutex (on the specified level) 276 * p203 - number of mutexes of the same level 277 * p204 - exceptional conditions 278 * p205 - opcode of TimeOutValue (see comment to ma00) 279 */ 280 Name (P200, Package (0x01) 281 { 282 0x00 283 }) 284 Name (P201, Package (0x01) 285 { 286 0x00 287 }) 288 Name (P202, Package (0x01) 289 { 290 0x00 291 }) 292 Name (P203, Package (0x01) 293 { 294 0x00 295 }) 296 Name (P204, Package (0x01) 297 { 298 0x00 299 }) 300 Name (P205, Package (0x01) 301 { 302 0x00 303 }) 304 /* Exceptions total number */ 305 306 Name (EX10, 0x00) 307 /* 308 * p30X - Current state 309 */ 310 Name (P300, Package (0x01) 311 { 312 0x00 313 }) /* scale of errors */ 314 Name (P301, Package (0x01) 315 { 316 0x00 317 }) /* scale of warnings */ 318 /* 319 * Non-zero means to check absence of exception 320 * before and after each operation additionally 321 * to the checking (if any) specified per-operation. 322 */ 323 Name (FLG0, 0x00) 324 /* 325 * Handle exceptions 326 * 327 * Exceptional condition flag: 328 * 329 * EX0D - FAIL expected 330 * EX0E - check for "no exception" 331 * otherwise - opcode of exception expected 332 */ 333 /* 334 * The _TCI-based Initialization of multithreading interconnection 335 * (run command TCI_CMD_GET_ID_OF_THREADS to determine indexes of threads). 336 * 337 * Note: now when arguments (arg0, arg1, arg2) are determined 338 * by Threads command of AcpiExec and passed to test, it 339 * is unnecessary to do "The _TCI-based Initialization of 340 * multithreading interconnection" below. Used temporary. 341 */ 342 Name (FLG1, 0x00) 343 /* 344 * Variables used by particular tests 345 * 346 * FLG2, 347 * FLG3 348 * 1) To show that Serialized method is grabbed exclusively 349 * 2) To show that non-Serialized method is grabbed by two threads simultaneously 350 */ 351 Name (FLG2, 0x00) 352 Name (FLG3, 0x00) 353 /* 354 * The Control Thread manages and controls the specified testing strategy 355 * to be fulfilled by the Worker Threads. 356 * 357 * arg0 - number of threads 358 * arg1 - ID of current thread (0, can be used for control only) 359 * arg2 - Index of current thread 360 * arg3 - cammand - index of the test strategy to be 361 * managed and controlled by the Control Thread 362 * and fulfilled by the Worker Threads (Workers). 363 * 364 * Arguments of the command arg3: 365 * 366 * arg4 367 * arg5 368 * arg6 369 */ 370 Method (M100, 7, Serialized) 371 { 372 /* Prohibits activity of all the worker threads */ 373 374 Switch (Arg3) 375 { 376 Case (0x01) 377 { 378 /* CM01: All workers to exit the infinite loop */ 379 380 M10C (Arg0) 381 } 382 Case (0x02) 383 { 384 /* CM02: All workers to sleep for the specified period */ 385 386 M10D (Arg0) 387 } 388 389 } 390 } 391 392 /* 393 * Open testing - init interaction data 394 * 395 * arg0 - number of threads 396 */ 397 Method (M102, 1, Serialized) 398 { 399 Name (B000, Buffer (Arg0){}) 400 Name (P000, Package (Arg0){}) 401 Name (LPN0, 0x00) 402 Name (LPC0, 0x00) 403 DO00 = 0x00 404 CopyObject (B000, BS00) /* \BS00 */ 405 CopyObject (B000, BS01) /* \BS01 */ 406 CopyObject (B000, BS02) /* \BS02 */ 407 CopyObject (B000, BS03) /* \BS03 */ 408 CopyObject (P000, P200) /* \P200 */ 409 CopyObject (P000, P201) /* \P201 */ 410 CopyObject (P000, P202) /* \P202 */ 411 CopyObject (P000, P203) /* \P203 */ 412 CopyObject (P000, P204) /* \P204 */ 413 CopyObject (P000, P205) /* \P205 */ 414 CopyObject (P000, P300) /* \P300 */ 415 CopyObject (P000, P301) /* \P301 */ 416 LPN0 = Arg0 417 LPC0 = 0x00 418 While (LPN0) 419 { 420 P300 [LPC0] = 0x00 421 P301 [LPC0] = 0x00 422 LPN0-- 423 LPC0++ 424 } 425 426 /* 427 * Initialization to be done once 428 */ 429 If (!GLDI) 430 { 431 /* Statistics */ 432 433 CopyObject (P000, P100) /* \P100 */ 434 CopyObject (P000, P101) /* \P101 */ 435 CopyObject (P000, P102) /* \P102 */ 436 CopyObject (P000, P103) /* \P103 */ 437 CopyObject (P000, P104) /* \P104 */ 438 CopyObject (P000, P105) /* \P105 */ 439 CopyObject (P000, P106) /* \P106 */ 440 CopyObject (B000, BS04) /* \BS04 */ 441 LPN0 = Arg0 442 LPC0 = 0x00 443 While (LPN0) 444 { 445 P100 [LPC0] = 0x00 446 P101 [LPC0] = 0x00 447 P102 [LPC0] = 0x00 448 P103 [LPC0] = 0x00 449 P104 [LPC0] = 0x00 450 P105 [LPC0] = 0x00 451 P106 [LPC0] = 0x00 452 LPN0-- 453 LPC0++ 454 } 455 } 456 457 /* Init fl01 */ 458 459 M339 () 460 /* 461 * Reset all counters (cnt0) and flags (fl00) 462 * corresponding to all Mutexes. 463 */ 464 M330 () 465 /* Report that the Control thread is ready */ 466 467 CTL0 = 0x01 468 GLDI = 0x01 469 } 470 471 /* 472 * Control thread waits for all the worker threads to 473 * fulfill the specified for them buffer of commands. 474 * 475 * arg0 - number of threads 476 */ 477 Method (M103, 1, Serialized) 478 { 479 /* Wait for all Worker threads and check their statuses */ 480 481 Name (B000, Buffer (Arg0){}) 482 Name (B001, Buffer (Arg0){}) 483 Name (B002, Buffer (Arg0){}) 484 CopyObject (BS00, B000) /* \M103.B000 */ 485 M110 (Arg0, B000, B001, B002) 486 } 487 488 /* 489 * The _TCI-based initialization of multithreading interconnection 490 * 491 * In result each thread knows its ID and calculated its index 492 * between all threads participating in the test. 493 * 494 * arg0 - number of threads 495 * 496 * Return: 497 * success - II-Package 498 * otherwise - 0 499 */ 500 Method (M104, 1, NotSerialized) 501 { 502 /* 503 * Local0 - array of thread IDs 504 * Local1 - auxiliary 505 * Local2 - auxiliary 506 * Local7 - II-Package 507 */ 508 If (VB00) 509 { 510 Debug = "Checking for the Test Command Interface with the ACPICA (_TCI) support" 511 } 512 513 If (!M3A5 ()) 514 { 515 Debug = "The Test Command Interface with the ACPICA (_TCI) is not supported" 516 Return (0x00) 517 } 518 519 If (VB00) 520 { 521 Debug = "Getting array of thread IDs" 522 } 523 524 Local0 = M163 (Arg0) 525 Local1 = ObjectType (Local0) 526 If ((Local1 != C00C)) 527 { 528 Debug = "Failed to get array of thread indexes" 529 Return (0x00) 530 } 531 532 If (VB00) 533 { 534 Debug = "Calculating index of thread" 535 } 536 537 Local7 = M105 (Local0, Arg0) 538 Local2 = ObjectType (Local7) 539 If ((Local2 != C00C)) 540 { 541 Debug = "Invalid contents of Package of threads" 542 Return (0x00) 543 } 544 545 Return (Local7) 546 } 547 548 /* 549 * Calculate and return II-Package with Index of current thread between 550 * all threads participating in the test and ID of that thread. 551 * 552 * arg0 - the Package of thread IDs returned by m163 which 553 * executes the command TCI_CMD_GET_ID_OF_THREADS. 554 * arg1 - number of threads 555 * 556 * Return: 557 * II-Package in success: 558 * 0-th element - ID of that current thread 559 * 1-th element - Index of current thread between all threads participating in test 560 * Integer otherwise: 561 * 0 562 */ 563 Method (M105, 2, NotSerialized) 564 { 565 /* 566 * Local0 - auxiliary 567 * Local1 - auxiliary 568 * Local2 - lpN0 569 * Local3 - lpC0 570 * Local4 - TCI_PACKAGE_THR_NUM 571 * Local5 - TCI_PACKAGE_THR_NUM_REAL 572 * Local6 - TCI_PACKAGE_THR_ID (ID of thread) 573 * Local7 - Index of thread 574 */ 575 Local7 = FF32 /* \FF32 */ 576 /* Store(arg0, Debug) */ 577 578 Local4 = DerefOf (Arg0 [C22C]) /* TCI_PACKAGE_THR_NUM */ 579 If (!Local4) 580 { 581 Debug = "TCI_PACKAGE_THR_NUM is zero" 582 Return (0x00) 583 } 584 585 Local5 = DerefOf (Arg0 [C22D]) /* TCI_PACKAGE_THR_NUM_REAL */ 586 If (!Local5) 587 { 588 Debug = "TCI_PACKAGE_THR_NUM_REAL is zero" 589 Return (0x00) 590 } 591 592 Local6 = DerefOf (Arg0 [C22E]) /* TCI_PACKAGE_THR_ID */ 593 If (!Local6) 594 { 595 Debug = "TCI_PACKAGE_THR_ID is zero" 596 Return (0x00) 597 } 598 599 If ((Local4 != Local5)) 600 { 601 Debug = "TCI_PACKAGE_THR_NUM != TCI_PACKAGE_THR_NUM_REAL" 602 Debug = Local4 603 Debug = Local5 604 Return (0x00) 605 } 606 607 If ((Local4 != Arg1)) 608 { 609 Debug = "TCI_PACKAGE_THR_NUM != Number of threads" 610 Debug = Local4 611 Debug = Arg1 612 Return (0x00) 613 } 614 615 /* Calculate index of thread */ 616 617 Local2 = Arg1 618 Local3 = 0x00 619 Local0 = C22F /* \C22F */ 620 While (Local2) 621 { 622 Local1 = DerefOf (Arg0 [Local0]) 623 If (!Local1) 624 { 625 Debug = "thread ID is zero" 626 Return (0x00) 627 } 628 ElseIf ((Local1 == Local6)) 629 { 630 If ((Local7 != FF32)) 631 { 632 Debug = "thread ID encountered twice" 633 Return (0x00) 634 } 635 636 Local7 = Local3 637 } 638 639 Local0++ 640 Local2-- 641 Local3++ 642 } 643 644 /* Return Package: Index of current thread, ID of current thread */ 645 646 Local0 = Package (0x02){} 647 Local0 [0x00] = Local6 648 Local0 [0x01] = Local7 649 Return (Local0) 650 } 651 652 /* 653 * Report errors detected by the worker threads 654 * 655 * arg0 - name of test 656 * arg1 - number of threads 657 */ 658 Method (M106, 2, Serialized) 659 { 660 Name (LPN0, 0x00) 661 Name (LPC0, 0x00) 662 LPN0 = Arg1 663 LPC0 = 0x00 664 While (LPN0) 665 { 666 Local0 = DerefOf (P300 [LPC0]) 667 If (Local0) 668 { 669 /* 670 * Reports: 671 * lpC0 - Index of thread 672 * Local0 - the scale of its errors 673 */ 674 ERR (Arg0, Z147, __LINE__, 0x00, 0x00, LPC0, Local0) 675 } 676 677 LPN0-- 678 LPC0++ 679 } 680 } 681 682 /* 683 * Initialization of multithreading interconnection 684 * 685 * Note: now when arguments (arg0, arg1, arg2) are determined 686 * by Threads command of AcpiExec and passed to test, it 687 * is unnecessary to do "The _TCI-based Initialization of 688 * multithreading interconnection" below. Used temporary. 689 * 690 * arg0 - number of threads 691 * arg1 - ID of current thread 692 * arg2 - Index of current thread 693 * arg3 - minimal number of threads needed for test 694 */ 695 Method (M107, 4, NotSerialized) 696 { 697 /* Set the multi-threading mode flag */ 698 699 SET3 (0x01) 700 /* 701 * Local0 - auxiliary 702 * Local1 - auxiliary 703 * Local6 - ID of thread 704 * Local7 - Index of thread 705 */ 706 /* The _TCI-based Initialization of multithreading interconnection */ 707 If (FLG1) 708 { 709 Local0 = M104 (Arg0) 710 Local1 = ObjectType (Local0) 711 If ((Local1 != C00C)) 712 { 713 ERR ("m107", Z147, __LINE__, 0x00, 0x00, Local1, C00C) 714 Return (0x00) 715 } 716 717 /* Get ID and Index of current thread */ 718 719 Local6 = DerefOf (Local0 [0x00]) 720 Local7 = DerefOf (Local0 [0x01]) 721 If ((Local6 != Arg1)) 722 { 723 ERR ("m107", Z147, __LINE__, 0x00, 0x00, Local6, Arg1) 724 Return (0x00) 725 } 726 727 If ((Local7 != Arg2)) 728 { 729 ERR ("m107", Z147, __LINE__, 0x00, 0x00, Local7, Arg2) 730 Return (0x00) 731 } 732 } 733 734 If (((Arg0 < 0x02) || (Arg0 < Arg3))) 735 { 736 Debug = "Insufficient number of threads for Test!" 737 Return (0x00) 738 } 739 740 Return (0x01) 741 } 742 743 /* 744 * Close testing 745 * 746 * arg0 - name of test 747 * arg1 - number of threads 748 * arg2 - ID of current thread 749 * arg3 - Index of current thread 750 */ 751 Method (M108, 4, NotSerialized) 752 { 753 /* all workers to exit the infinite loop */ 754 755 M100 (Arg1, Arg2, Arg3, CM01, 0x00, 0x00, 0x00) 756 /* Report errors detected by the worker threads */ 757 758 M106 (Arg0, Arg1) 759 } 760 761 /* 762 * CM01: all workers to exit the infinite loop 763 * 764 * arg0 - number of threads 765 */ 766 Method (M10C, 1, Serialized) 767 { 768 /* All workers to exit the infinite loop */ 769 770 M200 (BS00, Arg0, C101) /* cmd: Exit the infinite loop */ 771 M114 (Arg0) 772 /* Wait for all Worker threads */ 773 774 Name (B000, Buffer (Arg0){}) 775 Name (B001, Buffer (Arg0){}) 776 Name (B002, Buffer (Arg0){}) 777 CopyObject (BS00, B000) /* \M10C.B000 */ 778 M110 (Arg0, B000, B001, B002) 779 } 780 781 /* 782 * CM02: all workers to sleep for the specified period 783 * 784 * arg0 - number of threads 785 */ 786 Method (M10D, 1, NotSerialized) 787 { 788 /* All workers to sleep for the specified period */ 789 790 M200 (BS00, Arg0, C102) /* cmd: Sleep for the specified number of Milliseconds */ 791 M114 (Arg0) 792 /* Wait for all Worker threads */ 793 794 M103 (Arg0) 795 } 796 797 /* 798 * Control thread checks that the specified set of worker threads 799 * hang on the specified operations or completed the operations. 800 * 801 * arg0 - number of threads 802 * arg1 - buffer of arg0 length 803 * 1 - check completion of operation 804 * 2 - check hang 805 * 806 * Return: 807 * These mean unexpected behaviour: 808 * 0x01 - some threads has not completed operation 809 * 0x02 - some threads are not hang on operation 810 * These report the contents of buffer: 811 * 0x10 - has checkings of completed operation 812 * 0x20 - has checkings of hang on operation 813 */ 814 Method (M10E, 2, Serialized) 815 { 816 Name (LPN0, 0x00) 817 Name (LPC0, 0x00) 818 Name (RVAL, 0x00) 819 LPN0 = Arg0 820 LPC0 = 0x00 821 While (LPN0) 822 { 823 /* For not a Control thread only */ 824 825 If ((LPC0 != 0x00)) 826 { 827 Local0 = DerefOf (Arg1 [LPC0]) 828 Local1 = DerefOf (BS01 [LPC0]) 829 If ((Local0 == 0x01)) 830 { 831 /* check completion of operation */ 832 833 RVAL |= 0x10 834 If (!Local1) 835 { 836 RVAL |= 0x01 837 } 838 } 839 ElseIf ((Local0 == 0x02)) 840 { 841 /* check hang */ 842 843 RVAL |= 0x20 844 If (Local1) 845 { 846 RVAL |= 0x02 847 } 848 } 849 } 850 851 LPN0-- 852 LPC0++ 853 } 854 855 Return (RVAL) /* \M10E.RVAL */ 856 } 857 858 /* 859 * Run and analyze result of m10e() 860 * 861 * arg0, 862 * arg1 - see m10e 863 */ 864 Method (M10F, 2, Serialized) 865 { 866 Name (LPN0, 0x00) 867 Name (LPC0, 0x00) 868 Name (RVAL, 0x00) 869 LPN0 = SL03 /* \SL03 */ 870 LPC0 = 0x00 871 While (LPN0) 872 { 873 Sleep (SL02) 874 RVAL = M10E (Arg0, Arg1) 875 If (!(RVAL & 0x20)) 876 { 877 /* doesn't have checkings of hang */ 878 879 If (!(RVAL & 0x01)) 880 { 881 /* all examined have completed */ 882 883 Break 884 } 885 } 886 887 LPN0-- 888 LPC0++ 889 } 890 891 Return (RVAL) /* \M10F.RVAL */ 892 } 893 894 /* 895 * Control thread waits for all the worker threads to 896 * fulfill the specified for them buffer of commands. 897 * 898 * arg0 - number of threads (total) 899 * arg1 - the per-thread expectations of completion status mapping buffer 900 * arg2 - the per-thread expectations of hang status mapping buffer 901 * arg3 - the per-thread expectations of idle status mapping buffer 902 */ 903 Method (M110, 4, Serialized) 904 { 905 Name (LPN0, 0x00) 906 Name (LPC0, 0x00) 907 Name (FIND, 0x00) 908 Name (SL80, 0x00) 909 Name (SL81, 0x00) 910 Name (CMD0, 0x00) 911 Name (HNG0, 0x00) 912 Name (IDL0, 0x00) 913 Name (QUIT, 0x00) 914 /* 915 * Check that all the worker threads saw my 916 * non-zero do00 and fulfilled the proper command. 917 */ 918 While (0x01) 919 { 920 FIND = 0x00 921 LPN0 = Arg0 922 LPC0 = 0x00 923 While (LPN0) 924 { 925 /* For not a Control thread only */ 926 927 If ((LPC0 != 0x00)) 928 { 929 CMD0 = DerefOf (Arg1 [LPC0]) 930 HNG0 = DerefOf (Arg2 [LPC0]) 931 IDL0 = DerefOf (Arg3 [LPC0]) 932 Local0 = DerefOf (BS00 [LPC0]) 933 Local1 = DerefOf (BS01 [LPC0]) 934 Local2 = DerefOf (BS03 [LPC0]) 935 Local3 = DerefOf (BS04 [LPC0]) /* terminated threads */ 936 If (Local3){ /* Thread already completed by c108 */ 937 } 938 ElseIf (CMD0) 939 { 940 If ((Local0 != CMD0)) 941 { 942 ERR ("m110", Z147, __LINE__, 0x00, 0x00, Local0, CMD0) 943 Debug = LPC0 /* \M110.LPC0 */ 944 } 945 946 If (!Local1) 947 { 948 /* Not completed yet */ 949 950 FIND = 0x01 951 Break 952 } 953 ElseIf ((Local1 != Local0)) 954 { 955 /* Has executed unexpected command */ 956 957 ERR ("m110", Z147, __LINE__, 0x00, 0x00, Local1, Local0) 958 Debug = LPC0 /* \M110.LPC0 */ 959 } 960 } 961 ElseIf (HNG0) 962 { 963 SL81 = 0x01 964 If ((SL80 < SL03)) 965 { 966 /* 967 * Delay here is some pure attempt to be objective - 968 * it can look like hang now but go just after this 969 * checking. 970 */ 971 SL80++ 972 Sleep (SL02) 973 } 974 975 Local4 = DerefOf (BS01 [LPC0]) 976 If (Local4) 977 { 978 /* Doesn't hang */ 979 980 If ((Local4 != Local0)) 981 { 982 /* Has executed unexpected command */ 983 984 ERR ("m110", Z147, __LINE__, 0x00, 0x00, Local1, Local0) 985 Debug = LPC0 /* \M110.LPC0 */ 986 } 987 988 ERR ("m110", Z147, __LINE__, 0x00, 0x00, Local0, Local4) 989 Debug = LPC0 /* \M110.LPC0 */ 990 } 991 } 992 ElseIf (IDL0) 993 { 994 If ((Local0 != C100)) 995 { 996 ERR ("m110", Z147, __LINE__, 0x00, 0x00, Local0, CMD0) 997 Debug = LPC0 /* \M110.LPC0 */ 998 } 999 1000 If (!Local2) 1001 { 1002 /* Not completed yet */ 1003 1004 FIND = 0x01 1005 Break 1006 } 1007 ElseIf ((Local2 != C100)) 1008 { 1009 /* Has executed unexpected command */ 1010 1011 ERR ("m110", Z147, __LINE__, 0x00, 0x00, Local0, CMD0) 1012 Debug = LPC0 /* \M110.LPC0 */ 1013 } 1014 } 1015 Else 1016 { 1017 ERR ("m110", Z147, __LINE__, 0x00, 0x00, LPC0, Local0) 1018 Debug = LPC0 /* \M110.LPC0 */ 1019 } 1020 } 1021 1022 LPN0-- 1023 LPC0++ 1024 } 1025 1026 QUIT = 0x00 1027 If (!FIND) 1028 { 1029 QUIT = 0x01 1030 /* 1031 * All threads except those being checked for hang status 1032 * have completed their commands. 1033 */ 1034 If (SL81) 1035 { 1036 /* Has threads to check hang status */ 1037 1038 If ((SL80 < SL03)) 1039 { 1040 /* Not completed yet the specified delay */ 1041 1042 QUIT = 0x00 1043 } 1044 } 1045 } 1046 1047 If (QUIT) 1048 { 1049 Break 1050 } 1051 1052 /* 1053 * Don't report about Control thread sleeping - 1054 * don't use m206(0, sl00). 1055 */ 1056 Sleep (SL00) 1057 } 1058 1059 /* 1060 * Set do00 to zero and check that all the worker threads 1061 * saw my zero do00 (if only it is not the EXIT command). 1062 */ 1063 M200 (BS02, Arg0, 0x00) 1064 DO00 = 0x00 1065 While (0x01) 1066 { 1067 FIND = 0x00 1068 LPN0 = Arg0 1069 LPC0 = 0x00 1070 While (LPN0) 1071 { 1072 /* For not a Control thread only */ 1073 1074 If ((LPC0 != 0x00)) 1075 { 1076 /* 1077 * Reset the specified command for each thread 1078 * which in fact doesn't hang. 1079 */ 1080 Local0 = DerefOf (BS02 [LPC0]) 1081 If (Local0) 1082 { 1083 /* Alive, doesn't hang, so reset its command */ 1084 1085 BS00 [LPC0] = C100 /* \C100 */ 1086 BS01 [LPC0] = 0x00 1087 } 1088 1089 /* 1090 * For all threads except those being checked for 1091 * hang status and completed already. 1092 */ 1093 HNG0 = DerefOf (Arg2 [LPC0]) 1094 Local0 = DerefOf (BS04 [LPC0]) 1095 If ((!HNG0 && !Local0)) 1096 { 1097 Local0 = DerefOf (BS02 [LPC0]) 1098 If (!Local0) 1099 { 1100 FIND = 0x01 1101 Break 1102 } 1103 } 1104 } 1105 1106 LPN0-- 1107 LPC0++ 1108 } 1109 1110 /* 1111 * All threads except those being checked for hang status 1112 * have zeroed do00. 1113 */ 1114 If (!FIND) 1115 { 1116 Break 1117 } 1118 1119 /* 1120 * Don't report about Control thread sleeping - 1121 * don't use m206(0, sl00). 1122 */ 1123 Sleep (SL00) 1124 } 1125 /* All the worker threads are ready for any next command */ 1126 } 1127 1128 /* 1129 * Check absence of exception 1130 * 1131 * arg0 - ID of current thread 1132 * arg1 - Index of current thread 1133 * arg2 - exceptional condition flag 1134 * arg3 - the name of operation 1135 * 1136 * Return opcode of exception to be generated or zero 1137 */ 1138 Method (M111, 4, Serialized) 1139 { 1140 If ((FLG0 || Arg2)) 1141 { 1142 Local0 = CH08 ("m111", Arg0, Z147, 0x0C, 0x00, 0x00) 1143 If (Local0) 1144 { 1145 SE00 (Arg1, ER03, "Error er03") 1146 } 1147 } 1148 1149 /* Analyze opcode of exception to be generated */ 1150 1151 Switch (Arg2) 1152 { 1153 Case (0x00) 1154 { 1155 Local0 = 0x00 1156 } 1157 Case (0xFE) 1158 { 1159 /* EX0E - check "no exception" */ 1160 1161 Local0 = 0x00 1162 } 1163 Case (0xFD) 1164 { 1165 /* EX0D - FAIL expected */ 1166 1167 Local0 = Arg2 1168 Concatenate (Arg3, ", generating FAIL condition ", Local1) 1169 M201 (Arg1, VB03, Local1) 1170 } 1171 Default 1172 { 1173 Local0 = Arg2 1174 Concatenate (Arg3, ", generating exceptional condition ", Local1) 1175 Concatenate (Local1, Local0, Local1) 1176 M201 (Arg1, VB03, Local1) 1177 } 1178 1179 } 1180 1181 Return (Local0) 1182 } 1183 1184 /* 1185 * Check exception 1186 * 1187 * arg0 - ID of current thread 1188 * arg1 - Index of current thread 1189 * arg2 - exceptional condition flag 1190 * arg3 - return code of operation 1191 */ 1192 Method (M112, 4, NotSerialized) 1193 { 1194 Local2 = 0x00 1195 If ((Arg2 == EX0E)) 1196 { 1197 /* check "no exception" */ 1198 1199 Local0 = CH08 ("m112", Arg0, Z147, 0x0D, 0x00, 0x00) 1200 If (Local0) 1201 { 1202 SE00 (Arg1, ER03, "Error er03") 1203 } 1204 } 1205 ElseIf ((Arg2 == EX0D)) 1206 { 1207 /* FAIL of operation expected */ 1208 1209 If (!Arg3) 1210 { 1211 ERR ("m112", Z147, __LINE__, 0x00, 0x00, Arg3, 0x01) 1212 } 1213 } 1214 ElseIf (Arg2) 1215 { 1216 /* check presence of particular exception */ 1217 1218 Local0 = CH09 (0x00, Arg0, Arg2, Z147, 0x0F, RefOf (Local2)) 1219 If (Local0) 1220 { 1221 SE00 (Arg1, ER04, "Error er04") 1222 } 1223 } 1224 1225 If (FLG0) 1226 { 1227 Local0 = CH08 ("m112", Arg0, Z147, 0x10, 0x00, 0x00) 1228 If (Local0) 1229 { 1230 SE00 (Arg1, ER03, "Error er03") 1231 } 1232 } 1233 } 1234 1235 /* 1236 * Control thread initiates execution of commands by the worker threads 1237 * 1238 * arg0 - number of threads (total) 1239 */ 1240 Method (M114, 1, NotSerialized) 1241 { 1242 M200 (BS01, Arg0, 0x00) 1243 M200 (BS03, Arg0, 0x00) 1244 DO00 = 0x01 1245 } 1246 1247 /* 1248 * Return index of the greatest alive non-terminated yet thread 1249 * 1250 * arg0 - number of threads 1251 */ 1252 Method (M115, 1, Serialized) 1253 { 1254 Name (LPN0, 0x00) 1255 Name (LPC0, 0x00) 1256 /* Means 'not found' */ 1257 1258 Local7 = Arg0 1259 /* Inverse order, excluding a Control thread */ 1260 1261 LPN0 = (Arg0 - 0x01) 1262 LPC0 = (Arg0 - 0x01) 1263 While (LPN0) 1264 { 1265 Local0 = DerefOf (BS04 [LPC0]) 1266 If (!Local0) 1267 { 1268 Local7 = LPC0 /* \M115.LPC0 */ 1269 Break 1270 } 1271 1272 LPN0-- 1273 LPC0-- 1274 } 1275 1276 Return (Local7) 1277 } 1278 1279 /* 1280 * Add error-bit relative to arg0-th thread 1281 * 1282 * arg0 - Index of thread 1283 * arg1 - error-bit 1284 * arg2 - message 1285 */ 1286 Method (SE00, 3, NotSerialized) 1287 { 1288 Local0 = DerefOf (P300 [Arg0]) 1289 Local1 = (Arg1 | Local0) 1290 P300 [Arg0] = Local1 1291 If (VB04) 1292 { 1293 /* Add scale of Errors */ 1294 1295 Local0 = DerefOf (P100 [Arg0]) 1296 Local1 = (Arg1 | Local0) 1297 P100 [Arg0] = Local1 1298 /* Increment statistics of Errors (number) */ 1299 1300 M212 (RefOf (P101), Arg0) 1301 } 1302 1303 If (VB06) 1304 { 1305 Concatenate ("ERROR: ", Arg2, Local0) 1306 M201 (Arg0, 0x01, Local0) 1307 } 1308 } 1309 1310 /* 1311 * Add warning-bit relative to arg0-th thread 1312 * 1313 * arg0 - Index of thread 1314 * arg1 - warning-bit 1315 * arg2 - message 1316 */ 1317 Method (WRN0, 3, NotSerialized) 1318 { 1319 Local0 = DerefOf (P301 [Arg0]) 1320 Local1 = (Arg1 | Local0) 1321 P301 [Arg0] = Local1 1322 If (VB04) 1323 { 1324 /* Add scale of Warnings */ 1325 1326 Local0 = DerefOf (P102 [Arg0]) 1327 Local1 = (Arg1 | Local0) 1328 P102 [Arg0] = Local1 1329 /* Increment statistics of Warnings (number) */ 1330 1331 M212 (RefOf (P103), Arg0) 1332 } 1333 1334 If (VB05) 1335 { 1336 Concatenate ("WARNING: ", Arg2, Local0) 1337 M201 (Arg0, 0x01, Local0) 1338 } 1339 } 1340