VirtualBox

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


Ignore:
Timestamp:
May 25, 2013 5:51:06 PM (12 years ago)
Author:
vboxsync
Message:

Devices/LsiLogic: Move most of the work from EMT to a dedicated worker thread and use SUP event semaphore to notify it about new work

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

Legend:

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

    r46253 r46265  
    2222#include <VBox/vmm/pdmdev.h>
    2323#include <VBox/vmm/pdmqueue.h>
     24#include <VBox/vmm/pdmthread.h>
    2425#include <VBox/vmm/pdmcritsect.h>
    2526#include <VBox/scsi.h>
     27#include <VBox/sup.h>
    2628#include <iprt/assert.h>
    2729#include <iprt/asm.h>
     
    331333    /** Indicates that PDMDevHlpAsyncNotificationCompleted should be called when
    332334     * a port is entering the idle state. */
    333     bool volatile                  fSignalIdle;
     335    bool volatile                    fSignalIdle;
    334336    /** Flag whether we have tasks which need to be processed again- */
    335     bool volatile                  fRedo;
     337    bool volatile                    fRedo;
     338    /** Flag whether the worker thread is sleeping. */
     339    volatile bool                    fWrkThreadSleeping;
    336340    /** Alignment padding. */
    337     bool                             afPadding2[HC_ARCH_BITS == 32 ? 2 : 6];
     341    bool                             afPadding2[HC_ARCH_BITS == 32 ? 1 : 5];
    338342    /** List of tasks which can be redone. */
    339343    R3PTRTYPE(volatile PLSILOGICREQ) pTasksRedoHead;
     
    354358        uint8_t                      u8Padding[2 * sizeof(RTUINTPTR)];
    355359    };
     360
     361    /** The support driver session handle. */
     362    R3R0PTRTYPE(PSUPDRVSESSION)      pSupDrvSession;
     363    /** Worker thread. */
     364    R3PTRTYPE(PPDMTHREAD)            pThreadWrk;
     365    /** The event semaphore the processing thread waits on. */
     366    SUPSEMEVENT                      hEvtProcess;
     367
    356368} LSILOGISCSI;
    357369/** Pointer to the device instance data of the LsiLogic emulation. */
     
    12741286            if (!ASMAtomicXchgBool(&pThis->fNotificationSend, true))
    12751287            {
     1288#ifdef IN_RC
    12761289                PPDMQUEUEITEMCORE pNotificationItem = PDMQueueAlloc(pThis->CTX_SUFF(pNotificationQueue));
    12771290                AssertPtr(pNotificationItem);
    12781291
    12791292                PDMQueueInsert(pThis->CTX_SUFF(pNotificationQueue), pNotificationItem);
     1293#else
     1294                LogFlowFunc(("Signal event semaphore\n"));
     1295                int rc = SUPSemEventSignal(pThis->pSupDrvSession, pThis->hEvtProcess);
     1296                AssertRC(rc);
     1297#endif
    12801298            }
    12811299            break;
     
    36933711    LogFlowFunc(("pDevIns=%#p pItem=%#p\n", pDevIns, pItem));
    36943712
    3695     /* Reset notification event. */
    3696     ASMAtomicXchgBool(&pThis->fNotificationSend, false);
    3697 
    3698     /* Only process request which arrived before we received the notification. */
    3699     uint32_t uRequestQueueNextEntryWrite = ASMAtomicReadU32(&pThis->uRequestQueueNextEntryFreeWrite);
    3700 
    3701     /* Go through the messages now and process them. */
    3702     while (   RT_LIKELY(pThis->enmState == LSILOGICSTATE_OPERATIONAL)
    3703            && (pThis->uRequestQueueNextAddressRead != uRequestQueueNextEntryWrite))
    3704     {
    3705         uint32_t  u32RequestMessageFrameDesc = pThis->CTX_SUFF(pRequestQueueBase)[pThis->uRequestQueueNextAddressRead];
    3706         RTGCPHYS  GCPhysMessageFrameAddr = LSILOGIC_RTGCPHYS_FROM_U32(pThis->u32HostMFAHighAddr,
    3707                                                                       (u32RequestMessageFrameDesc & ~0x07));
    3708 
    3709         PLSILOGICREQ pLsiReq;
    3710 
    3711         /* Get new task state. */
    3712         rc = RTMemCacheAllocEx(pThis->hTaskCache, (void **)&pLsiReq);
    3713         AssertRC(rc);
    3714 
    3715         pLsiReq->GCPhysMessageFrameAddr = GCPhysMessageFrameAddr;
    3716 
    3717         /* Read the message header from the guest first. */
    3718         PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &pLsiReq->GuestRequest, sizeof(MptMessageHdr));
    3719 
    3720         /* Determine the size of the request. */
    3721         uint32_t cbRequest = 0;
    3722 
    3723         switch (pLsiReq->GuestRequest.Header.u8Function)
    3724         {
    3725             case MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST:
    3726                 cbRequest = sizeof(MptSCSIIORequest);
    3727                 break;
    3728             case MPT_MESSAGE_HDR_FUNCTION_SCSI_TASK_MGMT:
    3729                 cbRequest = sizeof(MptSCSITaskManagementRequest);
    3730                 break;
    3731             case MPT_MESSAGE_HDR_FUNCTION_IOC_INIT:
    3732                 cbRequest = sizeof(MptIOCInitRequest);
    3733                 break;
    3734             case MPT_MESSAGE_HDR_FUNCTION_IOC_FACTS:
    3735                 cbRequest = sizeof(MptIOCFactsRequest);
    3736                 break;
    3737             case MPT_MESSAGE_HDR_FUNCTION_CONFIG:
    3738                 cbRequest = sizeof(MptConfigurationRequest);
    3739                 break;
    3740             case MPT_MESSAGE_HDR_FUNCTION_PORT_FACTS:
    3741                 cbRequest = sizeof(MptPortFactsRequest);
    3742                 break;
    3743             case MPT_MESSAGE_HDR_FUNCTION_PORT_ENABLE:
    3744                 cbRequest = sizeof(MptPortEnableRequest);
    3745                 break;
    3746             case MPT_MESSAGE_HDR_FUNCTION_EVENT_NOTIFICATION:
    3747                 cbRequest = sizeof(MptEventNotificationRequest);
    3748                 break;
    3749             case MPT_MESSAGE_HDR_FUNCTION_EVENT_ACK:
    3750                 AssertMsgFailed(("todo\n"));
    3751                 //cbRequest = sizeof(MptEventAckRequest);
    3752                 break;
    3753             case MPT_MESSAGE_HDR_FUNCTION_FW_DOWNLOAD:
    3754                 cbRequest = sizeof(MptFWDownloadRequest);
    3755                 break;
    3756             case MPT_MESSAGE_HDR_FUNCTION_FW_UPLOAD:
    3757                 cbRequest = sizeof(MptFWUploadRequest);
    3758                 break;
    3759             default:
    3760                 AssertMsgFailed(("Unknown function issued %u\n", pLsiReq->GuestRequest.Header.u8Function));
    3761                 lsilogicSetIOCFaultCode(pThis, LSILOGIC_IOCSTATUS_INVALID_FUNCTION);
    3762         }
    3763 
    3764         if (cbRequest != 0)
    3765         {
    3766             /* Read the complete message frame from guest memory now. */
    3767             PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &pLsiReq->GuestRequest, cbRequest);
    3768 
    3769             /* Handle SCSI I/O requests now. */
    3770             if (pLsiReq->GuestRequest.Header.u8Function == MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST)
    3771             {
    3772                rc = lsilogicR3ProcessSCSIIORequest(pThis, pLsiReq);
    3773                AssertRC(rc);
    3774             }
    3775             else
    3776             {
    3777                 MptReplyUnion Reply;
    3778                 rc = lsilogicR3ProcessMessageRequest(pThis, &pLsiReq->GuestRequest.Header, &Reply);
    3779                 AssertRC(rc);
    3780                 RTMemCacheFree(pThis->hTaskCache, pLsiReq);
    3781             }
    3782 
    3783             pThis->uRequestQueueNextAddressRead++;
    3784             pThis->uRequestQueueNextAddressRead %= pThis->cRequestQueueEntries;
    3785         }
    3786     }
     3713    rc = SUPSemEventSignal(pThis->pSupDrvSession, pThis->hEvtProcess);
     3714    AssertRC(rc);
    37873715
    37883716    return true;
     
    42234151    pThis->pRequestQueueBaseR3   = NULL;
    42244152}
     4153
     4154
     4155/* The worker thread. */
     4156static DECLCALLBACK(int) lsilogicR3Worker(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
     4157{
     4158    PLSILOGICSCSI pThis = (PLSILOGICSCSI)pThread->pvUser;
     4159    int rc = VINF_SUCCESS;
     4160
     4161    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
     4162        return VINF_SUCCESS;
     4163
     4164    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
     4165    {
     4166        bool fNotificationSend;
     4167
     4168        ASMAtomicWriteBool(&pThis->fWrkThreadSleeping, true);
     4169        fNotificationSend = ASMAtomicXchgBool(&pThis->fNotificationSend, false);
     4170        if (!fNotificationSend)
     4171        {
     4172            Assert(ASMAtomicReadBool(&pThis->fWrkThreadSleeping));
     4173            rc = SUPSemEventWaitNoResume(pThis->pSupDrvSession, pThis->hEvtProcess, RT_INDEFINITE_WAIT);
     4174            AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_INTERRUPTED, ("%Rrc\n", rc), rc);
     4175            if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING))
     4176                break;
     4177            LogFlowFunc(("Woken up with rc=%Rrc\n", rc));
     4178            fNotificationSend = ASMAtomicXchgBool(&pThis->fNotificationSend, false);
     4179        }
     4180
     4181        ASMAtomicWriteBool(&pThis->fWrkThreadSleeping, false);
     4182
     4183        /* Only process request which arrived before we received the notification. */
     4184        uint32_t uRequestQueueNextEntryWrite = ASMAtomicReadU32(&pThis->uRequestQueueNextEntryFreeWrite);
     4185
     4186        /* Go through the messages now and process them. */
     4187        while (   RT_LIKELY(pThis->enmState == LSILOGICSTATE_OPERATIONAL)
     4188               && (pThis->uRequestQueueNextAddressRead != uRequestQueueNextEntryWrite))
     4189        {
     4190            uint32_t  u32RequestMessageFrameDesc = pThis->CTX_SUFF(pRequestQueueBase)[pThis->uRequestQueueNextAddressRead];
     4191            RTGCPHYS  GCPhysMessageFrameAddr = LSILOGIC_RTGCPHYS_FROM_U32(pThis->u32HostMFAHighAddr,
     4192                                                                          (u32RequestMessageFrameDesc & ~0x07));
     4193
     4194            PLSILOGICREQ pLsiReq;
     4195
     4196            /* Get new task state. */
     4197            rc = RTMemCacheAllocEx(pThis->hTaskCache, (void **)&pLsiReq);
     4198            AssertRC(rc);
     4199
     4200            pLsiReq->GCPhysMessageFrameAddr = GCPhysMessageFrameAddr;
     4201
     4202            /* Read the message header from the guest first. */
     4203            PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &pLsiReq->GuestRequest, sizeof(MptMessageHdr));
     4204
     4205            /* Determine the size of the request. */
     4206            uint32_t cbRequest = 0;
     4207
     4208            switch (pLsiReq->GuestRequest.Header.u8Function)
     4209            {
     4210                case MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST:
     4211                    cbRequest = sizeof(MptSCSIIORequest);
     4212                    break;
     4213                case MPT_MESSAGE_HDR_FUNCTION_SCSI_TASK_MGMT:
     4214                    cbRequest = sizeof(MptSCSITaskManagementRequest);
     4215                    break;
     4216                case MPT_MESSAGE_HDR_FUNCTION_IOC_INIT:
     4217                    cbRequest = sizeof(MptIOCInitRequest);
     4218                    break;
     4219                case MPT_MESSAGE_HDR_FUNCTION_IOC_FACTS:
     4220                    cbRequest = sizeof(MptIOCFactsRequest);
     4221                    break;
     4222                case MPT_MESSAGE_HDR_FUNCTION_CONFIG:
     4223                    cbRequest = sizeof(MptConfigurationRequest);
     4224                    break;
     4225                case MPT_MESSAGE_HDR_FUNCTION_PORT_FACTS:
     4226                    cbRequest = sizeof(MptPortFactsRequest);
     4227                    break;
     4228                case MPT_MESSAGE_HDR_FUNCTION_PORT_ENABLE:
     4229                    cbRequest = sizeof(MptPortEnableRequest);
     4230                    break;
     4231                case MPT_MESSAGE_HDR_FUNCTION_EVENT_NOTIFICATION:
     4232                    cbRequest = sizeof(MptEventNotificationRequest);
     4233                    break;
     4234                case MPT_MESSAGE_HDR_FUNCTION_EVENT_ACK:
     4235                    AssertMsgFailed(("todo\n"));
     4236                    //cbRequest = sizeof(MptEventAckRequest);
     4237                    break;
     4238                case MPT_MESSAGE_HDR_FUNCTION_FW_DOWNLOAD:
     4239                    cbRequest = sizeof(MptFWDownloadRequest);
     4240                    break;
     4241                case MPT_MESSAGE_HDR_FUNCTION_FW_UPLOAD:
     4242                    cbRequest = sizeof(MptFWUploadRequest);
     4243                    break;
     4244                default:
     4245                    AssertMsgFailed(("Unknown function issued %u\n", pLsiReq->GuestRequest.Header.u8Function));
     4246                    lsilogicSetIOCFaultCode(pThis, LSILOGIC_IOCSTATUS_INVALID_FUNCTION);
     4247            }
     4248
     4249            if (cbRequest != 0)
     4250            {
     4251                /* Read the complete message frame from guest memory now. */
     4252                PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &pLsiReq->GuestRequest, cbRequest);
     4253
     4254                /* Handle SCSI I/O requests now. */
     4255                if (pLsiReq->GuestRequest.Header.u8Function == MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST)
     4256                {
     4257                   rc = lsilogicR3ProcessSCSIIORequest(pThis, pLsiReq);
     4258                   AssertRC(rc);
     4259                }
     4260                else
     4261                {
     4262                    MptReplyUnion Reply;
     4263                    rc = lsilogicR3ProcessMessageRequest(pThis, &pLsiReq->GuestRequest.Header, &Reply);
     4264                    AssertRC(rc);
     4265                    RTMemCacheFree(pThis->hTaskCache, pLsiReq);
     4266                }
     4267
     4268                pThis->uRequestQueueNextAddressRead++;
     4269                pThis->uRequestQueueNextAddressRead %= pThis->cRequestQueueEntries;
     4270            }
     4271        } /* While request frames available. */
     4272    } /* While running */
     4273
     4274    return VINF_SUCCESS;
     4275}
     4276
     4277
     4278/**
     4279 * Unblock the worker thread so it can respond to a state change.
     4280 *
     4281 * @returns VBox status code.
     4282 * @param   pDevIns     The pcnet device instance.
     4283 * @param   pThread     The send thread.
     4284 */
     4285static DECLCALLBACK(int) lsilogicR3WorkerWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
     4286{
     4287    PLSILOGICSCSI pThis = PDMINS_2_DATA(pDevIns, PLSILOGICSCSI);
     4288    return SUPSemEventSignal(pThis->pSupDrvSession, pThis->hEvtProcess);
     4289}
     4290
    42254291
    42264292/**
     
    51605226    }
    51615227
     5228    if (pThis->hEvtProcess != NIL_SUPSEMEVENT)
     5229    {
     5230        SUPSemEventClose(pThis->pSupDrvSession, pThis->hEvtProcess);
     5231        pThis->hEvtProcess = NIL_SUPSEMEVENT;
     5232    }
     5233
    51625234    lsilogicR3ConfigurationPagesFree(pThis);
    51635235    lsilogicR3MemRegionsFree(pThis);
     
    51785250     * Initialize enought of the state to make the destructure not trip up.
    51795251     */
    5180     pThis->hTaskCache = NIL_RTMEMCACHE;
     5252    pThis->hTaskCache  = NIL_RTMEMCACHE;
     5253    pThis->hEvtProcess = NIL_SUPSEMEVENT;
    51815254    RTListInit(&pThis->ListMemRegns);
    51825255
     
    52965369    pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
    52975370    pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     5371    pThis->pSupDrvSession = PDMDevHlpGetSupDrvSession(pDevIns);
    52985372    pThis->IBase.pfnQueryInterface = lsilogicR3StatusQueryInterface;
    52995373    pThis->ILeds.pfnQueryStatusLed = lsilogicR3StatusQueryStatusLed;
     
    53955469    else
    53965470        AssertMsgFailed(("Invalid controller type: %d\n", pThis->enmCtrlType));
     5471
     5472    /*
     5473     * Create event semaphore and worker thread.
     5474     */
     5475    rc = PDMDevHlpThreadCreate(pDevIns, &pThis->pThreadWrk, pThis, lsilogicR3Worker,
     5476                               lsilogicR3WorkerWakeUp, 0, RTTHREADTYPE_IO, szDevTag);
     5477    if (RT_FAILURE(rc))
     5478        return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
     5479                                   N_("LsiLogic: Failed to create worker thread %s"), szDevTag);
     5480
     5481    rc = SUPSemEventCreate(pThis->pSupDrvSession, &pThis->hEvtProcess);
     5482    if (RT_FAILURE(rc))
     5483        return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
     5484                                   N_("LsiLogic: Failed to create SUP event semaphore"));
    53975485
    53985486    /*
  • trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp

    r46253 r46265  
    16161616    GEN_CHECK_OFF(LSILOGICSCSI, fSignalIdle);
    16171617    GEN_CHECK_OFF(LSILOGICSCSI, fRedo);
     1618    GEN_CHECK_OFF(LSILOGICSCSI, fWrkThreadSleeping);
    16181619    GEN_CHECK_OFF(LSILOGICSCSI, pTasksRedoHead);
    16191620    GEN_CHECK_OFF(LSILOGICSCSI, u32DiagMemAddr);
    16201621    GEN_CHECK_OFF(LSILOGICSCSI, cbMemRegns);
    16211622    GEN_CHECK_OFF(LSILOGICSCSI, ListMemRegns);
     1623    GEN_CHECK_OFF(LSILOGICSCSI, pSupDrvSession);
     1624    GEN_CHECK_OFF(LSILOGICSCSI, pThreadWrk);
     1625    GEN_CHECK_OFF(LSILOGICSCSI, hEvtProcess);
    16221626#endif /* VBOX_WITH_LSILOGIC */
    16231627
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