Changeset 2837


Ignore:
Timestamp:
Oct 28, 2006, 5:59:21 AM (19 years ago)
Author:
bird
Message:

in progress...

Location:
trunk/kLdr
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/kLdr/kLdr.h

    r2836 r2837  
    731731#define KLDR_ERR_INVALID_HANDLE         (KLDR_ERR_BASE + 33)
    732732/** 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
    734743
    735744/** Encountered a bad fixup. */
  • trunk/kLdr/kLdrDyld.c

    r2836 r2837  
    8989 * previous frame.
    9090 */
    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;
     91static PPKLDRDYLDMOD    g_papStackMods;
     92/** The number of used entries in the g_papStackMods array. */
     93static uint32_t         g_cStackMods;
     94/** The number of entries allocated for the g_papStackMods array. */
     95static uint32_t         g_cStackModsAllocated;
     96/** Number of active load calls. */
     97static uint32_t         g_cActiveLoadCalls;
     98/** Number of active unload calls. */
     99static uint32_t         g_cActiveUnloadCalls;
     100/** Boolean flag indicating that GC is active. */
     101static uint32_t         g_fActiveGC;
     102
    96103
    97104/** The global error buffer. */
     
    102109/** The executable flags. */
    103110uint32_t        kLdrDyldFlags;
     111
    104112
    105113
     
    116124static int kldrDyldDoGetFilename(PKLDRDYLDMOD pMod, char *pszFilename, size_t cchFilename);
    117125static 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
     127static void     kldrDyldDoModuleTerminationAndGarabageCollection(void);
     128
     129static uint32_t kldrDyldStackNewFrame(void);
     130int     kldrDyldStackPushModule(PKLDRDYLDMOD pMod);
     131static int      kldrDyldStackFrameCompleted(void);
     132static void     kldrDyldStackDropFrame(uint32_t iStackTop, uint32_t iStackBottom, int rc);
     133
     134static int      kldrDyldCopyError(int rc, char *pszErr, size_t cchErr);
    121135
    122136
     
    178192    {
    179193        PKLDRDYLDMOD pMod = NULL;
     194        g_cActiveLoadCalls++;
    180195        rc = kldrDyldDoLoad(pszDll, pszDefPrefix, pszDefSuffix, enmSearch, fFlags, phMod, pszErr, cchErr);
     196        g_cActiveLoadCalls--;
     197        kldrDyldDoModuleTerminationAndGarabageCollection();
    181198        kldrHlpSemRelease();
    182199        *phMod = pMod;
     
    203220    if (!rc)
    204221    {
     222        g_cActiveUnloadCalls++;
    205223        rc = kldrDyldDoUnload(hMod);
     224        g_cActiveUnloadCalls--;
     225        kldrDyldDoModuleTerminationAndGarabageCollection();
    206226        kldrHlpSemRelease();
    207227    }
     
    217237 *
    218238 * @returns 0 on success.
    219  * @returns KLDR_ERR_MODULE_NOT_FOUND on failure.
     239 * @returns KLDR_ERR_MODULE_NOT_FOUND or some I/O error on failure.
    220240 * @param   pszDll          The name of the dll to look for.
    221241 * @param   pszDefPrefix    Prefix than can be used when searching.
     
    383403
    384404
    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 */
     420int 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().
    389511 * @internal
    390512 */
     
    392514                          unsigned fFlags, PPKLDRDYLDMOD ppMod, char *pszErr, size_t cchErr)
    393515{
    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.
    398520     */
    399521    rc = kldrDyldFindExistingModule(pszDll, pszDefPrefix, pszDefSuffix, enmSearch, fFlags, ppMod);
     
    401523    {
    402524        /*
    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.
    405529         */
    406 //continue here        if ((*ppMod)->enmState::KLDRSTATE_LOADED)
     530        switch ((*ppMod)->enmState)
    407531        {
    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;
    409570        }
    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
    418583    if (!rc)
    419584    {
    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     */
    423703    return kldrDyldCopyError(rc, pszErr, cchErr);
    424704}
     
    543823{
    544824    /*
    545      * Load all dependant modules.
     825     * Load all prerequisite modules.
    546826     */
    547827    PKLDRMOD pCur;
     
    594874#endif
    595875
     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 */
     883static 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
    596999/**
    5971000 * Starts loading a new module and its dependencies.
    598  */
    599 static void kldrDyldStartLoading(void)
     1001 * @returns Where the new stack frame starts.
     1002 */
     1003static uint32_t kldrDyldStackNewFrame(void)
    6001004{
    6011005#ifdef KLDRDYLD_STRICT
     
    6101014    }
    6111015#endif
    612 }
    613 
    614 
    615 /**
    616  * Records the loading of the module.
     1016    return g_cStackMods;
     1017}
     1018
     1019
     1020/**
     1021 * Records the module.
    6171022 *
    6181023 * @return 0 on success, KLDR_ERR_NO_MEMORY if we can't expand the table.
    6191024 * @param   pMod        The module to record.
    6201025 */
    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 
     1026int 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 */
     1060static 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 */
     1073static 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}
    6421194
    6431195
  • trunk/kLdr/kLdrDyldMod.c

    r2835 r2837  
    3535
    3636
     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
    3748
    3849
    3950
     51
     52void kldrDyldModUnloadPrerequisites(PKLDRDYLDMOD pMod)
     53{
     54
     55}
     56
     57
     58void 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  
    7777    /** The module been mapped.
    7878     * Prev state: OPEN
    79      * Next state: LOADED_DEPS, DESTROYED
     79     * Next state: LOADED_PREREQUISITES, DESTROYED
    8080     */
    8181    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
    8490     * Next state: FIXED_UP, DESTROYED
    8591     */
    86     KLDRSTATE_LOADED_DEPS,
     92    KLDRSTATE_LOADED_PREREQUISITES,
    8793    /** Fixups has been applied.
    88      * Prev state: LOADED_DEPS
     94     * Prev state: LOADED_PREREQUISITES
    8995     * Next state: PENDING_INIT, DESTROYED
    9096     */
     
    124130     * (The loader can still be in a re-entrant mode.)
    125131     * Prev state: TERMINATING, INITIALIZING, PENDING_INITIALIZATION
    126      * Next state: GC, RELOADING
     132     * Next state: GC, RELOADED
    127133     */
    128134    KLDRSTATE_PENDING_GC,
    129135    /** Being garbage collected.
    130      * (The loader can still be in a re-entrant mode.)
    131136     * 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
    132142     * Next state: DESTROYED
    133143     */
    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,
    141145    /** The module has been destroyed and is no longer valid.
    142      * Prev state: GC
     146     * Prev state: GC, PENDING_DESTROY
    143147     */
    144148    KLDRSTATE_DESTROYED,
     
    163167    /** The module handle. */
    164168    HKLDRMOD            hMod;
    165     /** The number of references. */
     169    /** The total number of references. */
    166170    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. */
    168174    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 has
    171      * been completed. An alternative to this would be to not add the cDynRefs until
    172      * the load operation has completed... */
    173     uint32_t            cDynRefsInProgress;
    174175    /** Set if this is the executable module.
    175176     * When clear, the module is a shared object or relocatable object. */
     
    180181    uint32_t            fBindable : 1;
    181182    /** 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;
    183188    /** The load list linkage. */
    184189    struct
     
    233238int kldrDyldModCreate(PKLDRRDR pRdr, PPKLDRDYLDMOD ppMod);
    234239int kldrDyldModDestroy(PKLDRDYLDMOD pMod);
    235 int kldrDyldModAddDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pModDep);
    236 int kldrDyldModRemoveDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pModDep);
     240int kldrDyldModAddRef(PKLDRDYLDMOD pMod);
     241void kldrDyldModDeref(PKLDRDYLDMOD pMod);
     242int kldrDyldModAddDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep);
     243void kldrDyldModRemoveDep(PKLDRDYLDMOD pMod, PKLDRDYLDMOD pDep);
    237244int kldrDyldModDynamicLoad(PKLDRDYLDMOD pMod);
    238245int kldrDyldModDynamicUnload(PKLDRDYLDMOD pMod);
     
    245252int kldrDyldModMap(PKLDRDYLDMOD pMod);
    246253int kldrDyldModUnmap(PKLDRDYLDMOD pMod);
    247 int kldrDyldModLoadDependencies(PKLDRDYLDMOD pMod);
     254int kldrDyldModLoadPrerequisites(PKLDRDYLDMOD pMod, const char *pszName, const char *pszDefPrefix, const char *pszDefSuffix,
     255                                 KLDRDYLDSEARCH enmSearch, unsigned fFlags);
     256int kldrDyldModCheckPrerequisites(PKLDRDYLDMOD pMod);
     257void kldrDyldModUnloadPrerequisites(PKLDRDYLDMOD pMod);
    248258int kldrDyldModFixup(PKLDRDYLDMOD pMod);
    249259int kldrDyldModCallInit(PKLDRDYLDMOD pMod);
    250 int kldrDyldModCallTerm(PKLDRDYLDMOD pMod);
     260void kldrDyldModCallTerm(PKLDRDYLDMOD pMod);
     261int kldrDyldModReload(PKLDRDYLDMOD pMod);
    251262int kldrDyldModAttachThread(PKLDRDYLDMOD pMod);
    252263int kldrDyldModDetachThread(PKLDRDYLDMOD pMod);
Note: See TracChangeset for help on using the changeset viewer.