Changeset 2842 for trunk/kLdr/kLdrDyldMod.c
- Timestamp:
- Oct 30, 2006, 1:49:15 AM (19 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kLdr/kLdrDyldMod.c
r2837 r2842 49 49 50 50 51 51 /** 52 * Decrement the dynamic load count of the module and unload the module 53 * if the total reference count reaches zero. 54 * 55 * This may cause a cascade of unloading to occure. See kldrDyldModUnloadPrerequisites(). 56 * 57 * @returns status code. 58 * @retval 0 on success. 59 * @retval KLDR_ERR_NOT_LOADED_DYNAMICALLY if the module wasn't loaded dynamically. 60 * @param pMod The module to unload. 61 */ 62 int kldrDyldModDynamicUnload(PKLDRDYLDMOD pMod) 63 { 64 if (pMod->cDynRefs == 0) 65 return KLDR_ERR_NOT_LOADED_DYNAMICALLY; 66 KLDRDYLDMOD_ASSERT(pMod->cDynRefs <= pMod->cRefs); 67 KLDRDYLDMOD_ASSERT(pMod->enmState == KLDRSTATE_GOOD); 68 69 pMod->cRefs--; 70 pMod->cDynRefs--; 71 if (pMod->cRefs > 0) 72 return 0; 73 74 /* 75 * The module should be unloaded. 76 */ 77 kldrDyldModUnloadPrerequisites(pMod); 78 return 0; 79 } 80 81 82 /** 83 * Worker for kldrDyldModUnloadPrerequisites. 84 * 85 * @returns The number of modules that now can be unloaded. 86 * @param pMod The module in question. 87 */ 88 static uint32_t kldrDyldModUnloadPrerequisitesOne(PKLDRDYLDMOD pMod) 89 { 90 PKLDRDYLDMOD pMod2; 91 uint32_t cToUnload = 0; 92 uint32_t i; 93 94 KLDRDYLDMOD_ASSERT(pMod->papPrereqs); 95 96 /* 97 * Release the one in this module. 98 */ 99 for (i = 0; i < pMod->cPrereqs; i++) 100 { 101 pMod2 = pMod->papPrereqs[i]; 102 if (pMod2) 103 { 104 /* do the derefering ourselves or we'll end up in a recursive loop here. */ 105 KLDRDYLDMOD_ASSERT(pMod2->cDepRefs > 0); 106 KLDRDYLDMOD_ASSERT(pMod2->cRefs >= pMod2->cDepRefs); 107 pMod2->cDepRefs--; 108 pMod2->cRefs--; 109 cToUnload += !pMod2->cRefs; 110 } 111 } 112 113 /* 114 * Change the state 115 */ 116 switch (pMod->enmState) 117 { 118 case KLDRSTATE_LOADED_PREREQUISITES: 119 case KLDRSTATE_FIXED_UP: 120 pMod->enmState = KLDRSTATE_PENDING_DESTROY; 121 kldrDyldModUnlink(pMod); 122 break; 123 124 case KLDRSTATE_PENDING_INITIALIZATION: 125 pMod->enmState = KLDRSTATE_PENDING_GC; 126 break; 127 128 case KLDRSTATE_RELOADED_FIXED_UP: 129 case KLDRSTATE_RELOADED_LOADED_PREREQUISITES: 130 case KLDRSTATE_GOOD: 131 pMod->enmState = KLDRSTATE_PENDING_TERMINATION; 132 break; 133 134 case KLDRSTATE_INITIALIZATION_FAILED: 135 break; 136 137 default: 138 KLDRDYLDMOD_ASSERT(!"invalid state"); 139 break; 140 } 141 142 return cToUnload; 143 } 144 145 146 /** 147 * This is the heart of the unload code. 148 * 149 * It will recursivly (using the load list) initiate module unloading 150 * of all affected modules. 151 * 152 * This function will cause a state transition ot PENDING_DESTROY, PENDING_GC 153 * or PENDING_TERMINATION depending on the module state. There is one exception 154 * to this, and that's INITIALIZATION_FAILED, where the state will not be changed. 155 * 156 * @param pMod The module which prerequisites should be unloaded. 157 */ 52 158 void kldrDyldModUnloadPrerequisites(PKLDRDYLDMOD pMod) 53 159 { 54 55 } 160 uint32_t cToUnload; 161 162 /* sanity */ 163 #ifdef KLDRDYLD_STRICT 164 { 165 PKLDRDYLDMOD pMod2; 166 for (pMod2 = kLdrDyldHead; pMod2; pMod2 = pMod2->Load.pNext) 167 KLDRDYLDMOD_ASSERT(pMod2->enmState != KLDRSTATE_GOOD || pMod2->cRefs); 168 } 169 #endif 170 KLDRDYLDMOD_ASSERT(pMod->papPrereqs); 171 172 /* 173 * Unload prereqs of the module we're called on first. 174 */ 175 cToUnload = kldrDyldModUnloadPrerequisitesOne(pMod); 176 177 /* 178 * Iterate the load list in a cyclic manner until there are no more 179 * modules that can be pushed on into unloading. 180 */ 181 while (cToUnload) 182 { 183 cToUnload = 0; 184 for (pMod = kLdrDyldHead; pMod; pMod = pMod->Load.pNext) 185 { 186 if ( pMod->cRefs 187 || pMod->enmState >= KLDRSTATE_PENDING_TERMINATION 188 || pMod->enmState < KLDRSTATE_LOADED_PREREQUISITES) 189 continue; 190 cToUnload += kldrDyldModUnloadPrerequisitesOne(pMod); 191 } 192 } 193 } 194 195 196 56 197 57 198
Note:
See TracChangeset
for help on using the changeset viewer.