Ignore:
Timestamp:
Oct 30, 2006, 1:49:15 AM (19 years ago)
Author:
bird
Message:

toplevel load api code is done.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kLdr/kLdrDyldMod.c

    r2837 r2842  
    4949
    5050
    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 */
     62int 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 */
     88static 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 */
    52158void kldrDyldModUnloadPrerequisites(PKLDRDYLDMOD pMod)
    53159{
    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
    56197
    57198
Note: See TracChangeset for help on using the changeset viewer.