Changeset 2830


Ignore:
Timestamp:
Oct 23, 2006, 10:53:11 PM (19 years ago)
Author:
bird
Message:

Page aligned object allocation.

Location:
trunk/kLdr
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/kLdr/kLdr.c

    r2826 r2830  
    4949#include "kLdrHlp.h"
    5050
    51 #if 0
    52 /*******************************************************************************
    53 *   Global Variables                                                           *
    54 *******************************************************************************/
    55 /** Pointer to the head module (the executable).
    56  * (This is exported, so no prefix.) */
    57 PKLDRMOD        kLdrModuleHead = NULL;
    58 /** Pointer to the tail module.
    59  * (This is exported, so no prefix.) */
    60 PKLDRMOD        kLdrModuleTail = NULL;
    61 /** The Library search path. */
    62 char            kLdrLibraryPath[4096];
    63 /** The executable flags. */
    64 uint32_t        kLdrFlags;
    65 /** Bootstrap stack and temporary space. */
    66 char            abStack[8192];
    67 /** Set if we've initialized the loader. */
    68 int             fInitialized = 0;
    69 
    7051
    7152/*******************************************************************************
    72 *   Internal Functions                                                         *
     53*   Header Files                                                               *
    7354*******************************************************************************/
    74 static int kldrInit(void);
    75 static int kldrTerm(void);
    76 
    77 
    78 /**
    79  * Initialize the loader.
     55/** Flag indicating whether we've initialized the loader or not.
     56 *
     57 * 0 if not initialized.
     58 * -1 if we're initializing or terminating.
     59 * 1 if we've successfully initialized it.
     60 * -2 if initialization failed.
    8061 */
    81 int kldrInit(void)
    82 {
    83     if (fInitialized)
    84         return 0;
    85     /** @todo */
    86     return 0;
    87 }
    88 
    89 
    90 
    91 void kldrLoadExe(PKLDREXEARGS pArgs)
    92 {
    93     /*
    94      * Copy the arguments into the globals and do load init.
    95      */
    96     kLdrFlags = pArgs->fFlags;
    97     kLdrMemCopy(kLdrLibraryPath, pArgs->szLibPath, KLDR_MIN(sizeof(pArgs->szLibPath), sizeof(kLdrLibraryPath)));
    98     int rc = kldrInit();
    99     if (rc)
    100         kldrFailure(rc, "kLdr: Init failure, rc=%d\n", rc);
    101 
    102     /*
    103      * Open the executable module.
    104      */
    105     PKLDRMOD pExe;
    106     kldrOpenExe(pArgs->szExecutable, &pExe);
    107 
    108     /* Map the segments. */
    109     kldrModMapSegments(pExe);
    110 
    111     /*
    112      * This is the point where we switch to the executable
    113      * stack, allocating it if necessary.
    114      */
    115     void *pvBottom;
    116     kldrModSetupStack(pExe, &pvBottom);
    117     kldrLoadExecSwitchStack(pvBottom);
    118 }
    119 
    120 
    121 void kldrLoadExeOnNewStack(void)
    122 {
    123     /*
    124      * Load all dependant modules.
    125      */
    126     PKLDRMOD pCur;
    127     do  for (pCur = kLdrModuleHead; pCur; pCur = pCur->pNext)
    128         {
    129             if (pCur->enmState >= KLDRSTATE_DEPS)
    130                 continue;
    131             kldrModLoadDeps(pCur);
    132         }
    133     while (pCur);
    134 
    135     /*
    136      * Do fixups (FIFO).
    137      */
    138     for (pCur = kLdrModuleHead; pCur; pCur = pCur->pNext)
    139     {
    140         if (pCur->enmState >= KLDRSTATE_FIXED)
    141             continue;
    142         kldrModFixup(pCur, 0);
    143     }
    144 
    145     /*
    146      * Do module initialization.
    147      */
    148     for (pCur = kLdrModuleTail; pCur != kLdrModuleTail; pCur = pCur->pPrev)
    149     {
    150         if (pCur->enmState >= KLDRSTATE_INITED)
    151             continue;
    152         kldrModCallInit(pCur);
    153     }
    154 
    155     /*
    156      * Get the executable start address and commit the work that's been done.
    157      */
    158     void *pvEntry;
    159     kldrModGetExeEntry(&pvEntry);
    160 
    161     for (pCur = kLdrModuleHead; pCur; pCur = pCur->pNext)
    162         if (pCur->enmState == KLDRSTATE_INITED)
    163             pCur->enmState = KLDRSTATE_LOADED;
    164 
    165     kldrSemRelease();
    166 
    167     /*
    168      * We're now ready for starting the executable code.
    169      */
    170     kldrOSStartExe(pLdrModuleHead, pvEntry);
    171 }
    172 
    173 
    174 int kLdrLoadDll(const char *pszFilename, unsigned fFlags, void *pvmod)
    175 {
    176 
    177     return -1;
    178 }
    179 
     62static int volatile g_fInitialized;
    18063
    18164
    18265
    18366/**
    184  * Panic / failure
    185  *
    186  * @returns rc if we're in a position where we can return.
    187  * @param   rc              Return code.
    188  * @param   pszFormat       Message string. Limited fprintf like formatted.
    189  * @param   ...             Message string arguments.
     67 * Initializes the loader.
     68 * @returns 0 on success, non-zero OS status code on failure.
    19069 */
    191 int kldrFailure(int rc, const char *pszFormat, ...)
     70int kldrInit(void)
    19271{
    193     kldrExit(1);
     72    int rc;
     73
     74    /* check we're already good. */
     75    if (g_fInitialized == 1)
     76        return 0;
     77
     78    /* a tiny serialization effort. */
     79    for (;;)
     80    {
     81        if (g_fInitialized == 1)
     82            return 0;
     83        if (g_fInitialized == -2)
     84            return -1;
     85        /** @todo atomic test and set if we care. */
     86        if (g_fInitialized == 0)
     87        {
     88            g_fInitialized = -1;
     89            break;
     90        }
     91        kldrHlpSleep(1);
     92    }
     93
     94    /*
     95     * Do the initialization.
     96     */
     97    rc = kldrHlpHeapInit();
     98    if (!rc)
     99    {
     100        rc = kldrHlpSemInit();
     101        if (!rc)
     102        {
     103            g_fInitialized = 1;
     104            return 0;
     105        }
     106        kldrHlpHeapTerm();
     107    }
     108    g_fInitialized = -2;
    194109    return rc;
    195110}
    196111
    197 #endif
     112
     113/**
     114 * Terminates the loader.
     115 */
     116void kldrTerm(void)
     117{
     118    /* can't terminate unless it's initialized. */
     119    if (g_fInitialized != 1)
     120        return;
     121    g_fInitialized = -1;
     122
     123    /*
     124     * Do the termination.
     125     */
     126    kldrHlpSemTerm();
     127    kldrHlpHeapTerm();
     128
     129    /* done */
     130    g_fInitialized = 0;
     131}
     132
  • trunk/kLdr/kLdr.h

    r2829 r2830  
    6868    KLDRPROT_EXECUTE,
    6969    /** Execute & read. */
    70     KLDRPROT_EXECUTE_READONLY,
     70    KLDRPROT_EXECUTE_READ,
    7171    /** Execute, read & write. */
    7272    KLDRPROT_EXECUTE_READWRITE,
  • trunk/kLdr/kLdrHlp.c

    r2828 r2830  
    4141#include <kLdr.h>
    4242#include "kLdrHlp.h"
     43
     44
     45/*******************************************************************************
     46*   Global Variables                                                           *
     47*******************************************************************************/
     48#ifdef __OS2__
     49/** The loader sempahore. */
     50static HMTX             g_hmtx;
     51/** The base of the stub object.
     52 * The OS/2 exe stub consists of a single data object. When allocating memory
     53 * for an executable, we'll have to reuse this.  */
     54static void            *g_pvStub = NULL;
     55/** The size of the stub object - 0 if no stub. */
     56static size_t           g_cbStub = 0;
     57
     58#elif defined(__WIN__)
     59/** The loader sempahore. */
     60static CRITICAL_SECTION g_CritSect;
     61/** The system info. */
     62static SYSTEM_INFO      g_SystemInfo;
     63#else
     64# error "port me"
     65#endif
     66
     67
     68/**
     69 * Initializes the loader semaphore.
     70 *
     71 * @returns 0 on success, non-zero OS status code on failure.
     72 */
     73int     kldrHlpSemInit(void)
     74{
     75#ifdef __OS2__
     76    APIRET rc;
     77    g_hmtx = NULLHANDLE;
     78    rc = DosCreateMutexSem(NULL, &g_hmtx, 0, FALSE);
     79    if (rc)
     80        return rc;
     81
     82#elif defined(__WIN__)
     83    InitializeCriticalSection(&g_CritSect);
     84
     85#else
     86# error "port me"
     87#endif
     88    return 0;
     89}
     90
     91
     92/**
     93 * Terminates the loader semaphore.
     94 */
     95void    kldrHlpSemTerm(void)
     96{
     97#ifdef __OS2__
     98    APIRET rc;
     99    HMTX hmtx = g_hmtx;
     100    g_hmtx = NULLHANDLE;
     101    rc = DosCloseMutexSem(hmtx);
     102    if (rc)
     103        return rc;
     104
     105#elif defined(__WIN__)
     106    DeleteCriticalSection(&g_CritSect);
     107
     108#else
     109# error "port me"
     110#endif
     111}
     112
     113
     114/**
     115 * Requests the loader sempahore ownership.
     116 * This can be done recursivly.
     117 *
     118 * @returns 0 on success, non-zero OS status code on failure.
     119 */
     120int     kldrHlpSemRequest(void)
     121{
     122#ifdef __OS2__
     123    APIRET rc = DosRequestMutexSem(g_hmtx, 5000);
     124    if (rc == ERROR_TIMEOUT || rc == ERROR_SEM_TIMEOUT || rc == ERROR_INTERRUPT)
     125    {
     126        unsigned i = 0;
     127        do
     128        {
     129            /** @todo check for deadlocks etc. */
     130            rc = DosRequestMutexSem(g_hmtx, 1000);
     131        } while (   (   rc == ERROR_TIMEOUT
     132                     || rc == ERROR_SEM_TIMEOUT
     133                     || rc == ERROR_INTERRUPT)
     134                 && i++ < 120);
     135    }
     136    return rc;
     137
     138#elif defined(__WIN__)
     139    EnterCriticalSection(&g_CritSect);
     140    return 0;
     141
     142#else
     143# error "port me"
     144#endif
     145}
     146
     147
     148/**
     149 * Releases the loader semaphore ownership.
     150 * The caller is responsible for making sure it's the semaphore owner!
     151 */
     152void    kldrHlpSemRelease(void)
     153{
     154#ifdef __OS2__
     155    APIRET rc = DosReleaseMutexSem(g_hmtx);
     156    kldrHlpAssert(!rc); (void)rc;
     157
     158#elif defined(__WIN__)
     159    LeaveCriticalSection(&g_CritSect);
     160
     161#else
     162# error "port me"
     163#endif
     164
     165}
     166
     167#ifdef __OS2__
     168static ULONG kldrHlpPageProtToNative(KLDRPROT enmProt)
     169{
     170    switch (enmProt)
     171    {
     172        case KLDRPROT_NOACCESS:             return PAG_EXECUTE | PAG_READ | PAG_WRITE;
     173        case KLDRPROT_READONLY:             return PAG_COMMIT | PAG_READ;
     174        case KLDRPROT_READWRITE:            return PAG_COMMIT | PAG_READ | PAG_WRITE;
     175        case KLDRPROT_EXECUTE:              return PAG_COMMIT | PAG_EXECUTE;
     176        case KLDRPROT_EXECUTE_READ:         return PAG_COMMIT | PAG_EXECUTE | PAG_READ;
     177        case KLDRPROT_EXECUTE_READWRITE:    return PAG_COMMIT | PAG_EXECUTE | PAG_READ | PAG_WRITE;
     178        default:
     179            kldrHlpAssert(0);
     180            return ~0U;
     181    }
     182}
     183#elif defined(__WIN__)
     184static DWORD kldrHlpPageProtToNative(KLDRPROT enmProt)
     185{
     186    switch (enmProt)
     187    {
     188        case KLDRPROT_NOACCESS:             return PAGE_NOACCESS;
     189        case KLDRPROT_READONLY:             return PAGE_READONLY;
     190        case KLDRPROT_READWRITE:            return PAGE_READWRITE;
     191        case KLDRPROT_EXECUTE:              return PAGE_EXECUTE;
     192        case KLDRPROT_EXECUTE_READ:         return PAGE_EXECUTE_READ;
     193        case KLDRPROT_EXECUTE_READWRITE:    return PAGE_EXECUTE_READWRITE;
     194        default:
     195            kldrHlpAssert(0);
     196            return ~0U;
     197    }
     198}
     199#endif
     200
     201
     202/**
     203 * Allocate a chunk of memory with page granularity.
     204 *
     205 * @returns 0 on success, non-zero OS status code on failure.
     206 * @param   ppv         Where to store the address of the allocated memory.
     207 *                      If fFixed is set, *ppv will on entry contain the desired address (page aligned).
     208 * @param   cb          Number of bytes. Page aligned.
     209 * @param   enmProt     The new protection. Copy-on-write is invalid.
     210 */
     211int     kldrHlpPageAlloc(void **ppv, size_t cb, KLDRPROT enmProt, unsigned fFixed)
     212{
     213#ifdef __OS2__
     214    APIRET  rc;
     215    ULONG   fFlags = kldrHlpPageProtToNative(enmProt);;
     216
     217    if (!fFixed)
     218    {
     219        /* simple */
     220        rc = DosAllocMem(ppv, cb, fFlags | OBJ_ANY);
     221        if (rc == ERROR_INVALID_PARAMETER)
     222            rc = DosAllocMem(ppv, cb, fFlags);
     223    }
     224    else
     225    {
     226        /* not so simple. */
     227        /** @todo I've got code for this in libc somewhere. */
     228    }
     229    if (!rc)
     230        return 0;
     231    kldrHlpAssert(0);
     232    return rc;
     233
     234#elif defined(__WIN__)
     235    int     rc;
     236    DWORD   fProt = kldrHlpPageProtToNative(enmProt);
     237
     238    if (!g_SystemInfo.dwPageSize)
     239        GetSystemInfo(&g_SystemInfo);
     240
     241    *ppv = VirtualAlloc(fFixed ? *ppv : NULL, cb, MEM_COMMIT, fProt);
     242    if (*ppv == NULL)
     243    {
     244        rc = GetLastError();
     245        kldrHlpAssert(0);
     246    }
     247    return rc;
     248
     249#else
     250# error "port me"
     251#endif
     252}
     253
     254
     255/**
     256 * Change the protection of one or more pages in an allocation.
     257 *
     258 * (This will of course only work correctly on memory allocated by kldrHlpPageAlloc().)
     259 *
     260 * @returns 0 on success, non-zero OS status code on failure.
     261 * @param   pv          First page. Page aligned.
     262 * @param   cb          Number of bytes. Page aligned.
     263 * @param   enmProt     The new protection. Copy-on-write is invalid.
     264 */
     265int     kldrHlpPageProtect(void *pv, size_t cb, KLDRPROT enmProt)
     266{
     267#ifdef __OS2__
     268    APIRET      rc;
     269    uintptr_t   offStub;
     270    ULONG       fFlags = kldrHlpPageProtToNative(enmProt);;
     271
     272    /*
     273     * The non-stub pages.
     274     */
     275    rc = DosSetMem(pv, cb, fFlags);
     276    if (rc && fFlags != PAG_DECOMMIT)
     277        rc = DosSetMem(pv, cb, fFlags | PAG_COMMIT);
     278    if (rc)
     279    {
     280        /* Try page by page. */
     281        while (cb > 0)
     282        {
     283            rc = DosSetMem(pv, 0x1000, fFlags);
     284            if (rc && fFlags != PAG_DECOMMIT)
     285                rc = DosSetMem(pv, 0x1000, fFlags | PAG_COMMIT);
     286            if (rc)
     287                return rc;
     288            pv = (void *)((uintptr_t)pv + 0x1000);
     289            cb -= 0x1000;
     290        }
     291    }
     292    kldrHlpAssert(!rc);
     293    return rc;
     294
     295#elif defined(__WIN__)
     296    DWORD fOldProt = 0;
     297    DWORD fProt = kldrHlpPageProtToNative(enmProt);
     298    int rc = 0;
     299
     300    if (!VirtualProtect(pv, cb, fProt, &fOldProt))
     301    {
     302        rc = GetLastError();
     303        kldrHlpAssert(0);
     304    }
     305    return rc;
     306#else
     307# error "port me"
     308#endif
     309}
     310
     311
     312/**
     313 * Free memory allocated by kldrHlpPageAlloc().
     314 *
     315 * @returns 0 on success, non-zero OS status code on failure.
     316 * @param   pv          The address returned by kldrHlpPageAlloc().
     317 * @param   cb          The byte count requested from kldrHlpPageAlloc().
     318 */
     319int     kldrHlpPageFree(void *pv, size_t cb)
     320{
     321#ifdef __OS2__
     322    APIRET rc;
     323
     324    /*
     325     * Deal with any portion overlapping with the stub.
     326     */
     327    uintptr_t offStub = (uintptr_t)pv - (uintptr_t)g_pvStub;
     328    if (offStub < g_cbStub)
     329    {
     330        /* decommit the pages in the stub. */
     331        size_t cbSub = KLDR_MIN(g_cbStub - offStub, cb);
     332        rc = DosSetMem(pv, cbStub, PAG_DECOMMIT);
     333        if (rc)
     334        {
     335            /* Page by page, ignoring errors after the first success. */
     336            while (cbSub > 0)
     337            {
     338                if (!DosSetMem(pv, 0x1000, PAG_DECOMMIT))
     339                    rc = 0;
     340                pv = (void *)((uintptr_t)pv + 0x1000);
     341                cbSub -= 0x1000;
     342                cb -= 0x1000;
     343            }
     344            if (rc)
     345            {
     346                kldrHlpAssert(!rc);
     347                return rc;
     348            }
     349        }
     350        else
     351        {
     352            cb -= cbSub;
     353            if (!cb)
     354                return 0;
     355            pv = (void *)((uintptr_t)pv + cbSub);
     356        }
     357    }
     358
     359    /*
     360     * Free the object.
     361     */
     362    rc = DosFreeMem(pv);
     363    kldrHlpAssert(!rc);
     364    return rc;
     365
     366#elif defined(__WIN__)
     367    /*
     368     * Free the object.
     369     */
     370    int rc = 0;
     371    if (!VirtualFree(pv, 0 /*cb*/, MEM_RELEASE))
     372    {
     373        rc = GetLastError();
     374        kldrHlpAssert(0);
     375    }
     376    return rc;
     377
     378#else
     379# error "port me"
     380#endif
     381}
    43382
    44383
     
    137476}
    138477
     478
     479/**
     480 * Sleep for a number of milliseconds.
     481 * @param   cMillies    Number of milliseconds to sleep.
     482 */
     483void kldrHlpSleep(unsigned cMillies)
     484{
     485#ifdef __OS2__
     486    DosSleep(cMillies);
     487#elif defined(__WIN__)
     488    Sleep(cMillies);
     489#else
     490    usleep(cMillies * 1000);
     491#endif
     492}
     493
     494
    139495/** Internal worker for kldrHlpAssertMsg. */
    140496static void int2dec(char *pszLine, unsigned iLine)
  • trunk/kLdr/kLdrHlp.h

    r2828 r2830  
    112112
    113113
    114 int kldrSemInit(void);
    115 int kldrSemTerm(void);
    116 int kldrSemRequest(void);
    117 int kldrSemRelease(void);
    118 int kldrSemGlobalRequest(void);
    119 int kldrSemGlobalRelease(void);
     114int     kldrHlpSemInit(void);
     115void    kldrHlpSemTerm(void);
     116int     kldrHlpSemRequest(void);
     117void    kldrHlpSemRelease(void);
    120118
    121 int kldrPrivateAlloc(void *pv, size_t cb, unsigned fFlags, void **ppv);
    122 int kldrPrivateFree(void *pv, size_t cb);
    123 int kldrSharedAlloc(void *pv, size_t cb, unsigned fFlags, const char *pszFilename, void *File, void **ppv);
    124 int kldrSharedFree(void *pv, size_t cb);
     119int     kldrHlpPageAlloc(void **ppv, size_t cb, KLDRPROT enmProt, unsigned fFixed);
     120int     kldrHlpPageProtect(void *pv, size_t cb, KLDRPROT enmProt);
     121int     kldrHlpPageFree(void *pv, size_t cb);
    125122
    126123int     kldrHlpHeapInit(void);
     
    132129int     kldrHlpGetEnv(const char *pszVar, char *pszVal, size_t *pcchVal);
    133130void    kldrHlpExit(int rc);
     131void    kldrHlpSleep(unsigned cMillies);
    134132void    kldrHlpAssertMsg(const char *pszExpr, const char *pszFile, unsigned iLine, const char *pszFunction);
    135133
Note: See TracChangeset for help on using the changeset viewer.