dbexec.c revision 193529
184865Sobrien/******************************************************************************* 284865Sobrien * 384865Sobrien * Module Name: dbexec - debugger control method execution 484865Sobrien * 584865Sobrien ******************************************************************************/ 684865Sobrien 784865Sobrien/****************************************************************************** 884865Sobrien * 984865Sobrien * 1. Copyright Notice 1084865Sobrien * 1184865Sobrien * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp. 1284865Sobrien * All rights reserved. 1384865Sobrien * 1484865Sobrien * 2. License 1584865Sobrien * 1684865Sobrien * 2.1. This is your license from Intel Corp. under its intellectual property 1784865Sobrien * rights. You may have additional license terms from the party that provided 1884865Sobrien * you this software, covering your right to use that party's intellectual 1984865Sobrien * property rights. 2084865Sobrien * 2184865Sobrien * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 2284865Sobrien * copy of the source code appearing in this file ("Covered Code") an 2384865Sobrien * irrevocable, perpetual, worldwide license under Intel's copyrights in the 2484865Sobrien * base code distributed originally by Intel ("Original Intel Code") to copy, 2584865Sobrien * make derivatives, distribute, use and display any portion of the Covered 2684865Sobrien * Code in any form, with the right to sublicense such rights; and 2784865Sobrien * 2884865Sobrien * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 2984865Sobrien * license (with the right to sublicense), under only those claims of Intel 3084865Sobrien * patents that are infringed by the Original Intel Code, to make, use, sell, 3184865Sobrien * offer to sell, and import the Covered Code and derivative works thereof 3284865Sobrien * solely to the minimum extent necessary to exercise the above copyright 3384865Sobrien * license, and in no event shall the patent license extend to any additions 3484865Sobrien * to or modifications of the Original Intel Code. No other license or right 3584865Sobrien * is granted directly or by implication, estoppel or otherwise; 3684865Sobrien * 3784865Sobrien * The above copyright and patent license is granted only if the following 3884865Sobrien * conditions are met: 3984865Sobrien * 4084865Sobrien * 3. Conditions 4184865Sobrien * 4284865Sobrien * 3.1. Redistribution of Source with Rights to Further Distribute Source. 4384865Sobrien * Redistribution of source code of any substantial portion of the Covered 4484865Sobrien * Code or modification with rights to further distribute source must include 4584865Sobrien * the above Copyright Notice, the above License, this list of Conditions, 4684865Sobrien * and the following Disclaimer and Export Compliance provision. In addition, 4784865Sobrien * Licensee must cause all Covered Code to which Licensee contributes to 4884865Sobrien * contain a file documenting the changes Licensee made to create that Covered 4984865Sobrien * Code and the date of any change. Licensee must include in that file the 5084865Sobrien * documentation of any changes made by any predecessor Licensee. Licensee 5184865Sobrien * must include a prominent statement that the modification is derived, 5284865Sobrien * directly or indirectly, from Original Intel Code. 5384865Sobrien * 5484865Sobrien * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 5584865Sobrien * Redistribution of source code of any substantial portion of the Covered 5684865Sobrien * Code or modification without rights to further distribute source must 5784865Sobrien * include the following Disclaimer and Export Compliance provision in the 5884865Sobrien * documentation and/or other materials provided with distribution. In 5984865Sobrien * addition, Licensee may not authorize further sublicense of source of any 6084865Sobrien * portion of the Covered Code, and must include terms to the effect that the 6184865Sobrien * license from Licensee to its licensee is limited to the intellectual 6284865Sobrien * property embodied in the software Licensee provides to its licensee, and 6384865Sobrien * not to intellectual property embodied in modifications its licensee may 6484865Sobrien * make. 6584865Sobrien * 6684865Sobrien * 3.3. Redistribution of Executable. Redistribution in executable form of any 6784865Sobrien * substantial portion of the Covered Code or modification must reproduce the 6884865Sobrien * above Copyright Notice, and the following Disclaimer and Export Compliance 6984865Sobrien * provision in the documentation and/or other materials provided with the 7084865Sobrien * distribution. 7184865Sobrien * 7284865Sobrien * 3.4. Intel retains all right, title, and interest in and to the Original 7384865Sobrien * Intel Code. 7484865Sobrien * 7584865Sobrien * 3.5. Neither the name Intel nor any other trademark owned or controlled by 7684865Sobrien * Intel shall be used in advertising or otherwise to promote the sale, use or 7784865Sobrien * other dealings in products derived from or relating to the Covered Code 7884865Sobrien * without prior written authorization from Intel. 7984865Sobrien * 8084865Sobrien * 4. Disclaimer and Export Compliance 8184865Sobrien * 8284865Sobrien * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 8384865Sobrien * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 8484865Sobrien * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 8584865Sobrien * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 8684865Sobrien * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 8784865Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 8884865Sobrien * PARTICULAR PURPOSE. 8984865Sobrien * 9084865Sobrien * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 9184865Sobrien * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 9284865Sobrien * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 9384865Sobrien * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 9484865Sobrien * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 9584865Sobrien * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 9684865Sobrien * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 9784865Sobrien * LIMITED REMEDY. 9884865Sobrien * 9984865Sobrien * 4.3. Licensee shall not export, either directly or indirectly, any of this 10084865Sobrien * software or system incorporating such software without first obtaining any 10184865Sobrien * required license or other approval from the U. S. Department of Commerce or 10284865Sobrien * any other agency or department of the United States Government. In the 10384865Sobrien * event Licensee exports any such software from the United States or 10484865Sobrien * re-exports any such software from a foreign destination, Licensee shall 10584865Sobrien * ensure that the distribution and export/re-export of the software is in 10684865Sobrien * compliance with all laws, regulations, orders, or other restrictions of the 10784865Sobrien * U.S. Export Administration Regulations. Licensee agrees that neither it nor 10884865Sobrien * any of its subsidiaries will export/re-export any technical data, process, 10984865Sobrien * software, or service, directly or indirectly, to any country for which the 11084865Sobrien * United States government or any agency thereof requires an export license, 11184865Sobrien * other governmental approval, or letter of assurance, without first obtaining 11284865Sobrien * such license, approval or letter. 11384865Sobrien * 11484865Sobrien *****************************************************************************/ 11584865Sobrien 11684865Sobrien 11784865Sobrien#include <contrib/dev/acpica/include/acpi.h> 11884865Sobrien#include <contrib/dev/acpica/include/accommon.h> 11984865Sobrien#include <contrib/dev/acpica/include/acdebug.h> 12084865Sobrien#include <contrib/dev/acpica/include/acnamesp.h> 12184865Sobrien 12284865Sobrien#ifdef ACPI_DEBUGGER 12384865Sobrien 12484865Sobrien#define _COMPONENT ACPI_CA_DEBUGGER 12584865Sobrien ACPI_MODULE_NAME ("dbexec") 12684865Sobrien 12784865Sobrien 12884865Sobrienstatic ACPI_DB_METHOD_INFO AcpiGbl_DbMethodInfo; 12984865Sobrien 13084865Sobrien/* Local prototypes */ 13184865Sobrien 13284865Sobrienstatic ACPI_STATUS 13384865SobrienAcpiDbExecuteMethod ( 13484865Sobrien ACPI_DB_METHOD_INFO *Info, 13584865Sobrien ACPI_BUFFER *ReturnObj); 13684865Sobrien 13784865Sobrienstatic void 13884865SobrienAcpiDbExecuteSetup ( 13984865Sobrien ACPI_DB_METHOD_INFO *Info); 14084865Sobrien 14184865Sobrienstatic UINT32 14284865SobrienAcpiDbGetOutstandingAllocations ( 14384865Sobrien void); 14484865Sobrien 14584865Sobrienstatic void ACPI_SYSTEM_XFACE 14684865SobrienAcpiDbMethodThread ( 14784865Sobrien void *Context); 14884865Sobrien 14984865Sobrienstatic ACPI_STATUS 15084865SobrienAcpiDbExecutionWalk ( 15184865Sobrien ACPI_HANDLE ObjHandle, 15284865Sobrien UINT32 NestingLevel, 15384865Sobrien void *Context, 15484865Sobrien void **ReturnValue); 15584865Sobrien 15684865Sobrien 15784865Sobrien/******************************************************************************* 15884865Sobrien * 15984865Sobrien * FUNCTION: AcpiDbExecuteMethod 16084865Sobrien * 16184865Sobrien * PARAMETERS: Info - Valid info segment 16284865Sobrien * ReturnObj - Where to put return object 16384865Sobrien * 16484865Sobrien * RETURN: Status 16584865Sobrien * 16684865Sobrien * DESCRIPTION: Execute a control method. 16784865Sobrien * 16884865Sobrien ******************************************************************************/ 16984865Sobrien 17084865Sobrienstatic ACPI_STATUS 17184865SobrienAcpiDbExecuteMethod ( 17284865Sobrien ACPI_DB_METHOD_INFO *Info, 17384865Sobrien ACPI_BUFFER *ReturnObj) 17484865Sobrien{ 17584865Sobrien ACPI_STATUS Status; 17684865Sobrien ACPI_OBJECT_LIST ParamObjects; 17784865Sobrien ACPI_OBJECT Params[ACPI_METHOD_NUM_ARGS]; 17884865Sobrien ACPI_HANDLE Handle; 17984865Sobrien ACPI_BUFFER Buffer; 18084865Sobrien UINT32 i; 18184865Sobrien ACPI_DEVICE_INFO *ObjInfo; 18284865Sobrien 18384865Sobrien 18484865Sobrien if (AcpiGbl_DbOutputToFile && !AcpiDbgLevel) 18584865Sobrien { 18684865Sobrien AcpiOsPrintf ("Warning: debug output is not enabled!\n"); 18784865Sobrien } 18884865Sobrien 18984865Sobrien /* Get the NS node, determines existence also */ 19084865Sobrien 19184865Sobrien Status = AcpiGetHandle (NULL, Info->Pathname, &Handle); 19284865Sobrien if (ACPI_FAILURE (Status)) 19384865Sobrien { 19484865Sobrien return (Status); 19584865Sobrien } 19684865Sobrien 19784865Sobrien /* Get the object info for number of method parameters */ 19884865Sobrien 19984865Sobrien Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; 20084865Sobrien Status = AcpiGetObjectInfo (Handle, &Buffer); 20184865Sobrien if (ACPI_FAILURE (Status)) 20284865Sobrien { 20384865Sobrien return (Status); 20484865Sobrien } 20584865Sobrien 20684865Sobrien ParamObjects.Pointer = NULL; 20784865Sobrien ParamObjects.Count = 0; 20884865Sobrien 20984865Sobrien ObjInfo = Buffer.Pointer; 21084865Sobrien if (ObjInfo->Type == ACPI_TYPE_METHOD) 21184865Sobrien { 21284865Sobrien /* Are there arguments to the method? */ 21384865Sobrien 21484865Sobrien if (Info->Args && Info->Args[0]) 21584865Sobrien { 21684865Sobrien for (i = 0; Info->Args[i] && i < ACPI_METHOD_NUM_ARGS; i++) 21784865Sobrien { 21884865Sobrien Params[i].Type = ACPI_TYPE_INTEGER; 21984865Sobrien Params[i].Integer.Value = ACPI_STRTOUL (Info->Args[i], NULL, 16); 22084865Sobrien } 22184865Sobrien 22284865Sobrien ParamObjects.Pointer = Params; 22384865Sobrien ParamObjects.Count = i; 22484865Sobrien } 22584865Sobrien else 22684865Sobrien { 22784865Sobrien /* Setup default parameters */ 22884865Sobrien 22984865Sobrien for (i = 0; i < ObjInfo->ParamCount; i++) 23084865Sobrien { 23184865Sobrien switch (i) 23284865Sobrien { 23384865Sobrien case 0: 23484865Sobrien 235 Params[0].Type = ACPI_TYPE_INTEGER; 236 Params[0].Integer.Value = 0x01020304; 237 break; 238 239 case 1: 240 241 Params[1].Type = ACPI_TYPE_STRING; 242 Params[1].String.Length = 12; 243 Params[1].String.Pointer = "AML Debugger"; 244 break; 245 246 default: 247 248 Params[i].Type = ACPI_TYPE_INTEGER; 249 Params[i].Integer.Value = i * (ACPI_INTEGER) 0x1000; 250 break; 251 } 252 } 253 254 ParamObjects.Pointer = Params; 255 ParamObjects.Count = ObjInfo->ParamCount; 256 } 257 } 258 259 ACPI_FREE (Buffer.Pointer); 260 261 /* Prepare for a return object of arbitrary size */ 262 263 ReturnObj->Pointer = AcpiGbl_DbBuffer; 264 ReturnObj->Length = ACPI_DEBUG_BUFFER_SIZE; 265 266 /* Do the actual method execution */ 267 268 AcpiGbl_MethodExecuting = TRUE; 269 Status = AcpiEvaluateObject (NULL, 270 Info->Pathname, &ParamObjects, ReturnObj); 271 272 AcpiGbl_CmSingleStep = FALSE; 273 AcpiGbl_MethodExecuting = FALSE; 274 275 return (Status); 276} 277 278 279/******************************************************************************* 280 * 281 * FUNCTION: AcpiDbExecuteSetup 282 * 283 * PARAMETERS: Info - Valid method info 284 * 285 * RETURN: None 286 * 287 * DESCRIPTION: Setup info segment prior to method execution 288 * 289 ******************************************************************************/ 290 291static void 292AcpiDbExecuteSetup ( 293 ACPI_DB_METHOD_INFO *Info) 294{ 295 296 /* Catenate the current scope to the supplied name */ 297 298 Info->Pathname[0] = 0; 299 if ((Info->Name[0] != '\\') && 300 (Info->Name[0] != '/')) 301 { 302 ACPI_STRCAT (Info->Pathname, AcpiGbl_DbScopeBuf); 303 } 304 305 ACPI_STRCAT (Info->Pathname, Info->Name); 306 AcpiDbPrepNamestring (Info->Pathname); 307 308 AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 309 AcpiOsPrintf ("Executing %s\n", Info->Pathname); 310 311 if (Info->Flags & EX_SINGLE_STEP) 312 { 313 AcpiGbl_CmSingleStep = TRUE; 314 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 315 } 316 317 else 318 { 319 /* No single step, allow redirection to a file */ 320 321 AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT); 322 } 323} 324 325 326#ifdef ACPI_DBG_TRACK_ALLOCATIONS 327UINT32 328AcpiDbGetCacheInfo ( 329 ACPI_MEMORY_LIST *Cache) 330{ 331 332 return (Cache->TotalAllocated - Cache->TotalFreed - Cache->CurrentDepth); 333} 334#endif 335 336/******************************************************************************* 337 * 338 * FUNCTION: AcpiDbGetOutstandingAllocations 339 * 340 * PARAMETERS: None 341 * 342 * RETURN: Current global allocation count minus cache entries 343 * 344 * DESCRIPTION: Determine the current number of "outstanding" allocations -- 345 * those allocations that have not been freed and also are not 346 * in one of the various object caches. 347 * 348 ******************************************************************************/ 349 350static UINT32 351AcpiDbGetOutstandingAllocations ( 352 void) 353{ 354 UINT32 Outstanding = 0; 355 356#ifdef ACPI_DBG_TRACK_ALLOCATIONS 357 358 Outstanding += AcpiDbGetCacheInfo (AcpiGbl_StateCache); 359 Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeCache); 360 Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeExtCache); 361 Outstanding += AcpiDbGetCacheInfo (AcpiGbl_OperandCache); 362#endif 363 364 return (Outstanding); 365} 366 367 368/******************************************************************************* 369 * 370 * FUNCTION: AcpiDbExecutionWalk 371 * 372 * PARAMETERS: WALK_CALLBACK 373 * 374 * RETURN: Status 375 * 376 * DESCRIPTION: Execute a control method. Name is relative to the current 377 * scope. 378 * 379 ******************************************************************************/ 380 381static ACPI_STATUS 382AcpiDbExecutionWalk ( 383 ACPI_HANDLE ObjHandle, 384 UINT32 NestingLevel, 385 void *Context, 386 void **ReturnValue) 387{ 388 ACPI_OPERAND_OBJECT *ObjDesc; 389 ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 390 ACPI_BUFFER ReturnObj; 391 ACPI_STATUS Status; 392 393 394 ObjDesc = AcpiNsGetAttachedObject (Node); 395 if (ObjDesc->Method.ParamCount) 396 { 397 return (AE_OK); 398 } 399 400 ReturnObj.Pointer = NULL; 401 ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 402 403 AcpiNsPrintNodePathname (Node, "Execute"); 404 405 /* Do the actual method execution */ 406 407 AcpiOsPrintf ("\n"); 408 AcpiGbl_MethodExecuting = TRUE; 409 410 Status = AcpiEvaluateObject (Node, NULL, NULL, &ReturnObj); 411 412 AcpiOsPrintf ("[%4.4s] returned %s\n", AcpiUtGetNodeName (Node), 413 AcpiFormatException (Status)); 414 AcpiGbl_MethodExecuting = FALSE; 415 416 return (AE_OK); 417} 418 419 420/******************************************************************************* 421 * 422 * FUNCTION: AcpiDbExecute 423 * 424 * PARAMETERS: Name - Name of method to execute 425 * Args - Parameters to the method 426 * Flags - single step/no single step 427 * 428 * RETURN: None 429 * 430 * DESCRIPTION: Execute a control method. Name is relative to the current 431 * scope. 432 * 433 ******************************************************************************/ 434 435void 436AcpiDbExecute ( 437 char *Name, 438 char **Args, 439 UINT32 Flags) 440{ 441 ACPI_STATUS Status; 442 ACPI_BUFFER ReturnObj; 443 char *NameString; 444 445 446#ifdef ACPI_DEBUG_OUTPUT 447 UINT32 PreviousAllocations; 448 UINT32 Allocations; 449 450 451 /* Memory allocation tracking */ 452 453 PreviousAllocations = AcpiDbGetOutstandingAllocations (); 454#endif 455 456 if (*Name == '*') 457 { 458 (void) AcpiWalkNamespace (ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT, 459 ACPI_UINT32_MAX, AcpiDbExecutionWalk, NULL, NULL); 460 return; 461 } 462 else 463 { 464 NameString = ACPI_ALLOCATE (ACPI_STRLEN (Name) + 1); 465 if (!NameString) 466 { 467 return; 468 } 469 470 ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); 471 472 ACPI_STRCPY (NameString, Name); 473 AcpiUtStrupr (NameString); 474 AcpiGbl_DbMethodInfo.Name = NameString; 475 AcpiGbl_DbMethodInfo.Args = Args; 476 AcpiGbl_DbMethodInfo.Flags = Flags; 477 478 ReturnObj.Pointer = NULL; 479 ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 480 481 AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo); 482 Status = AcpiDbExecuteMethod (&AcpiGbl_DbMethodInfo, &ReturnObj); 483 ACPI_FREE (NameString); 484 } 485 486 /* 487 * Allow any handlers in separate threads to complete. 488 * (Such as Notify handlers invoked from AML executed above). 489 */ 490 AcpiOsSleep ((ACPI_INTEGER) 10); 491 492 493#ifdef ACPI_DEBUG_OUTPUT 494 495 /* Memory allocation tracking */ 496 497 Allocations = AcpiDbGetOutstandingAllocations () - PreviousAllocations; 498 499 AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 500 501 if (Allocations > 0) 502 { 503 AcpiOsPrintf ("Outstanding: 0x%X allocations after execution\n", 504 Allocations); 505 } 506#endif 507 508 if (ACPI_FAILURE (Status)) 509 { 510 AcpiOsPrintf ("Execution of %s failed with status %s\n", 511 AcpiGbl_DbMethodInfo.Pathname, AcpiFormatException (Status)); 512 } 513 else 514 { 515 /* Display a return object, if any */ 516 517 if (ReturnObj.Length) 518 { 519 AcpiOsPrintf ("Execution of %s returned object %p Buflen %X\n", 520 AcpiGbl_DbMethodInfo.Pathname, ReturnObj.Pointer, 521 (UINT32) ReturnObj.Length); 522 AcpiDbDumpExternalObject (ReturnObj.Pointer, 1); 523 } 524 else 525 { 526 AcpiOsPrintf ("No return object from execution of %s\n", 527 AcpiGbl_DbMethodInfo.Pathname); 528 } 529 } 530 531 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 532} 533 534 535/******************************************************************************* 536 * 537 * FUNCTION: AcpiDbMethodThread 538 * 539 * PARAMETERS: Context - Execution info segment 540 * 541 * RETURN: None 542 * 543 * DESCRIPTION: Debugger execute thread. Waits for a command line, then 544 * simply dispatches it. 545 * 546 ******************************************************************************/ 547 548static void ACPI_SYSTEM_XFACE 549AcpiDbMethodThread ( 550 void *Context) 551{ 552 ACPI_STATUS Status; 553 ACPI_DB_METHOD_INFO *Info = Context; 554 ACPI_DB_METHOD_INFO LocalInfo; 555 UINT32 i; 556 UINT8 Allow; 557 ACPI_BUFFER ReturnObj; 558 559 560 /* 561 * AcpiGbl_DbMethodInfo.Arguments will be passed as method arguments. 562 * Prevent AcpiGbl_DbMethodInfo from being modified by multiple threads 563 * concurrently. 564 * 565 * Note: The arguments we are passing are used by the ASL test suite 566 * (aslts). Do not change them without updating the tests. 567 */ 568 (void) AcpiOsWaitSemaphore (Info->InfoGate, 1, ACPI_WAIT_FOREVER); 569 570 if (Info->InitArgs) 571 { 572 AcpiDbUInt32ToHexString (Info->NumCreated, Info->IndexOfThreadStr); 573 AcpiDbUInt32ToHexString (ACPI_TO_INTEGER (AcpiOsGetThreadId ()), 574 Info->IdOfThreadStr); 575 } 576 577 if (Info->Threads && (Info->NumCreated < Info->NumThreads)) 578 { 579 Info->Threads[Info->NumCreated++] = 580 ACPI_TO_INTEGER (AcpiOsGetThreadId()); 581 } 582 583 LocalInfo = *Info; 584 LocalInfo.Args = LocalInfo.Arguments; 585 LocalInfo.Arguments[0] = LocalInfo.NumThreadsStr; 586 LocalInfo.Arguments[1] = LocalInfo.IdOfThreadStr; 587 LocalInfo.Arguments[2] = LocalInfo.IndexOfThreadStr; 588 LocalInfo.Arguments[3] = NULL; 589 590 (void) AcpiOsSignalSemaphore (Info->InfoGate, 1); 591 592 for (i = 0; i < Info->NumLoops; i++) 593 { 594 Status = AcpiDbExecuteMethod (&LocalInfo, &ReturnObj); 595 if (ACPI_FAILURE (Status)) 596 { 597 AcpiOsPrintf ("%s During execution of %s at iteration %X\n", 598 AcpiFormatException (Status), Info->Pathname, i); 599 if (Status == AE_ABORT_METHOD) 600 { 601 break; 602 } 603 } 604 605#if 0 606 if ((i % 100) == 0) 607 { 608 AcpiOsPrintf ("%d executions, Thread 0x%x\n", i, AcpiOsGetThreadId ()); 609 } 610 611 if (ReturnObj.Length) 612 { 613 AcpiOsPrintf ("Execution of %s returned object %p Buflen %X\n", 614 Info->Pathname, ReturnObj.Pointer, (UINT32) ReturnObj.Length); 615 AcpiDbDumpExternalObject (ReturnObj.Pointer, 1); 616 } 617#endif 618 } 619 620 /* Signal our completion */ 621 622 Allow = 0; 623 (void) AcpiOsWaitSemaphore (Info->ThreadCompleteGate, 1, ACPI_WAIT_FOREVER); 624 Info->NumCompleted++; 625 626 if (Info->NumCompleted == Info->NumThreads) 627 { 628 /* Do signal for main thread once only */ 629 Allow = 1; 630 } 631 632 (void) AcpiOsSignalSemaphore (Info->ThreadCompleteGate, 1); 633 634 if (Allow) 635 { 636 Status = AcpiOsSignalSemaphore (Info->MainThreadGate, 1); 637 if (ACPI_FAILURE (Status)) 638 { 639 AcpiOsPrintf ("Could not signal debugger thread sync semaphore, %s\n", 640 AcpiFormatException (Status)); 641 } 642 } 643} 644 645 646/******************************************************************************* 647 * 648 * FUNCTION: AcpiDbCreateExecutionThreads 649 * 650 * PARAMETERS: NumThreadsArg - Number of threads to create 651 * NumLoopsArg - Loop count for the thread(s) 652 * MethodNameArg - Control method to execute 653 * 654 * RETURN: None 655 * 656 * DESCRIPTION: Create threads to execute method(s) 657 * 658 ******************************************************************************/ 659 660void 661AcpiDbCreateExecutionThreads ( 662 char *NumThreadsArg, 663 char *NumLoopsArg, 664 char *MethodNameArg) 665{ 666 ACPI_STATUS Status; 667 UINT32 NumThreads; 668 UINT32 NumLoops; 669 UINT32 i; 670 UINT32 Size; 671 ACPI_MUTEX MainThreadGate; 672 ACPI_MUTEX ThreadCompleteGate; 673 ACPI_MUTEX InfoGate; 674 675 676 /* Get the arguments */ 677 678 NumThreads = ACPI_STRTOUL (NumThreadsArg, NULL, 0); 679 NumLoops = ACPI_STRTOUL (NumLoopsArg, NULL, 0); 680 681 if (!NumThreads || !NumLoops) 682 { 683 AcpiOsPrintf ("Bad argument: Threads %X, Loops %X\n", 684 NumThreads, NumLoops); 685 return; 686 } 687 688 /* 689 * Create the semaphore for synchronization of 690 * the created threads with the main thread. 691 */ 692 Status = AcpiOsCreateSemaphore (1, 0, &MainThreadGate); 693 if (ACPI_FAILURE (Status)) 694 { 695 AcpiOsPrintf ("Could not create semaphore for synchronization with the main thread, %s\n", 696 AcpiFormatException (Status)); 697 return; 698 } 699 700 /* 701 * Create the semaphore for synchronization 702 * between the created threads. 703 */ 704 Status = AcpiOsCreateSemaphore (1, 1, &ThreadCompleteGate); 705 if (ACPI_FAILURE (Status)) 706 { 707 AcpiOsPrintf ("Could not create semaphore for synchronization between the created threads, %s\n", 708 AcpiFormatException (Status)); 709 (void) AcpiOsDeleteSemaphore (MainThreadGate); 710 return; 711 } 712 713 Status = AcpiOsCreateSemaphore (1, 1, &InfoGate); 714 if (ACPI_FAILURE (Status)) 715 { 716 AcpiOsPrintf ("Could not create semaphore for synchronization of AcpiGbl_DbMethodInfo, %s\n", 717 AcpiFormatException (Status)); 718 (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 719 (void) AcpiOsDeleteSemaphore (MainThreadGate); 720 return; 721 } 722 723 ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); 724 725 /* Array to store IDs of threads */ 726 727 AcpiGbl_DbMethodInfo.NumThreads = NumThreads; 728 Size = 4 * AcpiGbl_DbMethodInfo.NumThreads; 729 AcpiGbl_DbMethodInfo.Threads = (UINT32 *) AcpiOsAllocate (Size); 730 if (AcpiGbl_DbMethodInfo.Threads == NULL) 731 { 732 AcpiOsPrintf ("No memory for thread IDs array\n"); 733 (void) AcpiOsDeleteSemaphore (MainThreadGate); 734 (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 735 (void) AcpiOsDeleteSemaphore (InfoGate); 736 return; 737 } 738 ACPI_MEMSET (AcpiGbl_DbMethodInfo.Threads, 0, Size); 739 740 /* Setup the context to be passed to each thread */ 741 742 AcpiGbl_DbMethodInfo.Name = MethodNameArg; 743 AcpiGbl_DbMethodInfo.Flags = 0; 744 AcpiGbl_DbMethodInfo.NumLoops = NumLoops; 745 AcpiGbl_DbMethodInfo.MainThreadGate = MainThreadGate; 746 AcpiGbl_DbMethodInfo.ThreadCompleteGate = ThreadCompleteGate; 747 AcpiGbl_DbMethodInfo.InfoGate = InfoGate; 748 749 /* Init arguments to be passed to method */ 750 751 AcpiGbl_DbMethodInfo.InitArgs = 1; 752 AcpiGbl_DbMethodInfo.Args = AcpiGbl_DbMethodInfo.Arguments; 753 AcpiGbl_DbMethodInfo.Arguments[0] = AcpiGbl_DbMethodInfo.NumThreadsStr; 754 AcpiGbl_DbMethodInfo.Arguments[1] = AcpiGbl_DbMethodInfo.IdOfThreadStr; 755 AcpiGbl_DbMethodInfo.Arguments[2] = AcpiGbl_DbMethodInfo.IndexOfThreadStr; 756 AcpiGbl_DbMethodInfo.Arguments[3] = NULL; 757 AcpiDbUInt32ToHexString (NumThreads, AcpiGbl_DbMethodInfo.NumThreadsStr); 758 759 AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo); 760 761 /* Create the threads */ 762 763 AcpiOsPrintf ("Creating %X threads to execute %X times each\n", 764 NumThreads, NumLoops); 765 766 for (i = 0; i < (NumThreads); i++) 767 { 768 Status = AcpiOsExecute (OSL_DEBUGGER_THREAD, AcpiDbMethodThread, 769 &AcpiGbl_DbMethodInfo); 770 if (ACPI_FAILURE (Status)) 771 { 772 break; 773 } 774 } 775 776 /* Wait for all threads to complete */ 777 778 (void) AcpiOsWaitSemaphore (MainThreadGate, 1, ACPI_WAIT_FOREVER); 779 780 AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 781 AcpiOsPrintf ("All threads (%X) have completed\n", NumThreads); 782 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 783 784 /* Cleanup and exit */ 785 786 (void) AcpiOsDeleteSemaphore (MainThreadGate); 787 (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 788 (void) AcpiOsDeleteSemaphore (InfoGate); 789 790 AcpiOsFree (AcpiGbl_DbMethodInfo.Threads); 791 AcpiGbl_DbMethodInfo.Threads = NULL; 792} 793 794#endif /* ACPI_DEBUGGER */ 795 796 797