VirtualBox

source: vbox/trunk/src/VBox/VMM/PDMAsyncCompletionFileFailsafe.cpp@ 21979

Last change on this file since 21979 was 21496, checked in by vboxsync, 15 years ago

VMM/PDMAsyncCompletion: Add basic working manager using RTFileAio API (Only tested on Linux) yet without caching. Splitted normal and failsafe manager into separate files to make the code easier to read

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.1 KB
Line 
1/* $Id: PDMAsyncCompletionFileFailsafe.cpp 21496 2009-07-10 20:16:09Z vboxsync $ */
2/** @file
3 * PDM Async I/O - Transport data asynchronous in R3 using EMT.
4 * Failsafe File I/O manager.
5 */
6
7/*
8 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
20 * additional information or have any questions.
21 */
22#define LOG_GROUP LOG_GROUP_PDM_ASYNC_COMPLETION
23#include <iprt/types.h>
24#include <VBox/log.h>
25
26#include "PDMAsyncCompletionFileInternal.h"
27
28static int pdmacFileAioMgrFailsafeProcessEndpoint(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint)
29{
30 int rc = VINF_SUCCESS;
31 PPDMASYNCCOMPLETIONTASK pTasks = pdmacFileEpGetNewTasks(pEndpoint);
32
33 while (pTasks)
34 {
35 PPDMASYNCCOMPLETIONTASKFILE pTaskFile = (PPDMASYNCCOMPLETIONTASKFILE)pTasks;
36
37 if (pTasks->pNext)
38 AssertMsg(pTasks->uTaskId < pTasks->pNext->uTaskId,
39 ("The task IDs are not ordered Curr=%u Next=%u\n", pTasks->uTaskId, pTasks->pNext->uTaskId));
40
41 switch (pTaskFile->enmTransferType)
42 {
43 case PDMACTASKFILETRANSFER_FLUSH:
44 {
45 rc = RTFileFlush(pEndpoint->File);
46 break;
47 }
48 case PDMACTASKFILETRANSFER_READ:
49 case PDMACTASKFILETRANSFER_WRITE:
50 {
51 PPDMACTASKFILESEG pSeg = pTaskFile->u.DataTransfer.pSegmentsHead;
52 RTFOFF offCurr = pTaskFile->u.DataTransfer.off;
53
54 do
55 {
56 if (pTaskFile->enmTransferType == PDMACTASKFILETRANSFER_READ)
57 {
58 rc = RTFileReadAt(pEndpoint->File, offCurr,
59 pSeg->DataSeg.pvSeg,
60 pSeg->DataSeg.cbSeg,
61 NULL);
62 }
63 else
64 {
65 rc = RTFileWriteAt(pEndpoint->File, offCurr,
66 pSeg->DataSeg.pvSeg,
67 pSeg->DataSeg.cbSeg,
68 NULL);
69 }
70
71 /* Free the segment. */
72 PPDMACTASKFILESEG pCur = pSeg;
73 pSeg = pSeg->pNext;
74
75 offCurr += pCur->DataSeg.cbSeg;
76
77 pdmacFileSegmentFree(pEndpoint, pCur);
78 } while(pSeg && RT_SUCCESS(rc));
79
80 AssertMsg(offCurr == (pTaskFile->u.DataTransfer.off + (RTFOFF)pTaskFile->u.DataTransfer.cbTransfer),
81 ("Incomplete transfer %llu bytes requested offCurr=%llu rc=%Rrc\n",
82 pTaskFile->u.DataTransfer.cbTransfer,
83 offCurr, rc));
84
85 break;
86 }
87 default:
88 AssertMsgFailed(("Invalid transfer type %d\n", pTaskFile->enmTransferType));
89 }
90
91 AssertRC(rc);
92 pTasks = pTasks->pNext;
93
94 /* Notify task owner */
95 pdmR3AsyncCompletionCompleteTask(&pTaskFile->Core);
96 }
97
98 return rc;
99}
100
101/**
102 * A fallback method in case something goes wrong with the normal
103 * I/O manager.
104 */
105int pdmacFileAioMgrFailsafe(RTTHREAD ThreadSelf, void *pvUser)
106{
107 int rc = VINF_SUCCESS;
108 PPDMACEPFILEMGR pAioMgr = (PPDMACEPFILEMGR)pvUser;
109
110 while (!pAioMgr->fShutdown)
111 {
112 if (!ASMAtomicReadBool(&pAioMgr->fWokenUp))
113 {
114 ASMAtomicWriteBool(&pAioMgr->fWaitingEventSem, true);
115 rc = RTSemEventWait(pAioMgr->EventSem, RT_INDEFINITE_WAIT);
116 ASMAtomicWriteBool(&pAioMgr->fWaitingEventSem, false);
117 AssertRC(rc);
118 }
119 ASMAtomicXchgBool(&pAioMgr->fWokenUp, false);
120
121 /* Process endpoint events first. */
122 PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint = pAioMgr->pEndpointsHead;
123 while (pEndpoint)
124 {
125 rc = pdmacFileAioMgrFailsafeProcessEndpoint(pEndpoint);
126 AssertRC(rc);
127 pEndpoint = pEndpoint->AioMgr.pEndpointNext;
128 }
129
130 /* Now check for an external blocking event. */
131 if (pAioMgr->fBlockingEventPending)
132 {
133 switch (pAioMgr->enmBlockingEvent)
134 {
135 case PDMACEPFILEAIOMGRBLOCKINGEVENT_ADD_ENDPOINT:
136 {
137 PPDMASYNCCOMPLETIONENDPOINTFILE pEndpointNew = pAioMgr->BlockingEventData.AddEndpoint.pEndpoint;
138 AssertMsg(VALID_PTR(pEndpointNew), ("Adding endpoint event without a endpoint to add\n"));
139
140 pEndpointNew->AioMgr.pEndpointNext = pAioMgr->pEndpointsHead;
141 pEndpointNew->AioMgr.pEndpointPrev = NULL;
142 if (pAioMgr->pEndpointsHead)
143 pAioMgr->pEndpointsHead->AioMgr.pEndpointPrev = pEndpointNew;
144 pAioMgr->pEndpointsHead = pEndpointNew;
145 break;
146 }
147 case PDMACEPFILEAIOMGRBLOCKINGEVENT_REMOVE_ENDPOINT:
148 {
149 PPDMASYNCCOMPLETIONENDPOINTFILE pEndpointRemove = pAioMgr->BlockingEventData.RemoveEndpoint.pEndpoint;
150 AssertMsg(VALID_PTR(pEndpointRemove), ("Removing endpoint event without a endpoint to remove\n"));
151
152 PPDMASYNCCOMPLETIONENDPOINTFILE pPrev = pEndpointRemove->AioMgr.pEndpointPrev;
153 PPDMASYNCCOMPLETIONENDPOINTFILE pNext = pEndpointRemove->AioMgr.pEndpointNext;
154
155 if (pPrev)
156 pPrev->AioMgr.pEndpointNext = pNext;
157 else
158 pAioMgr->pEndpointsHead = pNext;
159
160 if (pNext)
161 pNext->AioMgr.pEndpointPrev = pPrev;
162 break;
163 }
164 case PDMACEPFILEAIOMGRBLOCKINGEVENT_CLOSE_ENDPOINT:
165 {
166 PPDMASYNCCOMPLETIONENDPOINTFILE pEndpointClose = pAioMgr->BlockingEventData.CloseEndpoint.pEndpoint;
167 AssertMsg(VALID_PTR(pEndpointClose), ("Close endpoint event without a endpoint to Close\n"));
168
169 /* Make sure all tasks finished. */
170 rc = pdmacFileAioMgrFailsafeProcessEndpoint(pEndpointClose);
171 AssertRC(rc);
172 }
173 case PDMACEPFILEAIOMGRBLOCKINGEVENT_SHUTDOWN:
174 break;
175 case PDMACEPFILEAIOMGRBLOCKINGEVENT_SUSPEND:
176 break;
177 default:
178 AssertMsgFailed(("Invalid event type %d\n", pAioMgr->enmBlockingEvent));
179 }
180
181 /* Release the waiting thread. */
182 rc = RTSemEventSignal(pAioMgr->EventSemBlock);
183 AssertRC(rc);
184 }
185 }
186
187 return rc;
188}
189
Note: See TracBrowser for help on using the repository browser.

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