VirtualBox

Changeset 99960 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
May 24, 2023 9:55:50 PM (19 months ago)
Author:
vboxsync
Message:

IPRT/sg: Corrected RTSgBufIsAtEnd and made the code deal with (skip) empty segments. Added a testcase (incomplete).

Location:
trunk/src/VBox/Runtime
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/misc/sg.cpp

    r98103 r99960  
    4545
    4646
     47/**
     48 * Gets the next continuous block of buffer data (up to @a *pcbData bytes) and
     49 * advances the buffer position past it.
     50 */
    4751static void *rtSgBufGet(PRTSGBUF pSgBuf, size_t *pcbData)
    4852{
    49     size_t cbData;
    50     void *pvBuf;
    51 
    52     /* Check that the S/G buffer has memory left. */
    53     if (RT_UNLIKELY(   pSgBuf->idxSeg == pSgBuf->cSegs
    54                     && !pSgBuf->cbSegLeft))
    55     {
    56         *pcbData = 0;
    57         return NULL;
    58     }
     53    /*
     54     * Check that the S/G buffer has memory left (!RTSgIsEnd(pSgBuf)).
     55     */
     56    unsigned const idxSeg = pSgBuf->idxSeg;
     57    unsigned const cSegs  = pSgBuf->cSegs;
     58    if (RT_LIKELY(   idxSeg < cSegs
     59                  && (   pSgBuf->cbSegLeft > 0 /* paranoia, this condition shouldn't occur. */
     60                      || idxSeg + 1 < cSegs)))
     61    {
     62        /*
     63         * Grab the requested segment chunk.
     64         */
     65        void * const pvBuf     = pSgBuf->pvSegCur;
     66        size_t const cbSegLeft = pSgBuf->cbSegLeft;
     67        size_t const cbData    = RT_MIN(*pcbData, cbSegLeft);
    5968
    6069#ifndef RDESKTOP
    61     AssertMsg(      pSgBuf->cbSegLeft <= 128 * _1M
    62               &&    (uintptr_t)pSgBuf->pvSegCur                     >= (uintptr_t)pSgBuf->paSegs[pSgBuf->idxSeg].pvSeg
    63               &&    (uintptr_t)pSgBuf->pvSegCur + pSgBuf->cbSegLeft <= (uintptr_t)pSgBuf->paSegs[pSgBuf->idxSeg].pvSeg + pSgBuf->paSegs[pSgBuf->idxSeg].cbSeg,
    64               ("pSgBuf->idxSeg=%d pSgBuf->cSegs=%d pSgBuf->pvSegCur=%p pSgBuf->cbSegLeft=%zd pSgBuf->paSegs[%d].pvSeg=%p pSgBuf->paSegs[%d].cbSeg=%zd\n",
    65                pSgBuf->idxSeg, pSgBuf->cSegs, pSgBuf->pvSegCur, pSgBuf->cbSegLeft, pSgBuf->idxSeg, pSgBuf->paSegs[pSgBuf->idxSeg].pvSeg, pSgBuf->idxSeg,
    66                pSgBuf->paSegs[pSgBuf->idxSeg].cbSeg));
     70        AssertMsg(   pSgBuf->cbSegLeft <= 128 * _1M
     71                  && (uintptr_t)pSgBuf->pvSegCur             >= (uintptr_t)pSgBuf->paSegs[pSgBuf->idxSeg].pvSeg
     72                  && (uintptr_t)pSgBuf->pvSegCur + cbSegLeft <= (uintptr_t)pSgBuf->paSegs[pSgBuf->idxSeg].pvSeg + pSgBuf->paSegs[pSgBuf->idxSeg].cbSeg,
     73                  ("pSgBuf->idxSeg=%d pSgBuf->cSegs=%d pSgBuf->pvSegCur=%p cbSegLeft=%zd pSgBuf->paSegs[%d].pvSeg=%p pSgBuf->paSegs[%d].cbSeg=%zd\n",
     74                   pSgBuf->idxSeg, pSgBuf->cSegs, pSgBuf->pvSegCur, cbSegLeft, pSgBuf->idxSeg, pSgBuf->paSegs[pSgBuf->idxSeg].pvSeg, pSgBuf->idxSeg,
     75                   pSgBuf->paSegs[pSgBuf->idxSeg].cbSeg));
    6776#endif
    6877
    69     cbData = RT_MIN(*pcbData, pSgBuf->cbSegLeft);
    70     pvBuf  = pSgBuf->pvSegCur;
    71     pSgBuf->cbSegLeft -= cbData;
    72 
    73     /* Advance to the next segment if required. */
    74     if (!pSgBuf->cbSegLeft)
    75     {
    76         pSgBuf->idxSeg++;
    77 
    78         if (pSgBuf->idxSeg < pSgBuf->cSegs)
     78        /*
     79         * Advance ...
     80         */
     81        if (cbSegLeft == cbData)
    7982        {
    80             pSgBuf->pvSegCur  = pSgBuf->paSegs[pSgBuf->idxSeg].pvSeg;
    81             pSgBuf->cbSegLeft = pSgBuf->paSegs[pSgBuf->idxSeg].cbSeg;
     83            *pcbData = cbData;
     84
     85            /* ... to the next segment. */
     86            unsigned idxSegNew = idxSeg + 1;
     87            if (idxSegNew < pSgBuf->cSegs)
     88            {
     89                do
     90                {
     91                    PCRTSGSEG const pNewSeg = &pSgBuf->paSegs[idxSegNew];
     92                    if (pNewSeg->cbSeg > 0)
     93                    {
     94                        pSgBuf->idxSeg    = idxSegNew;
     95                        pSgBuf->cbSegLeft = pNewSeg->cbSeg;
     96                        pSgBuf->pvSegCur  = pNewSeg->pvSeg;
     97                        return pvBuf;
     98                    }
     99                    /* Empty segment, skip it. */
     100                    idxSegNew++;
     101                } while (idxSegNew < pSgBuf->cSegs);
     102            }
     103            pSgBuf->idxSeg    = idxSegNew;
     104            pSgBuf->cbSegLeft = 0;
     105            pSgBuf->pvSegCur  = NULL;
    82106        }
    83 
    84         *pcbData = cbData;
    85     }
    86     else
    87         pSgBuf->pvSegCur = (uint8_t *)pSgBuf->pvSegCur + cbData;
    88 
    89     return pvBuf;
     107        else
     108        {
     109            /* ... within the current segment. */
     110            Assert(*pcbData == cbData);
     111            pSgBuf->cbSegLeft = cbSegLeft - cbData;
     112            pSgBuf->pvSegCur  = (uint8_t *)pvBuf + cbData;
     113        }
     114
     115        return pvBuf;
     116    }
     117
     118    Assert(pSgBuf->cbSegLeft == 0);
     119    *pcbData = 0;
     120    return NULL;
    90121}
    91122
     
    208239        Assert(cbTmp == cbThisCmp);
    209240
    210         int rc = memcmp(pvBuf1, pvBuf2, cbThisCmp);
    211         if (rc)
    212             return rc;
     241        int iDiff = memcmp(pvBuf1, pvBuf2, cbThisCmp);
     242        if (iDiff)
     243            return iDiff;
    213244
    214245        cbLeft -= cbThisCmp;
     
    284315
    285316
    286 RTDECL(size_t) RTSgBufSet(PRTSGBUF pSgBuf, uint8_t ubFill, size_t cbSet)
    287 {
    288     AssertPtrReturn(pSgBuf, 0);
    289 
    290     size_t cbLeft = cbSet;
     317RTDECL(size_t) RTSgBufSet(PRTSGBUF pSgBuf, uint8_t bFill, size_t cbToSet)
     318{
     319    AssertPtrReturn(pSgBuf, 0);
     320
     321    size_t cbLeft = cbToSet;
    291322
    292323    while (cbLeft)
     
    294325        size_t cbThisSet = cbLeft;
    295326        void *pvBuf = rtSgBufGet(pSgBuf, &cbThisSet);
    296 
    297         if (!cbThisSet)
    298             break;
    299 
    300         memset(pvBuf, ubFill, cbThisSet);
     327        if (!pvBuf)
     328            break;
     329
     330        memset(pvBuf, bFill, cbThisSet);
    301331
    302332        cbLeft -= cbThisSet;
    303333    }
    304334
    305     return cbSet - cbLeft;
     335    return cbToSet - cbLeft;
    306336}
    307337
     
    317347    {
    318348        size_t cbThisCopy = cbLeft;
    319         void *pvSrc = rtSgBufGet(pSgBuf, &cbThisCopy);
    320 
    321         if (!cbThisCopy)
     349        void * const pvSrc = rtSgBufGet(pSgBuf, &cbThisCopy);
     350        if (!pvSrc)
    322351            break;
    323352
    324353        memcpy(pvBuf, pvSrc, cbThisCopy);
    325354
     355        pvBuf = (void *)((uintptr_t)pvBuf + cbThisCopy);
    326356        cbLeft -= cbThisCopy;
    327         pvBuf = (void *)((uintptr_t)pvBuf + cbThisCopy);
    328357    }
    329358
     
    342371    {
    343372        size_t cbThisCopy = cbLeft;
    344         void *pvDst = rtSgBufGet(pSgBuf, &cbThisCopy);
    345 
    346         if (!cbThisCopy)
     373        void * const pvDst = rtSgBufGet(pSgBuf, &cbThisCopy);
     374        if (!pvDst)
    347375            break;
    348376
    349377        memcpy(pvDst, pvBuf, cbThisCopy);
    350378
     379        pvBuf = (const void *)((uintptr_t)pvBuf + cbThisCopy);
    351380        cbLeft -= cbThisCopy;
    352         pvBuf = (const void *)((uintptr_t)pvBuf + cbThisCopy);
    353381    }
    354382
     
    367395    {
    368396        size_t cbThisCopy = cbLeft;
    369         void *pvSrc = rtSgBufGet(pSgBuf, &cbThisCopy);
    370 
    371         if (!cbThisCopy)
     397        void * const pvSrc = rtSgBufGet(pSgBuf, &cbThisCopy);
     398        if (!pvSrc)
    372399            break;
    373400
     
    392419    {
    393420        size_t cbThisCopy = cbLeft;
    394         void *pvDst = rtSgBufGet(pSgBuf, &cbThisCopy);
    395 
    396         if (!cbThisCopy)
     421        void * const pvDst = rtSgBufGet(pSgBuf, &cbThisCopy);
     422        if (!pvDst)
    397423            break;
    398424
     
    412438
    413439    size_t cbLeft = cbAdvance;
     440
    414441    while (cbLeft)
    415442    {
    416443        size_t cbThisAdvance = cbLeft;
    417         rtSgBufGet(pSgBuf, &cbThisAdvance);
    418         if (!cbThisAdvance)
     444        if (!rtSgBufGet(pSgBuf, &cbThisAdvance))
    419445            break;
    420446
     
    426452
    427453
    428 RTDECL(size_t) RTSgBufSegArrayCreate(PRTSGBUF pSgBuf, PRTSGSEG paSeg, unsigned *pcSeg, size_t cbData)
    429 {
    430     AssertPtrReturn(pSgBuf, 0);
    431     AssertPtrReturn(pcSeg, 0);
    432 
    433     unsigned cSeg = 0;
    434     size_t   cb = 0;
     454RTDECL(size_t) RTSgBufSegArrayCreate(PRTSGBUF pSgBuf, PRTSGSEG paSeg, unsigned *pcSegs, size_t cbData)
     455{
     456    AssertPtrReturn(pSgBuf, 0);
     457    AssertPtrReturn(pcSegs, 0);
     458
     459    unsigned cSegs = 0;
     460    size_t   cbRet = 0;
    435461
    436462    if (!paSeg)
     
    439465        {
    440466            size_t idx = pSgBuf->idxSeg;
    441             cSeg = 1;
    442 
    443             cb     += RT_MIN(pSgBuf->cbSegLeft, cbData);
    444             cbData -= RT_MIN(pSgBuf->cbSegLeft, cbData);
     467
     468            cbRet   = RT_MIN(pSgBuf->cbSegLeft, cbData);
     469            cSegs   = cbRet != 0;
     470            cbData -= cbRet;
    445471
    446472            while (   cbData
     
    448474            {
    449475                idx++;
    450                 cSeg++;
    451                 cb     += RT_MIN(pSgBuf->paSegs[idx].cbSeg, cbData);
    452                 cbData -= RT_MIN(pSgBuf->paSegs[idx].cbSeg, cbData);
     476                size_t cbThisSeg = RT_MIN(pSgBuf->paSegs[idx].cbSeg, cbData);
     477                if (cbThisSeg)
     478                {
     479                    cbRet  += cbThisSeg;
     480                    cbData -= cbThisSeg;
     481                    cSegs++;
     482                }
    453483            }
    454484        }
     
    457487    {
    458488        while (   cbData
    459                && cSeg < *pcSeg)
     489               && cSegs < *pcSegs)
    460490        {
    461             size_t  cbThisSeg = cbData;
    462             void *pvSeg = rtSgBufGet(pSgBuf, &cbThisSeg);
    463 
    464             if (!cbThisSeg)
    465             {
    466                 Assert(!pvSeg);
     491            size_t cbThisSeg = cbData;
     492            void * const pvSeg = rtSgBufGet(pSgBuf, &cbThisSeg);
     493            if (!pvSeg)
    467494                break;
    468             }
    469495
    470496            AssertMsg(cbThisSeg <= cbData, ("Impossible!\n"));
    471497
    472             paSeg[cSeg].cbSeg = cbThisSeg;
    473             paSeg[cSeg].pvSeg = pvSeg;
    474             cSeg++;
     498            paSeg[cSegs].cbSeg = cbThisSeg;
     499            paSeg[cSegs].pvSeg = pvSeg;
     500            cSegs++;
    475501            cbData -= cbThisSeg;
    476             cb     += cbThisSeg;
     502            cbRet  += cbThisSeg;
    477503        }
    478504    }
    479505
    480     *pcSeg = cSeg;
    481 
    482     return cb;
     506    *pcSegs = cSegs;
     507
     508    return cbRet;
    483509}
    484510
     
    494520    {
    495521        size_t cbThisCheck = cbLeft;
    496         void *pvBuf = rtSgBufGet(&SgBufTmp, &cbThisCheck);
    497         if (!cbThisCheck)
    498             break;
    499         fIsZero = ASMMemIsZero(pvBuf, cbThisCheck);
    500         if (!fIsZero)
    501             break;
    502         cbLeft -= cbThisCheck;
     522        void * const pvBuf = rtSgBufGet(&SgBufTmp, &cbThisCheck);
     523        if (!pvBuf)
     524            break;
     525        if (cbThisCheck > 0)
     526        {
     527            fIsZero = ASMMemIsZero(pvBuf, cbThisCheck);
     528            if (!fIsZero)
     529                break;
     530            cbLeft -= cbThisCheck;
     531        }
    503532    }
    504533
  • trunk/src/VBox/Runtime/testcase/Makefile.kmk

    r99801 r99960  
    142142        tstRTSemRW \
    143143        tstRTSemXRoads \
     144        tstRTSg \
    144145        tstRTSort \
    145146        tstRTStrAlloc \
     
    830831 tstRTSemXRoads_SOURCES = tstRTSemXRoads.cpp
    831832
     833 tstRTSg_TEMPLATE = VBoxR3TstExe
     834 tstRTSg_SOURCES = tstRTSg.cpp
     835
    832836 tstRTSort_TEMPLATE = VBoxR3TstExe
    833837 tstRTSort_SOURCES = tstRTSort.cpp
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette