Changeset 2837
- Timestamp:
- Oct 28, 2006, 5:59:21 AM (19 years ago)
- Location:
- trunk/kLdr
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kLdr/kLdr.h
r2836 r2837 731 731 #define KLDR_ERR_INVALID_HANDLE (KLDR_ERR_BASE + 33) 732 732 /** The module wasn't found. */ 733 #define KLDR_ERR_MODULE_NOT_FOUND (KLDR_ERR_BASE + 34) 733 #define KLDR_ERR_MODULE_NOT_FOUND (KLDR_ERR_BASE + 34) 734 /** A prerequisit module wasn't found. */ 735 #define KLDR_ERR_PREREQUISITE_MODULE_NOT_FOUND (KLDR_ERR_BASE + 35) 736 /** The module is being terminated and can therefore not be loaded. */ 737 #define KLDR_ERR_MODULE_TERMINATING (KLDR_ERR_BASE + 36) 738 /** A prerequisit module is being terminated and can therefore not be loaded. */ 739 #define KLDR_ERR_PREREQUISITE_MODULE_TERMINATING (KLDR_ERR_BASE + 37) 740 /** An allocation failed. */ 741 #define KLDR_ERR_NO_MEMORY (KLDR_ERR_BASE + 38) 742 734 743 735 744 /** Encountered a bad fixup. */ -
trunk/kLdr/kLdrDyld.c
r2836 r2837 89 89 * previous frame. 90 90 */ 91 PPKLDRDYLDMOD g_pakLdrDyld; 92 /** The number of used entries in the g_pakLdrDyld array. */ 93 uint32_t g_ckLdrDyld; 94 /** The number of entries allocated for the g_pakLdrDyld array. */ 95 uint32_t g_ckLdrDyldAllocated; 91 static PPKLDRDYLDMOD g_papStackMods; 92 /** The number of used entries in the g_papStackMods array. */ 93 static uint32_t g_cStackMods; 94 /** The number of entries allocated for the g_papStackMods array. */ 95 static uint32_t g_cStackModsAllocated; 96 /** Number of active load calls. */ 97 static uint32_t g_cActiveLoadCalls; 98 /** Number of active unload calls. */ 99 static uint32_t g_cActiveUnloadCalls; 100 /** Boolean flag indicating that GC is active. */ 101 static uint32_t g_fActiveGC; 102 96 103 97 104 /** The global error buffer. */ … … 102 109 /** The executable flags. */ 103 110 uint32_t kLdrDyldFlags; 111 104 112 105 113 … … 116 124 static int kldrDyldDoGetFilename(PKLDRDYLDMOD pMod, char *pszFilename, size_t cchFilename); 117 125 static int kldrDyldDoQuerySymbol(PKLDRDYLDMOD pMod, uint32_t uSymbolOrdinal, const char *pszSymbolName, uintptr_t *pValue, uint32_t *pfKind); 118 static void kldrDyldStartLoading(void); 119 static void kldrDyldStopLoading(void); 120 static int kldrDyldCopyError(int rc, char *pszErr, size_t cchErr); 126 127 static void kldrDyldDoModuleTerminationAndGarabageCollection(void); 128 129 static uint32_t kldrDyldStackNewFrame(void); 130 int kldrDyldStackPushModule(PKLDRDYLDMOD pMod); 131 static int kldrDyldStackFrameCompleted(void); 132 static void kldrDyldStackDropFrame(uint32_t iStackTop, uint32_t iStackBottom, int rc); 133 134 static int kldrDyldCopyError(int rc, char *pszErr, size_t cchErr); 121 135 122 136 … … 178 192 { 179 193 PKLDRDYLDMOD pMod = NULL; 194 g_cActiveLoadCalls++; 180 195 rc = kldrDyldDoLoad(pszDll, pszDefPrefix, pszDefSuffix, enmSearch, fFlags, phMod, pszErr, cchErr); 196 g_cActiveLoadCalls--; 197 kldrDyldDoModuleTerminationAndGarabageCollection(); 181 198 kldrHlpSemRelease(); 182 199 *phMod = pMod; … … 203 220 if (!rc) 204 221 { 222 g_cActiveUnloadCalls++; 205 223 rc = kldrDyldDoUnload(hMod); 224 g_cActiveUnloadCalls--; 225 kldrDyldDoModuleTerminationAndGarabageCollection(); 206 226 kldrHlpSemRelease(); 207 227 } … … 217 237 * 218 238 * @returns 0 on success. 219 * @returns KLDR_ERR_MODULE_NOT_FOUND o n failure.239 * @returns KLDR_ERR_MODULE_NOT_FOUND or some I/O error on failure. 220 240 * @param pszDll The name of the dll to look for. 221 241 * @param pszDefPrefix Prefix than can be used when searching. … … 383 403 384 404 385 386 387 /** 388 * Worker for kLdrDyldLoad(). 405 /** 406 * Gets prerequisite module. 407 * 408 * This will try load the requested module if necessary, returning it in the MAPPED state. 409 * 410 * @returns 0 on success. 411 * @returns KLDR_ERR_MODULE_NOT_FOUND or I/O error on failure. 412 * @param pszDll The name of the dll to look for. 413 * @param pszDefPrefix Prefix than can be used when searching. 414 * @param pszDefSuffix Suffix than can be used when searching. 415 * @param enmSearch Method to use when locating the module. 416 * @param fFlags Flags, a combintation of the KLDRYDLD_LOAD_FLAGS_* \#defines. 417 * @param pDep The depentant module. 418 * @param ppMod Where to put the module we get. 419 */ 420 int kldrDyldGetPrerequisite(const char *pszDll, const char *pszDefPrefix, const char *pszDefSuffix, KLDRDYLDSEARCH enmSearch, 421 unsigned fFlags, PKLDRDYLDMOD pDep, PPKLDRDYLDMOD ppMod) 422 { 423 int rc; 424 425 *ppMod = NULL; 426 427 /* 428 * Try find the module among the ones that's already loaded. 429 */ 430 rc = kldrDyldFindExistingModule(pszDll, pszDefPrefix, pszDefSuffix, enmSearch, fFlags, ppMod); 431 if (!rc) 432 { 433 /* 434 * See if the module should go on the stack and if it needs 435 * some work before that. 436 */ 437 switch ((*ppMod)->enmState) 438 { 439 /* 440 * The module is good, just add the dependency. 441 */ 442 case KLDRSTATE_GOOD: 443 case KLDRSTATE_INITIALIZING: 444 return kldrDyldModAddDep(*ppMod, pDep); 445 446 /* 447 * Prerequisites needs checking. 448 */ 449 case KLDRSTATE_PENDING_INITIALIZATION: 450 (*ppMod)->fAlreadySeen = 0; 451 case KLDRSTATE_PENDING_TERMINATION: 452 break; 453 454 /* 455 * The module has been terminated so it need to be reloaded, have it's 456 * prereqs loaded, fixed up and initialized before we can use it again. 457 */ 458 case KLDRSTATE_PENDING_GC: 459 rc = kldrDyldModReload(*ppMod); 460 if (rc) 461 return rc; 462 break; 463 464 /* 465 * It's just been loaded or reloaded in this session, we will push it 466 * onto the stack even so to get a consisten init order with the other 467 * states. 468 */ 469 case KLDRSTATE_MAPPED: 470 case KLDRSTATE_RELOADED: 471 break; 472 473 /* 474 * Forget it, we don't know how to deal with re-initialization here. 475 */ 476 case KLDRSTATE_TERMINATING: 477 KLDRDYLD_ASSERT(!"KLDR_ERR_PREREQUISITE_MODULE_TERMINATING"); 478 return KLDR_ERR_PREREQUISITE_MODULE_TERMINATING; 479 480 /* 481 * Invalid state. 482 */ 483 default: 484 KLDRDYLD_ASSERT(!"invalid state"); 485 break; 486 } 487 } 488 else 489 { 490 /* 491 * We'll have to load it from file. 492 */ 493 rc = kldrDyldFindNewModule(pszDll, pszDefPrefix, pszDefSuffix, enmSearch, fFlags, ppMod); 494 if (!rc) 495 rc = kldrDyldModMap(*ppMod); 496 } 497 498 /* 499 * Push it onto the stack and add the dependency. 500 */ 501 if (!rc) 502 rc = kldrDyldStackPushModule(*ppMod); 503 if (!rc) 504 rc = kldrDyldModAddDep(*ppMod, pDep); 505 return rc; 506 } 507 508 509 /** 510 * Worker for kLdrDyldLoad() and helper for kLdrDyldLoadExe(). 389 511 * @internal 390 512 */ … … 392 514 unsigned fFlags, PPKLDRDYLDMOD ppMod, char *pszErr, size_t cchErr) 393 515 { 394 int rc;395 396 /* 397 * Try find it among the modules that's already loaded.516 int rc; 517 518 /* 519 * Try find the module among the ones that's already loaded. 398 520 */ 399 521 rc = kldrDyldFindExistingModule(pszDll, pszDefPrefix, pszDefSuffix, enmSearch, fFlags, ppMod); … … 401 523 { 402 524 /* 403 * If we're in a module termination call we must check that all the modules we 404 * depend on are loaded and initialized. 525 * Because of initialization and termination routines this 526 * get's kind of complicated. Even if the module is loaded, 527 * we might end up having to resolve all dependencies to check 528 * whether reloading or/and initialization is required. 405 529 */ 406 //continue here if ((*ppMod)->enmState::KLDRSTATE_LOADED)530 switch ((*ppMod)->enmState) 407 531 { 408 kldrHlpAssert(!"implement me"); 532 /* 533 * Prerequisites are ok, so nothing to do really. 534 */ 535 case KLDRSTATE_GOOD: 536 case KLDRSTATE_INITIALIZING: 537 return kldrDyldModDynamicLoad(*ppMod); 538 539 /* 540 * Prerequisites needs checking. 541 */ 542 case KLDRSTATE_PENDING_INITIALIZATION: 543 (*ppMod)->fAlreadySeen = 0; 544 case KLDRSTATE_PENDING_TERMINATION: 545 break; 546 547 /* 548 * The module has been terminated so it need to be reloaded, have it's 549 * prereqs loaded, fixed up and initialized before we can use it again. 550 */ 551 case KLDRSTATE_PENDING_GC: 552 rc = kldrDyldModReload(*ppMod); 553 if (rc) 554 return kldrDyldCopyError(rc, pszErr, cchErr); 555 break; 556 557 /* 558 * Forget it, we don't know how to deal with re-initialization here. 559 */ 560 case KLDRSTATE_TERMINATING: 561 KLDRDYLD_ASSERT(!"KLDR_ERR_MODULE_TERMINATING"); 562 return KLDR_ERR_MODULE_TERMINATING; 563 564 /* 565 * Invalid state. 566 */ 567 default: 568 KLDRDYLD_ASSERT(!"invalid state"); 569 break; 409 570 } 410 return kldrDyldModDynamicLoad(*ppMod); 411 } 412 413 /* 414 * Try open it. 415 */ 416 kldrDyldStartLoading(); 417 rc = kldrDyldFindNewModule(pszDll, pszDefPrefix, pszDefSuffix, enmSearch, fFlags, ppMod); 571 } 572 else 573 { 574 /* 575 * We'll have to load it from file. 576 */ 577 rc = kldrDyldFindNewModule(pszDll, pszDefPrefix, pszDefSuffix, enmSearch, fFlags, ppMod); 578 if (rc) 579 return kldrDyldCopyError(rc, pszErr, cchErr); 580 rc = kldrDyldModMap(*ppMod); 581 } 582 418 583 if (!rc) 419 584 { 420 421 422 } 585 /* 586 * Create the stack frame of modules by resolving module prerequisites. 587 */ 588 uint32_t iStackBottom = kldrDyldStackNewFrame(); 589 uint32_t iStack = iStackBottom; 590 uint32_t iStackTop; 591 rc = kldrDyldStackPushModule(*ppMod); 592 while (!rc && iStack < g_cStackMods /* changes while we're in the loop */) 593 { 594 PKLDRDYLDMOD pMod = g_papStackMods[iStack]; 595 switch (pMod->enmState) 596 { 597 /* 598 * Load immediate prerequisite modules and push the ones needing 599 * attention onto the stack. 600 */ 601 case KLDRSTATE_MAPPED: 602 case KLDRSTATE_RELOADED: 603 rc = kldrDyldModLoadPrerequisites(pMod, pszDll, pszDefPrefix, pszDefSuffix, enmSearch, fFlags); 604 break; 605 606 /* 607 * Check dependencies. 608 */ 609 case KLDRSTATE_PENDING_TERMINATION: 610 rc = kldrDyldModCheckPrerequisites(pMod); 611 break; 612 613 /* 614 * Check its prerequisite modules the first time around. 615 */ 616 case KLDRSTATE_PENDING_INITIALIZATION: 617 if (!pMod->fAlreadySeen) 618 { 619 pMod->fAlreadySeen = 1; 620 rc = kldrDyldModCheckPrerequisites(pMod); 621 } 622 break; 623 624 /* 625 * These are ok. 626 */ 627 case KLDRSTATE_LOADED_PREREQUISITES: 628 case KLDRSTATE_INITIALIZING: 629 case KLDRSTATE_GOOD: 630 break; 631 632 /* 633 * All other stats are invalid. 634 */ 635 default: 636 KLDRDYLD_ASSERT(!"invalid state"); 637 break; 638 } 639 640 /* next */ 641 iStack++; 642 } 643 iStackTop = kldrDyldStackFrameCompleted(); 644 645 /* 646 * Apply fixups. 647 */ 648 for (iStack = iStackBottom; !rc && iStack < iStackTop; iStack++) 649 { 650 PKLDRDYLDMOD pMod = g_papStackMods[iStack]; 651 if (pMod->enmState == KLDRSTATE_LOADED_PREREQUISITES) 652 rc = kldrDyldModFixup(pMod); 653 654 } 655 #ifdef KLDRDYLD_STRICT 656 if (!rc) 657 for (iStack = iStackBottom; !rc && iStack < iStackTop; iStack++) 658 KLDRDYLD_ASSERT(g_papStackMods[iStack]->enmState >= KLDRSTATE_FIXED_UP); 659 #endif 660 661 /* 662 * Call the initializers (LIFO order). 663 */ 664 iStack = iStackBottom; 665 while (!rc && iStack-- > iStackTop) 666 { 667 PKLDRDYLDMOD pMod = g_papStackMods[iStack]; 668 if (pMod->enmState == KLDRSTATE_PENDING_INITIALIZATION) 669 rc = kldrDyldModCallInit(pMod); 670 } 671 #ifdef KLDRDYLD_STRICT 672 if (!rc) 673 for (iStack = iStackBottom; !rc && iStack < iStackTop; iStack++) 674 KLDRDYLD_ASSERT(g_papStackMods[iStack]->enmState == KLDRSTATE_GOOD); 675 #endif 676 677 /* 678 * Complete the load by incrementing the dynamic load count of the 679 * requested module (return handle is already set). 680 */ 681 if (!rc) 682 { 683 rc = kldrDyldModDynamicLoad(*ppMod); 684 if (!rc) 685 { 686 kldrDyldStackDropFrame(iStackTop, iStackBottom, rc); 687 kldrDyldModDeref(*ppMod); 688 return rc; 689 } 690 } 691 kldrDyldStackDropFrame(iStackTop, iStackBottom, rc); 692 } 693 else 694 { 695 /* If the reference count is 0 do a quick ref/deref to trigger destruction. */ 696 kldrDyldModAddRef(*ppMod); 697 kldrDyldModDeref(*ppMod); 698 } 699 700 /* 701 * We've failed, copy/create error string. 702 */ 423 703 return kldrDyldCopyError(rc, pszErr, cchErr); 424 704 } … … 543 823 { 544 824 /* 545 * Load all dependantmodules.825 * Load all prerequisite modules. 546 826 */ 547 827 PKLDRMOD pCur; … … 594 874 #endif 595 875 876 877 /** 878 * Do garbage collection. 879 * 880 * This isn't doing anything unless it's called from the last 881 * load or unload call. 882 */ 883 static void kldrDyldDoModuleTerminationAndGarabageCollection(void) 884 { 885 PKLDRDYLDMOD pMod; 886 887 /* 888 * We don't do anything untill we're got rid of all re-entrant calls. 889 * This will ensure that we get the most optimal termination order and 890 * that we don't unload anything too early. 891 */ 892 if (g_cActiveLoadCalls || g_cActiveUnloadCalls || g_fActiveGC) 893 return; 894 g_fActiveGC = 1; 895 896 /* 897 * Release prerequisites to maximize the number of term calls pending. 898 */ 899 for (pMod = kLdrDyldHead; pMod; pMod = pMod->Load.pNext); 900 { 901 kldrDyldModAddRef(pMod); 902 903 switch (pMod->enmState) 904 { 905 case KLDRSTATE_GOOD: 906 case KLDRSTATE_PENDING_GC: 907 break; 908 909 case KLDRSTATE_PENDING_INITIALIZATION: 910 case KLDRSTATE_PENDING_TERMINATION: 911 kldrDyldModUnloadPrerequisites(pMod); 912 break; 913 914 default: 915 KLDRDYLD_ASSERT(!"invalid GC state (a)"); 916 break; 917 } 918 919 kldrDyldModDeref(pMod); 920 } 921 922 /* 923 * Do termination calls (FIFO order) process new unloads. 924 * The current algorithm here is a bit sluggish, but it ensure correct order. 925 */ 926 do 927 { 928 for (pMod = g_pkLdrDyldTermHead; pMod; pMod = pMod->Term.pNext) 929 { 930 int fRestart = 0; 931 kldrDyldModAddRef(pMod); 932 933 switch (pMod->enmState) 934 { 935 case KLDRSTATE_GOOD: 936 case KLDRSTATE_PENDING_GC: 937 break; 938 939 case KLDRSTATE_PENDING_TERMINATION: 940 kldrDyldModUnloadPrerequisites(pMod); 941 kldrDyldModCallTerm(pMod); 942 fRestart = 1; 943 break; 944 945 case KLDRSTATE_PENDING_INITIALIZATION: 946 kldrDyldModUnloadPrerequisites(pMod); 947 break; 948 949 default: 950 KLDRDYLD_ASSERT(!"invalid GC state (b)"); 951 break; 952 } 953 954 kldrDyldModDeref(pMod); 955 if (fRestart) 956 break; 957 } 958 } while (pMod); 959 960 /* 961 * Unmap and destroy modules pending for GC. 962 */ 963 pMod = kLdrDyldHead; 964 while (pMod) 965 { 966 PKLDRDYLDMOD pNext = pMod->Load.pNext; 967 switch (pMod->enmState) 968 { 969 case KLDRSTATE_PENDING_GC: 970 kldrDyldModAddRef(pMod); 971 KLDRDYLD_ASSERT(pMod->cRefs == 1); 972 973 pMod->enmState = KLDRSTATE_GC; 974 kldrDyldModUnmap(pMod); 975 976 KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_DESTROY); 977 kldrDyldModDeref(pMod); 978 break; 979 980 /* the only other state that's valid at this point. */ 981 case KLDRSTATE_GOOD: 982 break; 983 984 /* all other stats are invalid. */ 985 default: 986 KLDRDYLD_ASSERT(!"invalid GC state (c)"); 987 break; 988 } 989 990 /* next */ 991 pMod = pNext; 992 } 993 994 g_fActiveGC = 0; 995 } 996 997 998 596 999 /** 597 1000 * Starts loading a new module and its dependencies. 598 */ 599 static void kldrDyldStartLoading(void) 1001 * @returns Where the new stack frame starts. 1002 */ 1003 static uint32_t kldrDyldStackNewFrame(void) 600 1004 { 601 1005 #ifdef KLDRDYLD_STRICT … … 610 1014 } 611 1015 #endif 612 } 613 614 615 /** 616 * Records the loading of the module. 1016 return g_cStackMods; 1017 } 1018 1019 1020 /** 1021 * Records the module. 617 1022 * 618 1023 * @return 0 on success, KLDR_ERR_NO_MEMORY if we can't expand the table. 619 1024 * @param pMod The module to record. 620 1025 */ 621 static int kldrDyldRecord(PKLDRDYLDMOD pMod) 622 { 623 624 } 625 626 627 628 /** 629 * Done loading a module and its dependencies. 630 * 631 * If the load failed, unload all the modules involved. 632 * If the load succeeded, 633 * 634 * @returns rc. 635 * @param rc The status code. 636 */ 637 static void kldrDyldDoneLoading(int rc) 638 { 639 640 } 641 1026 int kldrDyldStackPushModule(PKLDRDYLDMOD pMod) 1027 { 1028 int rc; 1029 1030 /* 1031 * Grow the stack if necessary. 1032 */ 1033 if (g_cStackMods + 1 > g_cStackModsAllocated) 1034 { 1035 uint32_t cNew = g_cStackModsAllocated ? g_cStackModsAllocated * 2 : 128; 1036 void *pvOld = g_papStackMods; 1037 void *pvNew = kldrHlpAlloc(cNew * sizeof(g_papStackMods[0])); 1038 if (!pvNew) 1039 return KLDR_ERR_NO_MEMORY; 1040 kLdrHlpMemCopy(pvNew, pvOld, g_cStackMods * sizeof(g_papStackMods[0])); 1041 g_papStackMods = (PPKLDRDYLDMOD)pvNew; 1042 kldrHlpFree(pvOld); 1043 } 1044 1045 /* 1046 * Add a reference and push the module onto the stack. 1047 */ 1048 rc = kldrDyldModAddRef(pMod); 1049 if (!rc) 1050 g_papStackMods[g_cStackMods++] = pMod; 1051 return rc; 1052 } 1053 1054 1055 /** 1056 * The frame has been completed. 1057 * 1058 * @returns Where the frame ends. 1059 */ 1060 static int kldrDyldStackFrameCompleted(void) 1061 { 1062 return g_cStackMods; 1063 } 1064 1065 1066 /** 1067 * Done with the stack frame, dereference all the module in it. 1068 * 1069 * @param iStackTop The top of the stack frame. 1070 * @param iStackBottom The bottom of the stack frame. 1071 * @param rc Used for state verification. 1072 */ 1073 static void kldrDyldStackDropFrame(uint32_t iStackTop, uint32_t iStackBottom, int rc) 1074 { 1075 uint32_t iStack; 1076 KLDRDYLD_ASSERT(iStackBottom <= g_cStackMods); 1077 KLDRDYLD_ASSERT(iStackTop == g_cStackMods); 1078 1079 /* 1080 * First pass, cleanup modules in an obvious 'failed' state so we don't 1081 * leave any of the non-reentrant states behind. 1082 */ 1083 for (iStack = iStackBottom; iStack < iStackTop; iStack++) 1084 { 1085 PKLDRDYLDMOD pMod = g_papStackMods[--iStackTop]; 1086 switch (pMod->enmState) 1087 { 1088 /* 1089 * Unmap freshly mapped so it can be destroyed. 1090 */ 1091 case KLDRSTATE_MAPPED: 1092 KLDRDYLD_ASSERT(rc); 1093 kldrDyldModUnmap(pMod); 1094 KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_DESTROY); 1095 break; 1096 1097 /* 1098 * Reload is reverted to it's old state. 1099 */ 1100 case KLDRSTATE_RELOADED: 1101 KLDRDYLD_ASSERT(rc); 1102 pMod->enmState = KLDRSTATE_PENDING_GC; 1103 break; 1104 1105 /* 1106 * Unload prerequisites and unmap modules loaded in this frame. 1107 */ 1108 case KLDRSTATE_LOADED_PREREQUISITES: 1109 case KLDRSTATE_FIXED_UP: /** @todo fix reload state mess. */ 1110 KLDRDYLD_ASSERT(rc); 1111 kldrDyldModUnloadPrerequisites(pMod); 1112 KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_GC); 1113 kldrDyldModUnmap(pMod); 1114 KLDRDYLD_ASSERT(pMod->enmState == KLDRSTATE_PENDING_DESTROY); 1115 break; 1116 1117 /* 1118 * Ok states. 1119 */ 1120 case KLDRSTATE_INITIALIZING: 1121 KLDRDYLD_ASSERT(g_cActiveLoadCalls > 0); 1122 break; 1123 case KLDRSTATE_TERMINATING: 1124 KLDRDYLD_ASSERT(rc); 1125 KLDRDYLD_ASSERT(g_fActiveGC); 1126 break; 1127 case KLDRSTATE_PENDING_TERMINATION: 1128 case KLDRSTATE_PENDING_INITIALIZATION: 1129 case KLDRSTATE_PENDING_GC: 1130 case KLDRSTATE_PENDING_DESTROY: 1131 KLDRDYLD_ASSERT(rc); 1132 break; 1133 case KLDRSTATE_GOOD: 1134 break; 1135 1136 /* 1137 * Bad states. 1138 */ 1139 default: 1140 KLDRDYLD_ASSERT(!"drop frame bad state (a)"); 1141 break; 1142 } 1143 } 1144 1145 /* 1146 * Second pass, release the references to the modules on the stack. 1147 */ 1148 while (iStackTop > iStackBottom) 1149 { 1150 /* 1151 * Pop a module. 1152 */ 1153 PKLDRDYLDMOD pMod = g_papStackMods[--iStackTop]; 1154 g_cStackMods = iStackTop; 1155 1156 /* 1157 * Validate the state. 1158 */ 1159 switch (pMod->enmState) 1160 { 1161 /* 1162 * Ok states 1163 */ 1164 case KLDRSTATE_INITIALIZING: 1165 KLDRDYLD_ASSERT(g_cActiveLoadCalls > 0); 1166 break; 1167 case KLDRSTATE_TERMINATING: 1168 KLDRDYLD_ASSERT(rc); 1169 KLDRDYLD_ASSERT(g_fActiveGC); 1170 break; 1171 case KLDRSTATE_PENDING_INITIALIZATION: 1172 case KLDRSTATE_PENDING_TERMINATION: 1173 case KLDRSTATE_PENDING_GC: 1174 case KLDRSTATE_PENDING_DESTROY: 1175 KLDRDYLD_ASSERT(rc); 1176 break; 1177 case KLDRSTATE_GOOD: 1178 break; 1179 1180 /* 1181 * Bad states. 1182 */ 1183 default: 1184 KLDRDYLD_ASSERT(!"drop frame bad state (b)"); 1185 break; 1186 } 1187 1188 /* 1189 * Release it. 1190 */ 1191 kldrDyldModDeref(pMod); 1192 } 1193 } 642 1194 643 1195 -
trunk/kLdr/kLdrDyldMod.c
r2835 r2837 35 35 36 36 37 /******************************************************************************* 38 * Defined Constants And Macros * 39 *******************************************************************************/ 40 /** @def KLDRDYLDMOD_ASSERT 41 * Assert that an expression is true when KLDRDYLD_STRICT is defined. 42 */ 43 #ifdef KLDRDYLD_STRICT 44 # define KLDRDYLDMOD_ASSERT(expr) kldrHlpAssert(expr) 45 #else 46 # define KLDRDYLDMOD_ASSERT(expr) do {} while (0) 47 #endif 37 48 38 49 39 50 51 52 void kldrDyldModUnloadPrerequisites(PKLDRDYLDMOD pMod) 53 { 54 55 } 56 57 58 void kldrDyldModDeref(PKLDRDYLDMOD pMod) 59 { 60 /* validate input */ 61 KLDRDYLDMOD_ASSERT(pMod->enmState > KLDRSTATE_INVALID && pMod->enmState < KLDRSTATE_END); 62 KLDRDYLDMOD_ASSERT(pMod->cRefs > 0); 63 KLDRDYLDMOD_ASSERT(pMod->cRefs >= pMod->cDepRefs + pMod->cDynRefs); 64 65 /* decrement. */ 66 if (pMod->cRefs > 0) 67 pMod->cRefs--; 68 69 /* 70 * Drop prerequisites for stats that implies that no recursion can have taken place yet. 71 * This ASSUMES that we're only dereferencing modules when an operation completes. 72 * (This is *required* for the reloaded state.) 73 */ 74 switch (pMod->enmState) 75 { 76 case KLDRSTATE_MAPPED: 77 case KLDRSTATE_LOADED_PREREQUISITES: 78 case KLDRSTATE_FIXED_UP: 79 case KLDRSTATE_RELOADED: 80 kldrDyldModUnloadPrerequisites(pMod); 81 pMod->enmState = KLDRSTATE_PENDING_GC; 82 break; 83 84 case KLDRSTATE_PENDING_INITIALIZATION: 85 case KLDRSTATE_INITIALIZING: 86 case KLDRSTATE_GOOD: 87 case KLDRSTATE_PENDING_TERMINATION: 88 case KLDRSTATE_TERMINATING: 89 case KLDRSTATE_PENDING_GC: 90 case KLDRSTATE_GC: 91 case KLDRSTATE_PENDING_DESTROY: 92 break; 93 94 default: 95 KLDRDYLDMOD_ASSERT(!"Invalid deref state"); 96 break; 97 } 98 99 /* 100 * Also drop prerequisites if noone is referencing the module. 101 */ 102 if (!pMod->cDepRefs && !pMod->cDynRefs) 103 { 104 switch (pMod->enmState) 105 { 106 case KLDRSTATE_MAPPED: 107 case KLDRSTATE_LOADED_PREREQUISITES: 108 case KLDRSTATE_FIXED_UP: 109 case KLDRSTATE_RELOADED: 110 /* already dropped. */ 111 break; 112 113 case KLDRSTATE_PENDING_INITIALIZATION: 114 kldrDyldModUnloadPrerequisites(pMod); 115 pMod->enmState = KLDRSTATE_PENDING_GC; 116 break; 117 118 case KLDRSTATE_GOOD: 119 pMod->enmState = KLDRSTATE_PENDING_TERMINATION; 120 case KLDRSTATE_PENDING_TERMINATION: 121 case KLDRSTATE_PENDING_GC: 122 kldrDyldModUnloadPrerequisites(pMod); 123 break; 124 125 case KLDRSTATE_TERMINATING: 126 case KLDRSTATE_GC: 127 case KLDRSTATE_PENDING_DESTROY: 128 break; 129 130 default: 131 KLDRDYLDMOD_ASSERT(!"Invalid deref state (b)"); 132 break; 133 } 134 } 135 136 /* 137 * If there are no references whatsoever now and the module 138 * is pending destruction, destroy it. 139 */ 140 if ( !pMod->cRefs 141 && ( pMod->enmState == KLDRSTATE_PENDING_DESTROY 142 || pMod->enmState == KLDRSTATE_GC)) 143 kldrDyldModDestroy(pMod); 144 } -
trunk/kLdr/kLdrInternal.h
r2836 r2837 77 77 /** The module been mapped. 78 78 * Prev state: OPEN 79 * Next state: LOADED_ DEPS, DESTROYED79 * Next state: LOADED_PREREQUISITES, DESTROYED 80 80 */ 81 81 KLDRSTATE_MAPPED, 82 /** The immediate dependencies has been loaded. 83 * Prev state: MAPPED 82 /** The module has been reloaded and needs to be fixed up again. 83 * (The loader can still be in a re-entrant mode.) 84 * Prev state: PENDING_GC 85 * Next state: LOADED_PREREQUISITES, PENDING_GC 86 */ 87 KLDRSTATE_RELOADED, 88 /** The immediate prerequisites have been loaded. 89 * Prev state: MAPPED, RELOADED 84 90 * Next state: FIXED_UP, DESTROYED 85 91 */ 86 KLDRSTATE_LOADED_ DEPS,92 KLDRSTATE_LOADED_PREREQUISITES, 87 93 /** Fixups has been applied. 88 * Prev state: LOADED_ DEPS94 * Prev state: LOADED_PREREQUISITES 89 95 * Next state: PENDING_INIT, DESTROYED 90 96 */ … … 124 130 * (The loader can still be in a re-entrant mode.) 125 131 * Prev state: TERMINATING, INITIALIZING, PENDING_INITIALIZATION 126 * Next state: GC, RELOAD ING132 * Next state: GC, RELOADED 127 133 */ 128 134 KLDRSTATE_PENDING_GC, 129 135 /** Being garbage collected. 130 * (The loader can still be in a re-entrant mode.)131 136 * Prev state: PENDING_GC 137 * Next state: PENDING_DESTROY, DESTROYED 138 */ 139 KLDRSTATE_GC, 140 /** The module has be unlinked, but there are still stack references to it. 141 * Prev state: GC 132 142 * Next state: DESTROYED 133 143 */ 134 KLDRSTATE_GC, 135 /** The module is being reloaded after having been scheduled for termination or/and GC. 136 * (The loader can still be in a re-entrant mode.) 137 * Prev state: PENDING_GC 138 * Next state: PENDING_INITIALIZATION 139 */ 140 KLDRSTATE_RELOADING, 144 KLDRSTATE_PENDING_DESTROY, 141 145 /** The module has been destroyed and is no longer valid. 142 * Prev state: GC 146 * Prev state: GC, PENDING_DESTROY 143 147 */ 144 148 KLDRSTATE_DESTROYED, … … 163 167 /** The module handle. */ 164 168 HKLDRMOD hMod; 165 /** The number of references. */169 /** The total number of references. */ 166 170 uint32_t cRefs; 167 /** The number of dynamic references. */ 171 /** The number of dependency references. */ 172 uint32_t cDepRefs; 173 /** The number of dynamic load references. */ 168 174 uint32_t cDynRefs; 169 /** The number of dynamic load operations in progress.170 * This is used to reject anyone trying to unload a module before the load has171 * been completed. An alternative to this would be to not add the cDynRefs until172 * the load operation has completed... */173 uint32_t cDynRefsInProgress;174 175 /** Set if this is the executable module. 175 176 * When clear, the module is a shared object or relocatable object. */ … … 180 181 uint32_t fBindable : 1; 181 182 /** Reserved for future use. */ 182 uint32_t fReserved : 29; 183 uint32_t fReserved : 28; 184 /** Already checked dependencies. 185 * This is flag used when resolving module dependencies during a load, it 186 * deals with modules in the KLDRSTATE_PENDING_INITIALIZATION state. */ 187 uint32_t fAlreadySeen : 1; 183 188 /** The load list linkage. */ 184 189 struct … … 233 238 int kldrDyldModCreate(PKLDRRDR pRdr, PPKLDRDYLDMOD ppMod); 234 239 int kldrDyldModDestroy(PKLDRDYLDMOD pMod); 235 int kldrDyldModAddDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pModDep); 236 int kldrDyldModRemoveDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pModDep); 240 int kldrDyldModAddRef(PKLDRDYLDMOD pMod); 241 void kldrDyldModDeref(PKLDRDYLDMOD pMod); 242 int kldrDyldModAddDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep); 243 void kldrDyldModRemoveDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep); 237 244 int kldrDyldModDynamicLoad(PKLDRDYLDMOD pMod); 238 245 int kldrDyldModDynamicUnload(PKLDRDYLDMOD pMod); … … 245 252 int kldrDyldModMap(PKLDRDYLDMOD pMod); 246 253 int kldrDyldModUnmap(PKLDRDYLDMOD pMod); 247 int kldrDyldModLoadDependencies(PKLDRDYLDMOD pMod); 254 int kldrDyldModLoadPrerequisites(PKLDRDYLDMOD pMod, const char *pszName, const char *pszDefPrefix, const char *pszDefSuffix, 255 KLDRDYLDSEARCH enmSearch, unsigned fFlags); 256 int kldrDyldModCheckPrerequisites(PKLDRDYLDMOD pMod); 257 void kldrDyldModUnloadPrerequisites(PKLDRDYLDMOD pMod); 248 258 int kldrDyldModFixup(PKLDRDYLDMOD pMod); 249 259 int kldrDyldModCallInit(PKLDRDYLDMOD pMod); 250 int kldrDyldModCallTerm(PKLDRDYLDMOD pMod); 260 void kldrDyldModCallTerm(PKLDRDYLDMOD pMod); 261 int kldrDyldModReload(PKLDRDYLDMOD pMod); 251 262 int kldrDyldModAttachThread(PKLDRDYLDMOD pMod); 252 263 int kldrDyldModDetachThread(PKLDRDYLDMOD pMod);
Note:
See TracChangeset
for help on using the changeset viewer.