VirtualBox

Changeset 45646 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Apr 19, 2013 1:48:09 PM (12 years ago)
Author:
vboxsync
Message:

Devices/AHCI: Offload work from EMT to a dedicated thread when using the async interface and make use of the SUPDrv event semaphore to get rid of certain R0/R3 context switches

Location:
trunk/src/VBox/Devices
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DevAHCI.cpp

    r45025 r45646  
    4343#include <VBox/vmm/pdmthread.h>
    4444#include <VBox/vmm/pdmcritsect.h>
     45#include <VBox/sup.h>
    4546#include <VBox/scsi.h>
    4647#include <iprt/assert.h>
     
    450451    /** Flag whether the port is in redo task mode. */
    451452    volatile bool                   fRedo;
     453    /** Flag whether the worker thread is sleeping. */
     454    volatile bool                   fWrkThreadSleeping;
    452455
    453456    /** Number of total sectors. */
     
    516519    /** Async IO Thread. */
    517520    R3PTRTYPE(PPDMTHREAD)           pAsyncIOThread;
    518     /** Request semaphore. */
    519     RTSEMEVENT                      AsyncIORequestSem;
    520521    /**
    521522     * Array of cached tasks. The tag number is the index value.
     
    527528    /** The current tracklist of the loaded medium if passthrough is used. */
    528529    R3PTRTYPE(PTRACKLIST)           pTrackList;
     530
     531    /** The event semaphore the processing thread waits on. */
     532    SUPSEMEVENT                     hEvtProcess;
    529533
    530534    /** Release statistics: number of DMA commands. */
     
    694698    volatile bool                   f8ByteMMIO4BytesWrittenSuccessfully;
    695699
     700    /** The support driver session handle. */
     701    R3R0PTRTYPE(PSUPDRVSESSION)     pSupDrvSession;
    696702} AHCI;
    697703/** Pointer to the state of an AHCI device. */
     
    10641070
    10651071        ASMAtomicOrU32(&pAhciPort->u32TasksNew, u32Value);
    1066         u32Tasks = ASMAtomicReadU32(&pAhciPort->u32TasksNew);
    10671072
    10681073        /* Send a notification to R3 if u32TasksNew was before our write. */
    1069         if (!(u32Tasks ^ u32Value))
    1070         {
     1074        if (ASMAtomicReadBool(&pAhciPort->fWrkThreadSleeping))
     1075        {
     1076#ifdef IN_RC
    10711077            PDEVPORTNOTIFIERQUEUEITEM pItem = (PDEVPORTNOTIFIERQUEUEITEM)PDMQueueAlloc(ahci->CTX_SUFF(pNotifierQueue));
    10721078            AssertMsg(VALID_PTR(pItem), ("Allocating item for queue failed\n"));
     
    10741080            pItem->iPort = pAhciPort->iLUN;
    10751081            PDMQueueInsert(ahci->CTX_SUFF(pNotifierQueue), (PPDMQUEUEITEMCORE)pItem);
     1082#else
     1083            LogFlowFunc(("Singal event semaphore\n"));
     1084            int rc = SUPSemEventSignal(ahci->pSupDrvSession, pAhciPort->hEvtProcess);
     1085            AssertRC(rc);
     1086#endif
    10761087        }
    10771088    }
     
    24032414    /* We use the assigned size here, because we currently only support page aligned MMIO ranges. */
    24042415    /** @todo change this to IOMMMIO_FLAGS_WRITE_ONLY_DWORD once EM/IOM starts
    2405      * handling 2nd DWORD failures on split accesses correctly. */ 
     2416     * handling 2nd DWORD failures on split accesses correctly. */
    24062417    rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,
    24072418                               IOMMMIO_FLAGS_READ_DWORD | IOMMMIO_FLAGS_WRITE_ONLY_DWORD_QWORD,
     
    56085619    AHCITXSTATE enmTxState = AHCITXSTATE_INVALID;
    56095620
     5621    LogFlowFunc(("pAhciPort=%p pAhciReq=%p rcReq=%d fFreeReq=%RTbool\n",
     5622                 pAhciPort, pAhciReq, rcReq, fFreeReq));
     5623
    56105624    ASMAtomicReadSize(&pAhciReq->enmTxState, &enmTxState);
    56115625    VBOXDD_AHCI_REQ_COMPLETED(pAhciReq, rcReq, enmTxState, pAhciReq->uOffset, pAhciReq->cbTransfer);
     
    62076221{
    62086222    PDEVPORTNOTIFIERQUEUEITEM pNotifierItem = (PDEVPORTNOTIFIERQUEUEITEM)pItem;
    6209     PAHCI                     pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
    6210     PAHCIPort                 pAhciPort = &pAhci->ahciPort[pNotifierItem->iPort];
     6223    PAHCI                     pThis = PDMINS_2_DATA(pDevIns, PAHCI);
     6224    PAHCIPort                 pAhciPort = &pThis->ahciPort[pNotifierItem->iPort];
    62116225    int                       rc = VINF_SUCCESS;
    62126226
    6213     if (!pAhciPort->fAsyncInterface)
    6214     {
    6215         ahciLog(("%s: Got notification from GC\n", __FUNCTION__));
    6216         /* Notify the async IO thread. */
    6217         rc = RTSemEventSignal(pAhciPort->AsyncIORequestSem);
    6218         AssertRC(rc);
    6219     }
    6220     else
     6227    ahciLog(("%s: Got notification from GC\n", __FUNCTION__));
     6228    /* Notify the async IO thread. */
     6229    rc = SUPSemEventSignal(pThis->pSupDrvSession, pAhciPort->hEvtProcess);
     6230    AssertRC(rc);
     6231
     6232    return true;
     6233}
     6234
     6235/* The async IO thread for one port. */
     6236static DECLCALLBACK(int) ahciAsyncIOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
     6237{
     6238    PAHCIPort pAhciPort = (PAHCIPort)pThread->pvUser;
     6239    PAHCI     pAhci     = pAhciPort->CTX_SUFF(pAhci);
     6240    int rc = VINF_SUCCESS;
     6241    uint64_t u64StartTime = 0;
     6242    uint64_t u64StopTime  = 0;
     6243    uint32_t uIORequestsProcessed = 0;
     6244    uint32_t uIOsPerSec = 0;
     6245    uint32_t fTasksToProcess = 0;
     6246
     6247    ahciLog(("%s: Port %d entering async IO loop.\n", __FUNCTION__, pAhciPort->iLUN));
     6248
     6249    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
     6250        return VINF_SUCCESS;
     6251
     6252    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
    62216253    {
    62226254        unsigned idx = 0;
    6223         uint32_t u32Tasks = ASMAtomicXchgU32(&pAhciPort->u32TasksNew, 0);
    6224 
     6255        uint32_t u32Tasks = 0;
     6256
     6257        ASMAtomicWriteBool(&pAhciPort->fWrkThreadSleeping, true);
     6258        u32Tasks = ASMAtomicXchgU32(&pAhciPort->u32TasksNew, 0);
     6259        if (!u32Tasks)
     6260        {
     6261            Assert(ASMAtomicReadBool(&pAhciPort->fWrkThreadSleeping));
     6262            rc = SUPSemEventWaitNoResume(pAhci->pSupDrvSession, pAhciPort->hEvtProcess, RT_INDEFINITE_WAIT);
     6263            AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_INTERRUPTED, ("%Rrc\n", rc), rc);
     6264            if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING))
     6265                break;
     6266            LogFlowFunc(("Woken up with rc=%Rrc\n", rc));
     6267            u32Tasks = ASMAtomicXchgU32(&pAhciPort->u32TasksNew, 0);
     6268        }
     6269
     6270        ASMAtomicWriteBool(&pAhciPort->fWrkThreadSleeping, false);
    62256271        idx = ASMBitFirstSetU32(u32Tasks);
    62266272        while (idx)
     
    62806326                    ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
    62816327                    AssertMsg(fXchg, ("Task is not active\n"));
    6282                     return true;
     6328                    break;
    62836329                }
    6284 
    6285                 if (pAhciPort->fResetDevice) /* The bit is not set and we are in a reset state. */
     6330                else if (pAhciPort->fResetDevice) /* The bit is not set and we are in a reset state. */
    62866331                {
    62876332                    ahciFinishStorageDeviceReset(pAhciPort, pAhciReq);
     
    62896334                    ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
    62906335                    AssertMsg(fXchg, ("Task is not active\n"));
    6291                     return true;
     6336                    break;
    62926337                }
    6293 
    6294                 /* We are not in a reset state update the control registers. */
    6295                 AssertMsgFailed(("%s: Update the control register\n", __FUNCTION__));
     6338                else /* We are not in a reset state update the control registers. */
     6339                    AssertMsgFailed(("%s: Update the control register\n", __FUNCTION__));
    62966340            }
    62976341            else
     
    63186362                    if (!(pAhciReq->fFlags & AHCI_REQ_OVERFLOW))
    63196363                    {
    6320                         VBOXDD_AHCI_REQ_SUBMIT(pAhciReq, enmTxDir, pAhciReq->uOffset, pAhciReq->cbTransfer);
    6321                         VBOXDD_AHCI_REQ_SUBMIT_TIMESTAMP(pAhciReq, pAhciReq->tsStart);
    6322                         if (enmTxDir == AHCITXDIR_FLUSH)
    6323                             rc = pAhciPort->pDrvBlockAsync->pfnStartFlush(pAhciPort->pDrvBlockAsync, pAhciReq);
    6324                         else if (enmTxDir == AHCITXDIR_TRIM)
     6364                        if (pAhciPort->fAsyncInterface)
    63256365                        {
    6326                             rc = ahciTrimRangesCreate(pAhciPort, pAhciReq);
    6327                             if (RT_SUCCESS(rc))
     6366                            VBOXDD_AHCI_REQ_SUBMIT(pAhciReq, enmTxDir, pAhciReq->uOffset, pAhciReq->cbTransfer);
     6367                            VBOXDD_AHCI_REQ_SUBMIT_TIMESTAMP(pAhciReq, pAhciReq->tsStart);
     6368                            if (enmTxDir == AHCITXDIR_FLUSH)
     6369                            {
     6370                                rc = pAhciPort->pDrvBlockAsync->pfnStartFlush(pAhciPort->pDrvBlockAsync,
     6371                                                                              pAhciReq);
     6372                            }
     6373                            else if (enmTxDir == AHCITXDIR_TRIM)
     6374                            {
     6375                                rc = ahciTrimRangesCreate(pAhciPort, pAhciReq);
     6376                                if (RT_SUCCESS(rc))
     6377                                {
     6378                                    pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
     6379                                    rc = pAhciPort->pDrvBlockAsync->pfnStartDiscard(pAhciPort->pDrvBlockAsync, pAhciReq->u.Trim.paRanges,
     6380                                                                                    pAhciReq->u.Trim.cRanges, pAhciReq);
     6381                                }
     6382                            }
     6383                            else if (enmTxDir == AHCITXDIR_READ)
     6384                            {
     6385                                pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
     6386                                rc = pAhciPort->pDrvBlockAsync->pfnStartRead(pAhciPort->pDrvBlockAsync, pAhciReq->uOffset,
     6387                                                                             &pAhciReq->u.Io.DataSeg, 1,
     6388                                                                             pAhciReq->cbTransfer,
     6389                                                                             pAhciReq);
     6390                            }
     6391                            else
    63286392                            {
    63296393                                pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
    6330                                 rc = pAhciPort->pDrvBlockAsync->pfnStartDiscard(pAhciPort->pDrvBlockAsync, pAhciReq->u.Trim.paRanges,
    6331                                                                                 pAhciReq->u.Trim.cRanges, pAhciReq);
     6394                                rc = pAhciPort->pDrvBlockAsync->pfnStartWrite(pAhciPort->pDrvBlockAsync, pAhciReq->uOffset,
     6395                                                                              &pAhciReq->u.Io.DataSeg, 1,
     6396                                                                              pAhciReq->cbTransfer,
     6397                                                                              pAhciReq);
    63326398                            }
    6333                         }
    6334                         else if (enmTxDir == AHCITXDIR_READ)
    6335                         {
    6336                             pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
    6337                             rc = pAhciPort->pDrvBlockAsync->pfnStartRead(pAhciPort->pDrvBlockAsync, pAhciReq->uOffset,
    6338                                                                          &pAhciReq->u.Io.DataSeg, 1,
    6339                                                                          pAhciReq->cbTransfer,
    6340                                                                          pAhciReq);
     6399                            if (rc == VINF_VD_ASYNC_IO_FINISHED)
     6400                                rc = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS, true);
     6401                            else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
     6402                                rc = ahciTransferComplete(pAhciPort, pAhciReq, rc, true);
    63416403                        }
    63426404                        else
    63436405                        {
    6344                             pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
    6345                             rc = pAhciPort->pDrvBlockAsync->pfnStartWrite(pAhciPort->pDrvBlockAsync, pAhciReq->uOffset,
    6346                                                                           &pAhciReq->u.Io.DataSeg, 1,
    6347                                                                           pAhciReq->cbTransfer,
    6348                                                                           pAhciReq);
     6406                            if (enmTxDir == AHCITXDIR_FLUSH)
     6407                                rc = pAhciPort->pDrvBlock->pfnFlush(pAhciPort->pDrvBlock);
     6408                            else if (enmTxDir == AHCITXDIR_TRIM)
     6409                            {
     6410                                rc = ahciTrimRangesCreate(pAhciPort, pAhciReq);
     6411                                if (RT_SUCCESS(rc))
     6412                                {
     6413                                    pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
     6414                                    rc = pAhciPort->pDrvBlock->pfnDiscard(pAhciPort->pDrvBlock, pAhciReq->u.Trim.paRanges,
     6415                                                                          pAhciReq->u.Trim.cRanges);
     6416                                    pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 0;
     6417                                }
     6418                            }
     6419                            else if (enmTxDir == AHCITXDIR_READ)
     6420                            {
     6421                                pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
     6422                                rc = pAhciPort->pDrvBlock->pfnRead(pAhciPort->pDrvBlock, pAhciReq->uOffset,
     6423                                                                   pAhciReq->u.Io.DataSeg.pvSeg,
     6424                                                                   pAhciReq->cbTransfer);
     6425                                pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 0;
     6426                            }
     6427                            else
     6428                            {
     6429                                pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
     6430                                rc = pAhciPort->pDrvBlock->pfnWrite(pAhciPort->pDrvBlock, pAhciReq->uOffset,
     6431                                                                    pAhciReq->u.Io.DataSeg.pvSeg,
     6432                                                                    pAhciReq->cbTransfer);
     6433                                pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 0;
     6434                            }
     6435                            rc = ahciTransferComplete(pAhciPort, pAhciReq, rc, true);
    63496436                        }
    6350                         if (rc == VINF_VD_ASYNC_IO_FINISHED)
    6351                             rc = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS, true);
    6352                         else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
    6353                             rc = ahciTransferComplete(pAhciPort, pAhciReq, rc, true);
    63546437                    }
    63556438                }
     
    63616444            idx = ASMBitFirstSetU32(u32Tasks);
    63626445        } /* while tasks available */
    6363     } /* fUseAsyncInterface */
    6364 
    6365     return true;
    6366 }
    6367 
    6368 /* The async IO thread for one port. */
    6369 static DECLCALLBACK(int) ahciAsyncIOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
    6370 {
    6371     PAHCIPort pAhciPort = (PAHCIPort)pThread->pvUser;
    6372     PAHCI     pAhci     = pAhciPort->CTX_SUFF(pAhci);
    6373     PAHCIREQ pAhciReq;
    6374     int rc = VINF_SUCCESS;
    6375     uint64_t u64StartTime = 0;
    6376     uint64_t u64StopTime  = 0;
    6377     uint32_t uIORequestsProcessed = 0;
    6378     uint32_t uIOsPerSec = 0;
    6379     uint32_t fTasksToProcess = 0;
    6380     unsigned idx = 0;
    6381 
    6382     ahciLog(("%s: Port %d entering async IO loop.\n", __FUNCTION__, pAhciPort->iLUN));
    6383 
    6384     if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
    6385         return VINF_SUCCESS;
    6386 
    6387     /* We use only one task structure. */
    6388     pAhciReq = (PAHCIREQ)RTMemAllocZ(sizeof(AHCIREQ));
    6389     if (!pAhciReq)
    6390     {
    6391         AssertMsgFailed(("Failed to allocate task state memory\n"));
    6392         return VERR_NO_MEMORY;
    6393     }
    6394 
    6395     pAhciReq->enmTxState = AHCITXSTATE_FREE;
    6396 
    6397     while (pThread->enmState == PDMTHREADSTATE_RUNNING)
    6398     {
    6399         /* New run to get number of I/O requests per second?. */
    6400         if (!u64StartTime)
    6401             u64StartTime = RTTimeMilliTS();
    6402 
    6403         ASMAtomicXchgBool(&pAhciPort->fAsyncIOThreadIdle, true);
    6404         if (pAhci->fSignalIdle)
    6405             PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
    6406 
    6407         rc = RTSemEventWait(pAhciPort->AsyncIORequestSem, 1000);
    6408         if (rc == VERR_TIMEOUT)
    6409         {
    6410             /* No I/O requests in-between. Reset statistics and wait again. */
    6411             pAhciPort->StatIORequestsPerSecond.c = 0;
    6412             rc = RTSemEventWait(pAhciPort->AsyncIORequestSem, RT_INDEFINITE_WAIT);
    6413         }
    6414 
    6415         if (RT_FAILURE(rc) || (pThread->enmState != PDMTHREADSTATE_RUNNING))
    6416             break;
    6417 
    6418         /* Go to sleep again if we are in redo mode. */
    6419         if (RT_UNLIKELY(pAhciPort->fRedo))
    6420             continue;
    6421 
    6422         AssertMsg(pAhciPort->pDrvBase, ("I/O thread without attached device?!\n"));
    6423 
    6424         ASMAtomicXchgBool(&pAhciPort->fAsyncIOThreadIdle, false);
    6425         fTasksToProcess = ASMAtomicXchgU32(&pAhciPort->u32TasksNew, 0);
    6426 
    6427         idx = ASMBitFirstSetU32(fTasksToProcess);
    6428 
    6429         /* Process commands. */
    6430         while (   idx
    6431                && RT_LIKELY(!pAhciPort->fPortReset))
    6432         {
    6433             bool fReqCanceled = false;
    6434             AHCITXDIR enmTxDir;
    6435 
    6436             idx--;
    6437             STAM_PROFILE_START(&pAhciPort->StatProfileProcessTime, a);
    6438 
    6439             pAhciReq->tsStart       = RTTimeMilliTS();
    6440             pAhciReq->uATARegStatus = 0;
    6441             pAhciReq->uATARegError  = 0;
    6442             pAhciReq->fFlags        = 0;
    6443             pAhciReq->uTag          = idx;
    6444             AssertMsg(pAhciReq->uTag < AHCI_NR_COMMAND_SLOTS, ("%s: Invalid Tag number %u!!\n", __FUNCTION__, pAhciReq->uTag));
    6445 
    6446             bool fXchg;
    6447             ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_ACTIVE, AHCITXSTATE_FREE, fXchg);
    6448             AssertMsg(fXchg, ("Task is already active\n"));
    6449 
    6450             /* Set current command slot */
    6451             ASMAtomicWriteU32(&pAhciPort->u32CurrentCommandSlot, pAhciReq->uTag);
    6452             pAhciPort->aCachedTasks[0] = pAhciReq; /* Make cancelling the request possible. */
    6453 
    6454             /* Mark the task as processed by the HBA if this is a queued task so that it doesn't occur in the CI register anymore. */
    6455             if (pAhciPort->regSACT & (1 << idx))
    6456             {
    6457                 pAhciReq->fFlags |= AHCI_REQ_CLEAR_SACT;
    6458                 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciReq->uTag));
    6459             }
    6460 
    6461             ahciPortTaskGetCommandFis(pAhciPort, pAhciReq);
    6462 
    6463             ahciLog(("%s: Got command at slot %d\n", __FUNCTION__, pAhciReq->uTag));
    6464 
    6465             if (!(pAhciReq->cmdFis[AHCI_CMDFIS_BITS] & AHCI_CMDFIS_C))
    6466             {
    6467                 /* If the reset bit is set put the device into reset state. */
    6468                 if (pAhciReq->cmdFis[AHCI_CMDFIS_CTL] & AHCI_CMDFIS_CTL_SRST)
    6469                 {
    6470                     ahciLog(("%s: Setting device into reset state\n", __FUNCTION__));
    6471                     pAhciPort->fResetDevice = true;
    6472                     ahciSendD2HFis(pAhciPort, pAhciReq, &pAhciReq->cmdFis[0], true);
    6473                 }
    6474                 else if (pAhciPort->fResetDevice) /* The bit is not set and we are in a reset state. */
    6475                 {
    6476                     ahciFinishStorageDeviceReset(pAhciPort, pAhciReq);
    6477                 }
    6478                 /* TODO: We are not in a reset state update the control registers. */
    6479 
    6480                 ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
    6481                 AssertMsg(fXchg, ("Task is already free\n"));
    6482             }
    6483             else
    6484             {
    6485                 AssertReleaseMsg(ASMAtomicReadU32(&pAhciPort->cTasksActive) < AHCI_NR_COMMAND_SLOTS,
    6486                                  ("There are more than 32 requests active"));
    6487                 ASMAtomicIncU32(&pAhciPort->cTasksActive);
    6488                 enmTxDir = ahciProcessCmd(pAhciPort, pAhciReq, &pAhciReq->cmdFis[0]);
    6489                 pAhciReq->enmTxDir = enmTxDir;
    6490 
    6491                 if (enmTxDir == AHCITXDIR_FLUSH)
    6492                     rc = pAhciPort->pDrvBlock->pfnFlush(pAhciPort->pDrvBlock);
    6493                 else if (enmTxDir == AHCITXDIR_TRIM)
    6494                 {
    6495                     rc = ahciTrimRangesCreate(pAhciPort, pAhciReq);
    6496                     if (RT_SUCCESS(rc))
    6497                     {
    6498                         pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
    6499                         rc = pAhciPort->pDrvBlock->pfnDiscard(pAhciPort->pDrvBlock,
    6500                                                               pAhciReq->u.Trim.paRanges,
    6501                                                               pAhciReq->u.Trim.cRanges);
    6502                         pAhciPort->Led.Actual.s.fWriting = 0;
    6503                     }
    6504                 }
    6505                 else if (enmTxDir != AHCITXDIR_NONE)
    6506                 {
    6507                     uint64_t uOffset = 0;
    6508                     size_t cbTransfer = 0;
    6509 
    6510                     rc = ahciIoBufAllocate(pAhciPort->pDevInsR3, pAhciReq, pAhciReq->cbTransfer);
    6511                     if (RT_FAILURE(rc))
    6512                         AssertMsgFailed(("%s: Failed to get number of list elments %Rrc\n", __FUNCTION__, rc));
    6513 
    6514                     if (!(pAhciReq->fFlags & AHCI_REQ_OVERFLOW))
    6515                     {
    6516                         STAM_REL_COUNTER_INC(&pAhciPort->StatDMA);
    6517 
    6518                         /* Initialize all values. */
    6519                         uOffset     = pAhciReq->uOffset;
    6520                         cbTransfer  = pAhciReq->cbTransfer;
    6521 
    6522                         STAM_PROFILE_START(&pAhciPort->StatProfileReadWrite, b);
    6523 
    6524                         AssertMsg(!(uOffset % 512), ("Offset is not sector aligned %llu\n", uOffset));
    6525                         AssertMsg(!(cbTransfer % 512), ("Number of bytes to process is not sector aligned %lu\n", cbTransfer));
    6526 
    6527                         if (enmTxDir == AHCITXDIR_READ)
    6528                         {
    6529                             pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
    6530                             rc = pAhciPort->pDrvBlock->pfnRead(pAhciPort->pDrvBlock, uOffset,
    6531                                                                pAhciReq->u.Io.DataSeg.pvSeg,
    6532                                                                cbTransfer);
    6533                             pAhciPort->Led.Actual.s.fReading = 0;
    6534                             STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesRead, cbTransfer);
    6535                         }
    6536                         else
    6537                         {
    6538                             pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
    6539                             rc = pAhciPort->pDrvBlock->pfnWrite(pAhciPort->pDrvBlock, uOffset,
    6540                                                                 pAhciReq->u.Io.DataSeg.pvSeg,
    6541                                                                 cbTransfer);
    6542                             pAhciPort->Led.Actual.s.fWriting = 0;
    6543                             STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesWritten, cbTransfer);
    6544                         }
    6545 
    6546                         STAM_PROFILE_STOP(&pAhciPort->StatProfileReadWrite, b);
    6547                     }
    6548                 }
    6549 
    6550                 fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, rc, false /* fFreeReq */);
    6551                 uIORequestsProcessed++;
    6552                 STAM_PROFILE_STOP(&pAhciPort->StatProfileProcessTime, a);
    6553             }
    6554 
    6555             if (!pAhciPort->fRedo)
    6556             {
    6557 #ifdef DEBUG
    6558                 /* Be paranoid. */
    6559                 memset(&pAhciReq->cmdHdr, 0, sizeof(CmdHdr));
    6560                 memset(&pAhciReq->cmdFis, 0, AHCI_CMDFIS_TYPE_H2D_SIZE);
    6561                 pAhciReq->GCPhysCmdHdrAddr = 0;
    6562                 pAhciReq->uOffset = 0;
    6563                 pAhciReq->cbTransfer = 0;
    6564 #endif
    6565             }
    6566 
    6567             /*
    6568              * Don't process other requests if the last one was canceled,
    6569              * the others are not valid anymore.
    6570              */
    6571             if (fReqCanceled)
    6572                 break;
    6573             fTasksToProcess &= ~(1 << idx);
    6574             idx = ASMBitFirstSetU32(fTasksToProcess);
    6575         } /* while tasks to process */
    6576 
    6577         u64StopTime = RTTimeMilliTS();
    6578         /* Check if one second has passed. */
    6579         if (u64StopTime - u64StartTime >= 1000)
    6580         {
    6581             /* Calculate number of I/O requests per second. */
    6582             uIOsPerSec = uIORequestsProcessed / ((u64StopTime - u64StartTime) / 1000);
    6583             ahciLog(("%s: Processed %u requests in %llu ms -> %u requests/s\n", __FUNCTION__, uIORequestsProcessed, u64StopTime - u64StartTime, uIOsPerSec));
    6584             u64StartTime = 0;
    6585             uIORequestsProcessed = 0;
    6586             /* For the release statistics. There is no macro to set the counter to a specific value. */
    6587             pAhciPort->StatIORequestsPerSecond.c = uIOsPerSec;
    6588         }
    65896446    } /* While running */
    6590 
    6591     if (pAhci->fSignalIdle)
    6592         PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
    6593 
    6594     RTMemFree(pAhciReq);
    6595     memset(pAhciPort->aCachedTasks, 0, sizeof(pAhciPort->aCachedTasks));
    65966447
    65976448    ahciLog(("%s: Port %d async IO thread exiting\n", __FUNCTION__, pAhciPort->iLUN));
     
    66086459static DECLCALLBACK(int) ahciAsyncIOLoopWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
    66096460{
     6461    PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
    66106462    PAHCIPort pAhciPort = (PAHCIPort)pThread->pvUser;
    6611     return RTSemEventSignal(pAhciPort->AsyncIORequestSem);
     6463    return SUPSemEventSignal(pThis->pSupDrvSession, pAhciPort->hEvtProcess);
    66126464}
    66136465
     
    75377389    AssertMsg(iLUN < pAhci->cPortsImpl, ("iLUN=%u", iLUN));
    75387390
    7539     if (!pAhciPort->fAsyncInterface)
     7391    if (pAhciPort->pAsyncIOThread)
    75407392    {
    75417393        int rcThread;
     
    75467398
    75477399        pAhciPort->pAsyncIOThread = NULL;
    7548 
    7549         rc = RTSemEventDestroy(pAhciPort->AsyncIORequestSem);
    7550         if (RT_FAILURE(rc))
    7551             AssertMsgFailed(("%s: Failed to destroy the event semaphore rc=%Rrc.\n", __FUNCTION__, rc));
    75527400    }
    75537401
     
    76337481            pAhciPort->fAsyncInterface = true;
    76347482        else
    7635         {
    76367483            pAhciPort->fAsyncInterface = false;
    76377484
    7638             /* Create event semaphore. */
    7639             rc = RTSemEventCreate(&pAhciPort->AsyncIORequestSem);
    7640             if (RT_FAILURE(rc))
    7641             {
    7642                 Log(("%s: Failed to create event semaphore for %s.\n", __FUNCTION__, szName));
    7643                 return rc;
    7644             }
    7645 
    7646             /* Create the async IO thread. */
    7647             rc = PDMDevHlpThreadCreate(pDevIns, &pAhciPort->pAsyncIOThread, pAhciPort, ahciAsyncIOLoop, ahciAsyncIOLoopWakeUp, 0,
    7648                                        RTTHREADTYPE_IO, szName);
    7649             if (RT_FAILURE(rc))
    7650             {
    7651                 AssertMsgFailed(("%s: Async IO Thread creation for %s failed rc=%d\n", __FUNCTION__, szName, rc));
    7652                 return rc;
    7653             }
    7654         }
     7485        /* Create the async IO thread. */
     7486        rc = PDMDevHlpThreadCreate(pDevIns, &pAhciPort->pAsyncIOThread, pAhciPort, ahciAsyncIOLoop, ahciAsyncIOLoopWakeUp, 0,
     7487                                   RTTHREADTYPE_IO, szName);
     7488        if (RT_FAILURE(rc))
     7489            return rc;
    76557490
    76567491        /*
     
    77657600static DECLCALLBACK(int) ahciR3Destruct(PPDMDEVINS pDevIns)
    77667601{
    7767     PAHCI       pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
     7602    PAHCI       pThis = PDMINS_2_DATA(pDevIns, PAHCI);
    77687603    int         rc    = VINF_SUCCESS;
    77697604    PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
     
    77747609     * will take care of terminating and cleaning up the thread.
    77757610     */
    7776     if (PDMCritSectIsInitialized(&pAhci->lock))
    7777     {
    7778         TMR3TimerDestroy(pAhci->CTX_SUFF(pHbaCccTimer));
    7779         pAhci->CTX_SUFF(pHbaCccTimer) = NULL;
     7611    if (PDMCritSectIsInitialized(&pThis->lock))
     7612    {
     7613        TMR3TimerDestroy(pThis->CTX_SUFF(pHbaCccTimer));
     7614        pThis->CTX_SUFF(pHbaCccTimer) = NULL;
    77807615
    77817616        Log(("%s: Destruct every port\n", __FUNCTION__));
    7782         for (unsigned iActPort = 0; iActPort < pAhci->cPortsImpl; iActPort++)
    7783         {
    7784             PAHCIPort pAhciPort = &pAhci->ahciPort[iActPort];
    7785 
    7786             if (pAhciPort->pAsyncIOThread)
     7617        for (unsigned iActPort = 0; iActPort < pThis->cPortsImpl; iActPort++)
     7618        {
     7619            PAHCIPort pAhciPort = &pThis->ahciPort[iActPort];
     7620
     7621            if (pAhciPort->hEvtProcess != NIL_SUPSEMEVENT)
    77877622            {
    7788                 /* Destroy the event semaphore. */
    7789                 rc = RTSemEventDestroy(pAhciPort->AsyncIORequestSem);
    7790                 if (RT_FAILURE(rc))
    7791                     Log(("%s: Destroying event semaphore for port %d failed rc=%Rrc\n", __FUNCTION__, iActPort, rc));
    7792                 pAhciPort->AsyncIORequestSem = NIL_RTSEMEVENT;
     7623                SUPSemEventClose(pThis->pSupDrvSession, pAhciPort->hEvtProcess);
     7624                pAhciPort->hEvtProcess = NIL_SUPSEMEVENT;
    77937625            }
    77947626
     
    78027634        }
    78037635
    7804         PDMR3CritSectDelete(&pAhci->lock);
     7636        PDMR3CritSectDelete(&pThis->lock);
    78057637    }
    78067638
     
    78997731    pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
    79007732    pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     7733    pThis->pSupDrvSession = PDMDevHlpGetSupDrvSession(pDevIns);
    79017734
    79027735    PCIDevSetVendorId    (&pThis->dev, 0x8086); /* Intel */
     
    79467779        pAhciPort->Led.u32Magic         = PDMLED_MAGIC;
    79477780        pAhciPort->pDrvBase             = NULL;
    7948         pAhciPort->AsyncIORequestSem    = NIL_RTSEMEVENT;
    79497781        pAhciPort->pAsyncIOThread       = NULL;
     7782        pAhciPort->hEvtProcess          = NIL_SUPSEMEVENT;
    79507783    }
    79517784
     
    80567889    {
    80577890        PAHCIPort pAhciPort = &pThis->ahciPort[i];
     7891
    80587892        PDMDevHlpSTAMRegisterF(pDevIns, &pAhciPort->StatDMA, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
    80597893                               "Number of DMA transfers.", "/Devices/SATA%d/Port%d/DMA", iInstance, i);
     
    81297963                LogRel(("AHCI: LUN#%d: using normal I/O\n", pAhciPort->iLUN));
    81307964                pAhciPort->fAsyncInterface = false;
    8131 
    8132                 rc = RTSemEventCreate(&pAhciPort->AsyncIORequestSem);
    8133                 AssertMsgRC(rc, ("Failed to create event semaphore for %s rc=%Rrc.\n", szName, rc));
    8134 
    8135 
    8136                 rc = PDMDevHlpThreadCreate(pDevIns, &pAhciPort->pAsyncIOThread, pAhciPort, ahciAsyncIOLoop,
    8137                                            ahciAsyncIOLoopWakeUp, 0, RTTHREADTYPE_IO, szName);
    8138                 AssertMsgRC(rc, ("%s: Async IO Thread creation for %s failed rc=%Rrc\n", szName, rc));
    81397965            }
     7966
     7967            rc = PDMDevHlpThreadCreate(pDevIns, &pAhciPort->pAsyncIOThread, pAhciPort, ahciAsyncIOLoop,
     7968                                       ahciAsyncIOLoopWakeUp, 0, RTTHREADTYPE_IO, szName);
     7969            if (RT_FAILURE(rc))
     7970                return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
     7971                                           N_("AHCI: Failed to create worker thread %s"), szName);
     7972
     7973            rc = SUPSemEventCreate(pThis->pSupDrvSession, &pAhciPort->hEvtProcess);
     7974            if (RT_FAILURE(rc))
     7975                return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
     7976                                           N_("AHCI: Failed to create SUP event semaphore"));
    81407977        }
    81417978        else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
  • trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp

    r44892 r45646  
    11521152    GEN_CHECK_OFF(AHCIPort, fAsyncIOThreadIdle);
    11531153    GEN_CHECK_OFF(AHCIPort, fRedo);
     1154    GEN_CHECK_OFF(AHCIPort, fWrkThreadSleeping);
    11541155    GEN_CHECK_OFF(AHCIPort, cTotalSectors);
    11551156    GEN_CHECK_OFF(AHCIPort, cMultSectors);
     
    11771178    GEN_CHECK_OFF(AHCIPort, Led);
    11781179    GEN_CHECK_OFF(AHCIPort, pAsyncIOThread);
    1179     GEN_CHECK_OFF(AHCIPort, AsyncIORequestSem);
    11801180
    11811181    GEN_CHECK_OFF(AHCIPort, aCachedTasks);
    11821182    GEN_CHECK_OFF(AHCIPort, pTaskErr);
    11831183    GEN_CHECK_OFF(AHCIPort, pTrackList);
     1184    GEN_CHECK_OFF(AHCIPort, hEvtProcess);
    11841185    GEN_CHECK_OFF(AHCIPort, StatDMA);
    11851186    GEN_CHECK_OFF(AHCIPort, StatBytesWritten);
     
    12451246    GEN_CHECK_OFF(AHCI, cCmdSlotsAvail);
    12461247    GEN_CHECK_OFF(AHCI, f8ByteMMIO4BytesWrittenSuccessfully);
     1248    GEN_CHECK_OFF(AHCI, pSupDrvSession);
    12471249#endif /* VBOX_WITH_AHCI */
    12481250
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