Changeset 2830 for trunk/kLdr/kLdrHlp.c


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

Page aligned object allocation.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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)
Note: See TracChangeset for help on using the changeset viewer.