dbexec.c revision 199337
1/******************************************************************************* 2 * 3 * Module Name: dbexec - debugger control method execution 4 * 5 ******************************************************************************/ 6 7/****************************************************************************** 8 * 9 * 1. Copyright Notice 10 * 11 * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp. 12 * All rights reserved. 13 * 14 * 2. License 15 * 16 * 2.1. This is your license from Intel Corp. under its intellectual property 17 * rights. You may have additional license terms from the party that provided 18 * you this software, covering your right to use that party's intellectual 19 * property rights. 20 * 21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 22 * copy of the source code appearing in this file ("Covered Code") an 23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 24 * base code distributed originally by Intel ("Original Intel Code") to copy, 25 * make derivatives, distribute, use and display any portion of the Covered 26 * Code in any form, with the right to sublicense such rights; and 27 * 28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 29 * license (with the right to sublicense), under only those claims of Intel 30 * patents that are infringed by the Original Intel Code, to make, use, sell, 31 * offer to sell, and import the Covered Code and derivative works thereof 32 * solely to the minimum extent necessary to exercise the above copyright 33 * license, and in no event shall the patent license extend to any additions 34 * to or modifications of the Original Intel Code. No other license or right 35 * is granted directly or by implication, estoppel or otherwise; 36 * 37 * The above copyright and patent license is granted only if the following 38 * conditions are met: 39 * 40 * 3. Conditions 41 * 42 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 43 * Redistribution of source code of any substantial portion of the Covered 44 * Code or modification with rights to further distribute source must include 45 * the above Copyright Notice, the above License, this list of Conditions, 46 * and the following Disclaimer and Export Compliance provision. In addition, 47 * Licensee must cause all Covered Code to which Licensee contributes to 48 * contain a file documenting the changes Licensee made to create that Covered 49 * Code and the date of any change. Licensee must include in that file the 50 * documentation of any changes made by any predecessor Licensee. Licensee 51 * must include a prominent statement that the modification is derived, 52 * directly or indirectly, from Original Intel Code. 53 * 54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 55 * Redistribution of source code of any substantial portion of the Covered 56 * Code or modification without rights to further distribute source must 57 * include the following Disclaimer and Export Compliance provision in the 58 * documentation and/or other materials provided with distribution. In 59 * addition, Licensee may not authorize further sublicense of source of any 60 * portion of the Covered Code, and must include terms to the effect that the 61 * license from Licensee to its licensee is limited to the intellectual 62 * property embodied in the software Licensee provides to its licensee, and 63 * not to intellectual property embodied in modifications its licensee may 64 * make. 65 * 66 * 3.3. Redistribution of Executable. Redistribution in executable form of any 67 * substantial portion of the Covered Code or modification must reproduce the 68 * above Copyright Notice, and the following Disclaimer and Export Compliance 69 * provision in the documentation and/or other materials provided with the 70 * distribution. 71 * 72 * 3.4. Intel retains all right, title, and interest in and to the Original 73 * Intel Code. 74 * 75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 76 * Intel shall be used in advertising or otherwise to promote the sale, use or 77 * other dealings in products derived from or relating to the Covered Code 78 * without prior written authorization from Intel. 79 * 80 * 4. Disclaimer and Export Compliance 81 * 82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 88 * PARTICULAR PURPOSE. 89 * 90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 97 * LIMITED REMEDY. 98 * 99 * 4.3. Licensee shall not export, either directly or indirectly, any of this 100 * software or system incorporating such software without first obtaining any 101 * required license or other approval from the U. S. Department of Commerce or 102 * any other agency or department of the United States Government. In the 103 * event Licensee exports any such software from the United States or 104 * re-exports any such software from a foreign destination, Licensee shall 105 * ensure that the distribution and export/re-export of the software is in 106 * compliance with all laws, regulations, orders, or other restrictions of the 107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 108 * any of its subsidiaries will export/re-export any technical data, process, 109 * software, or service, directly or indirectly, to any country for which the 110 * United States government or any agency thereof requires an export license, 111 * other governmental approval, or letter of assurance, without first obtaining 112 * such license, approval or letter. 113 * 114 *****************************************************************************/ 115 116 117#include <contrib/dev/acpica/include/acpi.h> 118#include <contrib/dev/acpica/include/accommon.h> 119#include <contrib/dev/acpica/include/acdebug.h> 120#include <contrib/dev/acpica/include/acnamesp.h> 121 122#ifdef ACPI_DEBUGGER 123 124#define _COMPONENT ACPI_CA_DEBUGGER 125 ACPI_MODULE_NAME ("dbexec") 126 127 128static ACPI_DB_METHOD_INFO AcpiGbl_DbMethodInfo; 129 130/* Local prototypes */ 131 132static ACPI_STATUS 133AcpiDbExecuteMethod ( 134 ACPI_DB_METHOD_INFO *Info, 135 ACPI_BUFFER *ReturnObj); 136 137static void 138AcpiDbExecuteSetup ( 139 ACPI_DB_METHOD_INFO *Info); 140 141static UINT32 142AcpiDbGetOutstandingAllocations ( 143 void); 144 145static void ACPI_SYSTEM_XFACE 146AcpiDbMethodThread ( 147 void *Context); 148 149static ACPI_STATUS 150AcpiDbExecutionWalk ( 151 ACPI_HANDLE ObjHandle, 152 UINT32 NestingLevel, 153 void *Context, 154 void **ReturnValue); 155 156 157/******************************************************************************* 158 * 159 * FUNCTION: AcpiDbExecuteMethod 160 * 161 * PARAMETERS: Info - Valid info segment 162 * ReturnObj - Where to put return object 163 * 164 * RETURN: Status 165 * 166 * DESCRIPTION: Execute a control method. 167 * 168 ******************************************************************************/ 169 170static ACPI_STATUS 171AcpiDbExecuteMethod ( 172 ACPI_DB_METHOD_INFO *Info, 173 ACPI_BUFFER *ReturnObj) 174{ 175 ACPI_STATUS Status; 176 ACPI_OBJECT_LIST ParamObjects; 177 ACPI_OBJECT Params[ACPI_METHOD_NUM_ARGS]; 178 ACPI_HANDLE Handle; 179 UINT32 i; 180 ACPI_DEVICE_INFO *ObjInfo; 181 182 183 if (AcpiGbl_DbOutputToFile && !AcpiDbgLevel) 184 { 185 AcpiOsPrintf ("Warning: debug output is not enabled!\n"); 186 } 187 188 /* Get the NS node, determines existence also */ 189 190 Status = AcpiGetHandle (NULL, Info->Pathname, &Handle); 191 if (ACPI_FAILURE (Status)) 192 { 193 return (Status); 194 } 195 196 /* Get the object info for number of method parameters */ 197 198 Status = AcpiGetObjectInfo (Handle, &ObjInfo); 199 if (ACPI_FAILURE (Status)) 200 { 201 return (Status); 202 } 203 204 ParamObjects.Pointer = NULL; 205 ParamObjects.Count = 0; 206 207 if (ObjInfo->Type == ACPI_TYPE_METHOD) 208 { 209 /* Are there arguments to the method? */ 210 211 if (Info->Args && Info->Args[0]) 212 { 213 for (i = 0; Info->Args[i] && i < ACPI_METHOD_NUM_ARGS; i++) 214 { 215 Params[i].Type = ACPI_TYPE_INTEGER; 216 Params[i].Integer.Value = ACPI_STRTOUL (Info->Args[i], NULL, 16); 217 } 218 219 ParamObjects.Pointer = Params; 220 ParamObjects.Count = i; 221 } 222 else 223 { 224 /* Setup default parameters */ 225 226 for (i = 0; i < ObjInfo->ParamCount; i++) 227 { 228 switch (i) 229 { 230 case 0: 231 232 Params[0].Type = ACPI_TYPE_INTEGER; 233 Params[0].Integer.Value = 0x01020304; 234 break; 235 236 case 1: 237 238 Params[1].Type = ACPI_TYPE_STRING; 239 Params[1].String.Length = 12; 240 Params[1].String.Pointer = "AML Debugger"; 241 break; 242 243 default: 244 245 Params[i].Type = ACPI_TYPE_INTEGER; 246 Params[i].Integer.Value = i * (ACPI_INTEGER) 0x1000; 247 break; 248 } 249 } 250 251 ParamObjects.Pointer = Params; 252 ParamObjects.Count = ObjInfo->ParamCount; 253 } 254 } 255 256 ACPI_FREE (ObjInfo); 257 258 /* Prepare for a return object of arbitrary size */ 259 260 ReturnObj->Pointer = AcpiGbl_DbBuffer; 261 ReturnObj->Length = ACPI_DEBUG_BUFFER_SIZE; 262 263 /* Do the actual method execution */ 264 265 AcpiGbl_MethodExecuting = TRUE; 266 Status = AcpiEvaluateObject (NULL, 267 Info->Pathname, &ParamObjects, ReturnObj); 268 269 AcpiGbl_CmSingleStep = FALSE; 270 AcpiGbl_MethodExecuting = FALSE; 271 272 return (Status); 273} 274 275 276/******************************************************************************* 277 * 278 * FUNCTION: AcpiDbExecuteSetup 279 * 280 * PARAMETERS: Info - Valid method info 281 * 282 * RETURN: None 283 * 284 * DESCRIPTION: Setup info segment prior to method execution 285 * 286 ******************************************************************************/ 287 288static void 289AcpiDbExecuteSetup ( 290 ACPI_DB_METHOD_INFO *Info) 291{ 292 293 /* Catenate the current scope to the supplied name */ 294 295 Info->Pathname[0] = 0; 296 if ((Info->Name[0] != '\\') && 297 (Info->Name[0] != '/')) 298 { 299 ACPI_STRCAT (Info->Pathname, AcpiGbl_DbScopeBuf); 300 } 301 302 ACPI_STRCAT (Info->Pathname, Info->Name); 303 AcpiDbPrepNamestring (Info->Pathname); 304 305 AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 306 AcpiOsPrintf ("Executing %s\n", Info->Pathname); 307 308 if (Info->Flags & EX_SINGLE_STEP) 309 { 310 AcpiGbl_CmSingleStep = TRUE; 311 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 312 } 313 314 else 315 { 316 /* No single step, allow redirection to a file */ 317 318 AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT); 319 } 320} 321 322 323#ifdef ACPI_DBG_TRACK_ALLOCATIONS 324UINT32 325AcpiDbGetCacheInfo ( 326 ACPI_MEMORY_LIST *Cache) 327{ 328 329 return (Cache->TotalAllocated - Cache->TotalFreed - Cache->CurrentDepth); 330} 331#endif 332 333/******************************************************************************* 334 * 335 * FUNCTION: AcpiDbGetOutstandingAllocations 336 * 337 * PARAMETERS: None 338 * 339 * RETURN: Current global allocation count minus cache entries 340 * 341 * DESCRIPTION: Determine the current number of "outstanding" allocations -- 342 * those allocations that have not been freed and also are not 343 * in one of the various object caches. 344 * 345 ******************************************************************************/ 346 347static UINT32 348AcpiDbGetOutstandingAllocations ( 349 void) 350{ 351 UINT32 Outstanding = 0; 352 353#ifdef ACPI_DBG_TRACK_ALLOCATIONS 354 355 Outstanding += AcpiDbGetCacheInfo (AcpiGbl_StateCache); 356 Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeCache); 357 Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeExtCache); 358 Outstanding += AcpiDbGetCacheInfo (AcpiGbl_OperandCache); 359#endif 360 361 return (Outstanding); 362} 363 364 365/******************************************************************************* 366 * 367 * FUNCTION: AcpiDbExecutionWalk 368 * 369 * PARAMETERS: WALK_CALLBACK 370 * 371 * RETURN: Status 372 * 373 * DESCRIPTION: Execute a control method. Name is relative to the current 374 * scope. 375 * 376 ******************************************************************************/ 377 378static ACPI_STATUS 379AcpiDbExecutionWalk ( 380 ACPI_HANDLE ObjHandle, 381 UINT32 NestingLevel, 382 void *Context, 383 void **ReturnValue) 384{ 385 ACPI_OPERAND_OBJECT *ObjDesc; 386 ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 387 ACPI_BUFFER ReturnObj; 388 ACPI_STATUS Status; 389 390 391 ObjDesc = AcpiNsGetAttachedObject (Node); 392 if (ObjDesc->Method.ParamCount) 393 { 394 return (AE_OK); 395 } 396 397 ReturnObj.Pointer = NULL; 398 ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 399 400 AcpiNsPrintNodePathname (Node, "Execute"); 401 402 /* Do the actual method execution */ 403 404 AcpiOsPrintf ("\n"); 405 AcpiGbl_MethodExecuting = TRUE; 406 407 Status = AcpiEvaluateObject (Node, NULL, NULL, &ReturnObj); 408 409 AcpiOsPrintf ("[%4.4s] returned %s\n", AcpiUtGetNodeName (Node), 410 AcpiFormatException (Status)); 411 AcpiGbl_MethodExecuting = FALSE; 412 413 return (AE_OK); 414} 415 416 417/******************************************************************************* 418 * 419 * FUNCTION: AcpiDbExecute 420 * 421 * PARAMETERS: Name - Name of method to execute 422 * Args - Parameters to the method 423 * Flags - single step/no single step 424 * 425 * RETURN: None 426 * 427 * DESCRIPTION: Execute a control method. Name is relative to the current 428 * scope. 429 * 430 ******************************************************************************/ 431 432void 433AcpiDbExecute ( 434 char *Name, 435 char **Args, 436 UINT32 Flags) 437{ 438 ACPI_STATUS Status; 439 ACPI_BUFFER ReturnObj; 440 char *NameString; 441 442 443#ifdef ACPI_DEBUG_OUTPUT 444 UINT32 PreviousAllocations; 445 UINT32 Allocations; 446 447 448 /* Memory allocation tracking */ 449 450 PreviousAllocations = AcpiDbGetOutstandingAllocations (); 451#endif 452 453 if (*Name == '*') 454 { 455 (void) AcpiWalkNamespace (ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT, 456 ACPI_UINT32_MAX, AcpiDbExecutionWalk, NULL, NULL, NULL); 457 return; 458 } 459 else 460 { 461 NameString = ACPI_ALLOCATE (ACPI_STRLEN (Name) + 1); 462 if (!NameString) 463 { 464 return; 465 } 466 467 ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); 468 469 ACPI_STRCPY (NameString, Name); 470 AcpiUtStrupr (NameString); 471 AcpiGbl_DbMethodInfo.Name = NameString; 472 AcpiGbl_DbMethodInfo.Args = Args; 473 AcpiGbl_DbMethodInfo.Flags = Flags; 474 475 ReturnObj.Pointer = NULL; 476 ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 477 478 AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo); 479 Status = AcpiDbExecuteMethod (&AcpiGbl_DbMethodInfo, &ReturnObj); 480 ACPI_FREE (NameString); 481 } 482 483 /* 484 * Allow any handlers in separate threads to complete. 485 * (Such as Notify handlers invoked from AML executed above). 486 */ 487 AcpiOsSleep ((ACPI_INTEGER) 10); 488 489 490#ifdef ACPI_DEBUG_OUTPUT 491 492 /* Memory allocation tracking */ 493 494 Allocations = AcpiDbGetOutstandingAllocations () - PreviousAllocations; 495 496 AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 497 498 if (Allocations > 0) 499 { 500 AcpiOsPrintf ("Outstanding: 0x%X allocations after execution\n", 501 Allocations); 502 } 503#endif 504 505 if (ACPI_FAILURE (Status)) 506 { 507 AcpiOsPrintf ("Execution of %s failed with status %s\n", 508 AcpiGbl_DbMethodInfo.Pathname, AcpiFormatException (Status)); 509 } 510 else 511 { 512 /* Display a return object, if any */ 513 514 if (ReturnObj.Length) 515 { 516 AcpiOsPrintf ("Execution of %s returned object %p Buflen %X\n", 517 AcpiGbl_DbMethodInfo.Pathname, ReturnObj.Pointer, 518 (UINT32) ReturnObj.Length); 519 AcpiDbDumpExternalObject (ReturnObj.Pointer, 1); 520 } 521 else 522 { 523 AcpiOsPrintf ("No return object from execution of %s\n", 524 AcpiGbl_DbMethodInfo.Pathname); 525 } 526 } 527 528 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 529} 530 531 532/******************************************************************************* 533 * 534 * FUNCTION: AcpiDbMethodThread 535 * 536 * PARAMETERS: Context - Execution info segment 537 * 538 * RETURN: None 539 * 540 * DESCRIPTION: Debugger execute thread. Waits for a command line, then 541 * simply dispatches it. 542 * 543 ******************************************************************************/ 544 545static void ACPI_SYSTEM_XFACE 546AcpiDbMethodThread ( 547 void *Context) 548{ 549 ACPI_STATUS Status; 550 ACPI_DB_METHOD_INFO *Info = Context; 551 ACPI_DB_METHOD_INFO LocalInfo; 552 UINT32 i; 553 UINT8 Allow; 554 ACPI_BUFFER ReturnObj; 555 556 557 /* 558 * AcpiGbl_DbMethodInfo.Arguments will be passed as method arguments. 559 * Prevent AcpiGbl_DbMethodInfo from being modified by multiple threads 560 * concurrently. 561 * 562 * Note: The arguments we are passing are used by the ASL test suite 563 * (aslts). Do not change them without updating the tests. 564 */ 565 (void) AcpiOsWaitSemaphore (Info->InfoGate, 1, ACPI_WAIT_FOREVER); 566 567 if (Info->InitArgs) 568 { 569 AcpiDbUInt32ToHexString (Info->NumCreated, Info->IndexOfThreadStr); 570 AcpiDbUInt32ToHexString (ACPI_TO_INTEGER (AcpiOsGetThreadId ()), 571 Info->IdOfThreadStr); 572 } 573 574 if (Info->Threads && (Info->NumCreated < Info->NumThreads)) 575 { 576 Info->Threads[Info->NumCreated++] = 577 ACPI_TO_INTEGER (AcpiOsGetThreadId()); 578 } 579 580 LocalInfo = *Info; 581 LocalInfo.Args = LocalInfo.Arguments; 582 LocalInfo.Arguments[0] = LocalInfo.NumThreadsStr; 583 LocalInfo.Arguments[1] = LocalInfo.IdOfThreadStr; 584 LocalInfo.Arguments[2] = LocalInfo.IndexOfThreadStr; 585 LocalInfo.Arguments[3] = NULL; 586 587 (void) AcpiOsSignalSemaphore (Info->InfoGate, 1); 588 589 for (i = 0; i < Info->NumLoops; i++) 590 { 591 Status = AcpiDbExecuteMethod (&LocalInfo, &ReturnObj); 592 if (ACPI_FAILURE (Status)) 593 { 594 AcpiOsPrintf ("%s During execution of %s at iteration %X\n", 595 AcpiFormatException (Status), Info->Pathname, i); 596 if (Status == AE_ABORT_METHOD) 597 { 598 break; 599 } 600 } 601 602#if 0 603 if ((i % 100) == 0) 604 { 605 AcpiOsPrintf ("%d executions, Thread 0x%x\n", i, AcpiOsGetThreadId ()); 606 } 607 608 if (ReturnObj.Length) 609 { 610 AcpiOsPrintf ("Execution of %s returned object %p Buflen %X\n", 611 Info->Pathname, ReturnObj.Pointer, (UINT32) ReturnObj.Length); 612 AcpiDbDumpExternalObject (ReturnObj.Pointer, 1); 613 } 614#endif 615 } 616 617 /* Signal our completion */ 618 619 Allow = 0; 620 (void) AcpiOsWaitSemaphore (Info->ThreadCompleteGate, 1, ACPI_WAIT_FOREVER); 621 Info->NumCompleted++; 622 623 if (Info->NumCompleted == Info->NumThreads) 624 { 625 /* Do signal for main thread once only */ 626 Allow = 1; 627 } 628 629 (void) AcpiOsSignalSemaphore (Info->ThreadCompleteGate, 1); 630 631 if (Allow) 632 { 633 Status = AcpiOsSignalSemaphore (Info->MainThreadGate, 1); 634 if (ACPI_FAILURE (Status)) 635 { 636 AcpiOsPrintf ("Could not signal debugger thread sync semaphore, %s\n", 637 AcpiFormatException (Status)); 638 } 639 } 640} 641 642 643/******************************************************************************* 644 * 645 * FUNCTION: AcpiDbCreateExecutionThreads 646 * 647 * PARAMETERS: NumThreadsArg - Number of threads to create 648 * NumLoopsArg - Loop count for the thread(s) 649 * MethodNameArg - Control method to execute 650 * 651 * RETURN: None 652 * 653 * DESCRIPTION: Create threads to execute method(s) 654 * 655 ******************************************************************************/ 656 657void 658AcpiDbCreateExecutionThreads ( 659 char *NumThreadsArg, 660 char *NumLoopsArg, 661 char *MethodNameArg) 662{ 663 ACPI_STATUS Status; 664 UINT32 NumThreads; 665 UINT32 NumLoops; 666 UINT32 i; 667 UINT32 Size; 668 ACPI_MUTEX MainThreadGate; 669 ACPI_MUTEX ThreadCompleteGate; 670 ACPI_MUTEX InfoGate; 671 672 673 /* Get the arguments */ 674 675 NumThreads = ACPI_STRTOUL (NumThreadsArg, NULL, 0); 676 NumLoops = ACPI_STRTOUL (NumLoopsArg, NULL, 0); 677 678 if (!NumThreads || !NumLoops) 679 { 680 AcpiOsPrintf ("Bad argument: Threads %X, Loops %X\n", 681 NumThreads, NumLoops); 682 return; 683 } 684 685 /* 686 * Create the semaphore for synchronization of 687 * the created threads with the main thread. 688 */ 689 Status = AcpiOsCreateSemaphore (1, 0, &MainThreadGate); 690 if (ACPI_FAILURE (Status)) 691 { 692 AcpiOsPrintf ("Could not create semaphore for synchronization with the main thread, %s\n", 693 AcpiFormatException (Status)); 694 return; 695 } 696 697 /* 698 * Create the semaphore for synchronization 699 * between the created threads. 700 */ 701 Status = AcpiOsCreateSemaphore (1, 1, &ThreadCompleteGate); 702 if (ACPI_FAILURE (Status)) 703 { 704 AcpiOsPrintf ("Could not create semaphore for synchronization between the created threads, %s\n", 705 AcpiFormatException (Status)); 706 (void) AcpiOsDeleteSemaphore (MainThreadGate); 707 return; 708 } 709 710 Status = AcpiOsCreateSemaphore (1, 1, &InfoGate); 711 if (ACPI_FAILURE (Status)) 712 { 713 AcpiOsPrintf ("Could not create semaphore for synchronization of AcpiGbl_DbMethodInfo, %s\n", 714 AcpiFormatException (Status)); 715 (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 716 (void) AcpiOsDeleteSemaphore (MainThreadGate); 717 return; 718 } 719 720 ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); 721 722 /* Array to store IDs of threads */ 723 724 AcpiGbl_DbMethodInfo.NumThreads = NumThreads; 725 Size = 4 * AcpiGbl_DbMethodInfo.NumThreads; 726 AcpiGbl_DbMethodInfo.Threads = (UINT32 *) AcpiOsAllocate (Size); 727 if (AcpiGbl_DbMethodInfo.Threads == NULL) 728 { 729 AcpiOsPrintf ("No memory for thread IDs array\n"); 730 (void) AcpiOsDeleteSemaphore (MainThreadGate); 731 (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 732 (void) AcpiOsDeleteSemaphore (InfoGate); 733 return; 734 } 735 ACPI_MEMSET (AcpiGbl_DbMethodInfo.Threads, 0, Size); 736 737 /* Setup the context to be passed to each thread */ 738 739 AcpiGbl_DbMethodInfo.Name = MethodNameArg; 740 AcpiGbl_DbMethodInfo.Flags = 0; 741 AcpiGbl_DbMethodInfo.NumLoops = NumLoops; 742 AcpiGbl_DbMethodInfo.MainThreadGate = MainThreadGate; 743 AcpiGbl_DbMethodInfo.ThreadCompleteGate = ThreadCompleteGate; 744 AcpiGbl_DbMethodInfo.InfoGate = InfoGate; 745 746 /* Init arguments to be passed to method */ 747 748 AcpiGbl_DbMethodInfo.InitArgs = 1; 749 AcpiGbl_DbMethodInfo.Args = AcpiGbl_DbMethodInfo.Arguments; 750 AcpiGbl_DbMethodInfo.Arguments[0] = AcpiGbl_DbMethodInfo.NumThreadsStr; 751 AcpiGbl_DbMethodInfo.Arguments[1] = AcpiGbl_DbMethodInfo.IdOfThreadStr; 752 AcpiGbl_DbMethodInfo.Arguments[2] = AcpiGbl_DbMethodInfo.IndexOfThreadStr; 753 AcpiGbl_DbMethodInfo.Arguments[3] = NULL; 754 AcpiDbUInt32ToHexString (NumThreads, AcpiGbl_DbMethodInfo.NumThreadsStr); 755 756 AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo); 757 758 /* Create the threads */ 759 760 AcpiOsPrintf ("Creating %X threads to execute %X times each\n", 761 NumThreads, NumLoops); 762 763 for (i = 0; i < (NumThreads); i++) 764 { 765 Status = AcpiOsExecute (OSL_DEBUGGER_THREAD, AcpiDbMethodThread, 766 &AcpiGbl_DbMethodInfo); 767 if (ACPI_FAILURE (Status)) 768 { 769 break; 770 } 771 } 772 773 /* Wait for all threads to complete */ 774 775 (void) AcpiOsWaitSemaphore (MainThreadGate, 1, ACPI_WAIT_FOREVER); 776 777 AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 778 AcpiOsPrintf ("All threads (%X) have completed\n", NumThreads); 779 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 780 781 /* Cleanup and exit */ 782 783 (void) AcpiOsDeleteSemaphore (MainThreadGate); 784 (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 785 (void) AcpiOsDeleteSemaphore (InfoGate); 786 787 AcpiOsFree (AcpiGbl_DbMethodInfo.Threads); 788 AcpiGbl_DbMethodInfo.Threads = NULL; 789} 790 791#endif /* ACPI_DEBUGGER */ 792 793 794