VirtualBox

source: vbox/trunk/src/VBox/VMM/include/PDMAsyncCompletionFileInternal.h@ 35346

Last change on this file since 35346 was 35346, checked in by vboxsync, 14 years ago

VMM reorg: Moving the public include files from include/VBox to include/VBox/vmm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.1 KB
Line 
1/* $Id: PDMAsyncCompletionFileInternal.h 35346 2010-12-27 16:13:13Z vboxsync $ */
2/** @file
3 * PDM Async I/O - Transport data asynchronous in R3 using EMT.
4 */
5
6/*
7 * Copyright (C) 2006-2008 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifndef ___PDMAsyncCompletionFileInternal_h
19#define ___PDMAsyncCompletionFileInternal_h
20
21#include <VBox/vmm/cfgm.h>
22#include <VBox/vmm/stam.h>
23#include <VBox/vmm/tm.h>
24#include <iprt/types.h>
25#include <iprt/file.h>
26#include <iprt/thread.h>
27#include <iprt/semaphore.h>
28#include <iprt/critsect.h>
29#include <iprt/avl.h>
30#include <iprt/list.h>
31#include <iprt/spinlock.h>
32#include <iprt/memcache.h>
33
34#include "PDMAsyncCompletionInternal.h"
35
36/** @todo: Revise the caching of tasks. We have currently four caches:
37 * Per endpoint task cache
38 * Per class cache
39 * Per endpoint task segment cache
40 * Per class task segment cache
41 *
42 * We could use the RT heap for this probably or extend MMR3Heap (uses RTMemAlloc
43 * instead of managing larger blocks) to have this global for the whole VM.
44 */
45
46RT_C_DECLS_BEGIN
47
48/**
49 * A few forward declarations.
50 */
51typedef struct PDMASYNCCOMPLETIONENDPOINTFILE *PPDMASYNCCOMPLETIONENDPOINTFILE;
52/** Pointer to a request segment. */
53typedef struct PDMACTASKFILE *PPDMACTASKFILE;
54/** Pointer to the endpoint class data. */
55typedef struct PDMASYNCCOMPLETIONTASKFILE *PPDMASYNCCOMPLETIONTASKFILE;
56/** Pointer to a cache LRU list. */
57typedef struct PDMACFILELRULIST *PPDMACFILELRULIST;
58/** Pointer to the global cache structure. */
59typedef struct PDMACFILECACHEGLOBAL *PPDMACFILECACHEGLOBAL;
60/** Pointer to a task segment. */
61typedef struct PDMACFILETASKSEG *PPDMACFILETASKSEG;
62
63/**
64 * Blocking event types.
65 */
66typedef enum PDMACEPFILEAIOMGRBLOCKINGEVENT
67{
68 /** Invalid tye */
69 PDMACEPFILEAIOMGRBLOCKINGEVENT_INVALID = 0,
70 /** An endpoint is added to the manager. */
71 PDMACEPFILEAIOMGRBLOCKINGEVENT_ADD_ENDPOINT,
72 /** An endpoint is removed from the manager. */
73 PDMACEPFILEAIOMGRBLOCKINGEVENT_REMOVE_ENDPOINT,
74 /** An endpoint is about to be closed. */
75 PDMACEPFILEAIOMGRBLOCKINGEVENT_CLOSE_ENDPOINT,
76 /** The manager is requested to terminate */
77 PDMACEPFILEAIOMGRBLOCKINGEVENT_SHUTDOWN,
78 /** The manager is requested to suspend */
79 PDMACEPFILEAIOMGRBLOCKINGEVENT_SUSPEND,
80 /** The manager is requested to resume */
81 PDMACEPFILEAIOMGRBLOCKINGEVENT_RESUME,
82 /** 32bit hack */
83 PDMACEPFILEAIOMGRBLOCKINGEVENT_32BIT_HACK = 0x7fffffff
84} PDMACEPFILEAIOMGRBLOCKINGEVENT;
85
86/**
87 * I/O manager type.
88 */
89typedef enum PDMACEPFILEMGRTYPE
90{
91 /** Simple aka failsafe */
92 PDMACEPFILEMGRTYPE_SIMPLE = 0,
93 /** Async I/O with host cache enabled. */
94 PDMACEPFILEMGRTYPE_ASYNC,
95 /** 32bit hack */
96 PDMACEPFILEMGRTYPE_32BIT_HACK = 0x7fffffff
97} PDMACEPFILEMGRTYPE;
98/** Pointer to a I/O manager type */
99typedef PDMACEPFILEMGRTYPE *PPDMACEPFILEMGRTYPE;
100
101/**
102 * States of the I/O manager.
103 */
104typedef enum PDMACEPFILEMGRSTATE
105{
106 /** Invalid state. */
107 PDMACEPFILEMGRSTATE_INVALID = 0,
108 /** Normal running state accepting new requests
109 * and processing them.
110 */
111 PDMACEPFILEMGRSTATE_RUNNING,
112 /** Fault state - not accepting new tasks for endpoints but waiting for
113 * remaining ones to finish.
114 */
115 PDMACEPFILEMGRSTATE_FAULT,
116 /** Suspending state - not accepting new tasks for endpoints but waiting
117 * for remaining ones to finish.
118 */
119 PDMACEPFILEMGRSTATE_SUSPENDING,
120 /** Shutdown state - not accepting new tasks for endpoints but waiting
121 * for remaining ones to finish.
122 */
123 PDMACEPFILEMGRSTATE_SHUTDOWN,
124 /** The I/O manager waits for all active requests to complete and doesn't queue
125 * new ones because it needs to grow to handle more requests.
126 */
127 PDMACEPFILEMGRSTATE_GROWING,
128 /** 32bit hack */
129 PDMACEPFILEMGRSTATE_32BIT_HACK = 0x7fffffff
130} PDMACEPFILEMGRSTATE;
131
132/**
133 * State of a async I/O manager.
134 */
135typedef struct PDMACEPFILEMGR
136{
137 /** Next Aio manager in the list. */
138 R3PTRTYPE(struct PDMACEPFILEMGR *) pNext;
139 /** Previous Aio manager in the list. */
140 R3PTRTYPE(struct PDMACEPFILEMGR *) pPrev;
141 /** Manager type */
142 PDMACEPFILEMGRTYPE enmMgrType;
143 /** Current state of the manager. */
144 PDMACEPFILEMGRSTATE enmState;
145 /** Event semaphore the manager sleeps on when waiting for new requests. */
146 RTSEMEVENT EventSem;
147 /** Flag whether the thread waits in the event semaphore. */
148 volatile bool fWaitingEventSem;
149 /** Thread data */
150 RTTHREAD Thread;
151 /** The async I/O context for this manager. */
152 RTFILEAIOCTX hAioCtx;
153 /** Flag whether the I/O manager was woken up. */
154 volatile bool fWokenUp;
155 /** List of endpoints assigned to this manager. */
156 R3PTRTYPE(PPDMASYNCCOMPLETIONENDPOINTFILE) pEndpointsHead;
157 /** Number of endpoints assigned to the manager. */
158 unsigned cEndpoints;
159 /** Number of requests active currently. */
160 unsigned cRequestsActive;
161 /** Number of maximum requests active. */
162 uint32_t cRequestsActiveMax;
163 /** Pointer to an array of free async I/O request handles. */
164 RTFILEAIOREQ *pahReqsFree;
165 /** Index of the next free entry in the cache. */
166 uint32_t iFreeEntry;
167 /** Size of the array. */
168 unsigned cReqEntries;
169 /** Memory cache for file range locks. */
170 RTMEMCACHE hMemCacheRangeLocks;
171 /** Number of milliseconds to wait until the bandwidth is refreshed for at least
172 * one endpoint and it is possible to process more requests. */
173 RTMSINTERVAL msBwLimitExpired;
174 /** Critical section protecting the blocking event handling. */
175 RTCRITSECT CritSectBlockingEvent;
176 /** Event semaphore for blocking external events.
177 * The caller waits on it until the async I/O manager
178 * finished processing the event. */
179 RTSEMEVENT EventSemBlock;
180 /** Flag whether a blocking event is pending and needs
181 * processing by the I/O manager. */
182 volatile bool fBlockingEventPending;
183 /** Blocking event type */
184 volatile PDMACEPFILEAIOMGRBLOCKINGEVENT enmBlockingEvent;
185 /** Event type data */
186 union
187 {
188 /** Add endpoint event. */
189 struct
190 {
191 /** The endpoint to be added */
192 volatile PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint;
193 } AddEndpoint;
194 /** Remove endpoint event. */
195 struct
196 {
197 /** The endpoint to be removed */
198 volatile PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint;
199 } RemoveEndpoint;
200 /** Close endpoint event. */
201 struct
202 {
203 /** The endpoint to be closed */
204 volatile PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint;
205 } CloseEndpoint;
206 } BlockingEventData;
207} PDMACEPFILEMGR;
208/** Pointer to a async I/O manager state. */
209typedef PDMACEPFILEMGR *PPDMACEPFILEMGR;
210/** Pointer to a async I/O manager state pointer. */
211typedef PPDMACEPFILEMGR *PPPDMACEPFILEMGR;
212
213/**
214 * A file access range lock.
215 */
216typedef struct PDMACFILERANGELOCK
217{
218 /** AVL node in the locked range tree of the endpoint. */
219 AVLRFOFFNODECORE Core;
220 /** How many tasks have locked this range. */
221 uint32_t cRefs;
222 /** Flag whether this is a read or write lock. */
223 bool fReadLock;
224 /** List of tasks which are waiting that the range gets unlocked. */
225 PPDMACTASKFILE pWaitingTasksHead;
226 /** List of tasks which are waiting that the range gets unlocked. */
227 PPDMACTASKFILE pWaitingTasksTail;
228} PDMACFILERANGELOCK, *PPDMACFILERANGELOCK;
229
230/**
231 * Backend type for the endpoint.
232 */
233typedef enum PDMACFILEEPBACKEND
234{
235 /** Non buffered. */
236 PDMACFILEEPBACKEND_NON_BUFFERED = 0,
237 /** Buffered (i.e host cache enabled) */
238 PDMACFILEEPBACKEND_BUFFERED,
239 /** 32bit hack */
240 PDMACFILEEPBACKEND_32BIT_HACK = 0x7fffffff
241} PDMACFILEEPBACKEND;
242/** Pointer to a backend type. */
243typedef PDMACFILEEPBACKEND *PPDMACFILEEPBACKEND;
244
245/**
246 * Global data for the file endpoint class.
247 */
248typedef struct PDMASYNCCOMPLETIONEPCLASSFILE
249{
250 /** Common data. */
251 PDMASYNCCOMPLETIONEPCLASS Core;
252 /** Override I/O manager type - set to SIMPLE after failure. */
253 PDMACEPFILEMGRTYPE enmMgrTypeOverride;
254 /** Default backend type for the endpoint. */
255 PDMACFILEEPBACKEND enmEpBackendDefault;
256 RTCRITSECT CritSect;
257 /** Pointer to the head of the async I/O managers. */
258 R3PTRTYPE(PPDMACEPFILEMGR) pAioMgrHead;
259 /** Number of async I/O managers currently running. */
260 unsigned cAioMgrs;
261 /** Maximum number of segments to cache per endpoint */
262 unsigned cTasksCacheMax;
263 /** Maximum number of simultaneous outstandingrequests. */
264 uint32_t cReqsOutstandingMax;
265 /** Bitmask for checking the alignment of a buffer. */
266 RTR3UINTPTR uBitmaskAlignment;
267 /** Flag whether the out of resources warning was printed already. */
268 bool fOutOfResourcesWarningPrinted;
269} PDMASYNCCOMPLETIONEPCLASSFILE;
270/** Pointer to the endpoint class data. */
271typedef PDMASYNCCOMPLETIONEPCLASSFILE *PPDMASYNCCOMPLETIONEPCLASSFILE;
272
273typedef enum PDMACEPFILEBLOCKINGEVENT
274{
275 /** The invalid event type */
276 PDMACEPFILEBLOCKINGEVENT_INVALID = 0,
277 /** A task is about to be canceled */
278 PDMACEPFILEBLOCKINGEVENT_CANCEL,
279 /** Usual 32bit hack */
280 PDMACEPFILEBLOCKINGEVENT_32BIT_HACK = 0x7fffffff
281} PDMACEPFILEBLOCKINGEVENT;
282
283/**
284 * States of the endpoint.
285 */
286typedef enum PDMASYNCCOMPLETIONENDPOINTFILESTATE
287{
288 /** Invalid state. */
289 PDMASYNCCOMPLETIONENDPOINTFILESTATE_INVALID = 0,
290 /** Normal running state accepting new requests
291 * and processing them.
292 */
293 PDMASYNCCOMPLETIONENDPOINTFILESTATE_ACTIVE,
294 /** The endpoint is about to be closed - not accepting new tasks for endpoints but waiting for
295 * remaining ones to finish.
296 */
297 PDMASYNCCOMPLETIONENDPOINTFILESTATE_CLOSING,
298 /** Removing from current I/O manager state - not processing new tasks for endpoints but waiting
299 * for remaining ones to finish.
300 */
301 PDMASYNCCOMPLETIONENDPOINTFILESTATE_REMOVING,
302 /** The current endpoint will be migrated to another I/O manager. */
303 PDMASYNCCOMPLETIONENDPOINTFILESTATE_MIGRATING,
304 /** 32bit hack */
305 PDMASYNCCOMPLETIONENDPOINTFILESTATE_32BIT_HACK = 0x7fffffff
306} PDMASYNCCOMPLETIONENDPOINTFILESTATE;
307
308/**
309 * Data for the file endpoint.
310 */
311typedef struct PDMASYNCCOMPLETIONENDPOINTFILE
312{
313 /** Common data. */
314 PDMASYNCCOMPLETIONENDPOINT Core;
315 /** Current state of the endpoint. */
316 PDMASYNCCOMPLETIONENDPOINTFILESTATE enmState;
317 /** The backend to use for this endpoint. */
318 PDMACFILEEPBACKEND enmBackendType;
319 /** async I/O manager this endpoint is assigned to. */
320 R3PTRTYPE(volatile PPDMACEPFILEMGR) pAioMgr;
321 /** Flags for opening the file. */
322 unsigned fFlags;
323 /** File handle. */
324 RTFILE File;
325 /**
326 * Real size of the file. Only updated if
327 * data is appended.
328 */
329 volatile uint64_t cbFile;
330 /** List of new tasks. */
331 R3PTRTYPE(volatile PPDMACTASKFILE) pTasksNewHead;
332
333 /** Head of the small cache for allocated task segments for exclusive
334 * use by this endpoint. */
335 R3PTRTYPE(volatile PPDMACTASKFILE) pTasksFreeHead;
336 /** Tail of the small cache for allocated task segments for exclusive
337 * use by this endpoint. */
338 R3PTRTYPE(volatile PPDMACTASKFILE) pTasksFreeTail;
339 /** Number of elements in the cache. */
340 volatile uint32_t cTasksCached;
341
342 /** Flag whether a flush request is currently active */
343 PPDMACTASKFILE pFlushReq;
344
345#ifdef VBOX_WITH_STATISTICS
346 /** Time spend in a read. */
347 STAMPROFILEADV StatRead;
348 /** Time spend in a write. */
349 STAMPROFILEADV StatWrite;
350#endif
351
352 /** Event semaphore for blocking external events.
353 * The caller waits on it until the async I/O manager
354 * finished processing the event. */
355 RTSEMEVENT EventSemBlock;
356 /** Flag whether caching is enabled for this file. */
357 bool fCaching;
358 /** Flag whether the file was opened readonly. */
359 bool fReadonly;
360 /** Flag whether the host supports the async flush API. */
361 bool fAsyncFlushSupported;
362#ifdef VBOX_WITH_DEBUGGER
363 /** Status code to inject for the next complete read. */
364 volatile int rcReqRead;
365 /** Status code to inject for the next complete write. */
366 volatile int rcReqWrite;
367#endif
368 /** Flag whether a blocking event is pending and needs
369 * processing by the I/O manager. */
370 bool fBlockingEventPending;
371 /** Blocking event type */
372 PDMACEPFILEBLOCKINGEVENT enmBlockingEvent;
373
374 /** Additional data needed for the event types. */
375 union
376 {
377 /** Cancelation event. */
378 struct
379 {
380 /** The task to cancel. */
381 PPDMACTASKFILE pTask;
382 } Cancel;
383 } BlockingEventData;
384 /** Data for exclusive use by the assigned async I/O manager. */
385 struct
386 {
387 /** Pointer to the next endpoint assigned to the manager. */
388 R3PTRTYPE(PPDMASYNCCOMPLETIONENDPOINTFILE) pEndpointNext;
389 /** Pointer to the previous endpoint assigned to the manager. */
390 R3PTRTYPE(PPDMASYNCCOMPLETIONENDPOINTFILE) pEndpointPrev;
391 /** List of pending requests (not submitted due to usage restrictions
392 * or a pending flush request) */
393 R3PTRTYPE(PPDMACTASKFILE) pReqsPendingHead;
394 /** Tail of pending requests. */
395 R3PTRTYPE(PPDMACTASKFILE) pReqsPendingTail;
396 /** Tree of currently locked ranges.
397 * If a write task is enqueued the range gets locked and any other
398 * task writing to that range has to wait until the task completes.
399 */
400 PAVLRFOFFTREE pTreeRangesLocked;
401 /** Number of requests currently being processed for this endpoint
402 * (excluded flush requests). */
403 unsigned cRequestsActive;
404 /** Number of requests processed during the last second. */
405 unsigned cReqsPerSec;
406 /** Current number of processed requests for the current update period. */
407 unsigned cReqsProcessed;
408 /** Flag whether the endpoint is about to be moved to another manager. */
409 bool fMoving;
410 /** Destination I/O manager. */
411 PPDMACEPFILEMGR pAioMgrDst;
412 } AioMgr;
413} PDMASYNCCOMPLETIONENDPOINTFILE;
414/** Pointer to the endpoint class data. */
415typedef PDMASYNCCOMPLETIONENDPOINTFILE *PPDMASYNCCOMPLETIONENDPOINTFILE;
416#ifdef VBOX_WITH_STATISTICS
417AssertCompileMemberAlignment(PDMASYNCCOMPLETIONENDPOINTFILE, StatRead, sizeof(uint64_t));
418#endif
419
420/** Request completion function */
421typedef DECLCALLBACK(void) FNPDMACTASKCOMPLETED(PPDMACTASKFILE pTask, void *pvUser, int rc);
422/** Pointer to a request completion function. */
423typedef FNPDMACTASKCOMPLETED *PFNPDMACTASKCOMPLETED;
424
425/**
426 * Transfer type.
427 */
428typedef enum PDMACTASKFILETRANSFER
429{
430 /** Invalid. */
431 PDMACTASKFILETRANSFER_INVALID = 0,
432 /** Read transfer. */
433 PDMACTASKFILETRANSFER_READ,
434 /** Write transfer. */
435 PDMACTASKFILETRANSFER_WRITE,
436 /** Flush transfer. */
437 PDMACTASKFILETRANSFER_FLUSH
438} PDMACTASKFILETRANSFER;
439
440/**
441 * Data of a request.
442 */
443typedef struct PDMACTASKFILE
444{
445 /** Pointer to the range lock we are waiting for */
446 PPDMACFILERANGELOCK pRangeLock;
447 /** Next task in the list. (Depending on the state) */
448 struct PDMACTASKFILE *pNext;
449 /** Endpoint */
450 PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint;
451 /** Transfer type. */
452 PDMACTASKFILETRANSFER enmTransferType;
453 /** Start offset */
454 RTFOFF Off;
455 /** Data segment. */
456 RTSGSEG DataSeg;
457 /** When non-zero the segment uses a bounce buffer because the provided buffer
458 * doesn't meet host requirements. */
459 size_t cbBounceBuffer;
460 /** Pointer to the used bounce buffer if any. */
461 void *pvBounceBuffer;
462 /** Start offset in the bounce buffer to copy from. */
463 uint32_t offBounceBuffer;
464 /** Flag whether this is a prefetch request. */
465 bool fPrefetch;
466 /** Already prepared native I/O request.
467 * Used if the request is prepared already but
468 * was not queued because the host has not enough
469 * resources. */
470 RTFILEAIOREQ hReq;
471 /** Completion function to call on completion. */
472 PFNPDMACTASKCOMPLETED pfnCompleted;
473 /** User data */
474 void *pvUser;
475} PDMACTASKFILE;
476
477/**
478 * Per task data.
479 */
480typedef struct PDMASYNCCOMPLETIONTASKFILE
481{
482 /** Common data. */
483 PDMASYNCCOMPLETIONTASK Core;
484 /** Number of bytes to transfer until this task completes. */
485 volatile int32_t cbTransferLeft;
486 /** Flag whether the task completed. */
487 volatile bool fCompleted;
488 /** Return code. */
489 volatile int rc;
490} PDMASYNCCOMPLETIONTASKFILE;
491
492int pdmacFileAioMgrFailsafe(RTTHREAD ThreadSelf, void *pvUser);
493int pdmacFileAioMgrNormal(RTTHREAD ThreadSelf, void *pvUser);
494
495int pdmacFileAioMgrNormalInit(PPDMACEPFILEMGR pAioMgr);
496void pdmacFileAioMgrNormalDestroy(PPDMACEPFILEMGR pAioMgr);
497
498int pdmacFileAioMgrCreate(PPDMASYNCCOMPLETIONEPCLASSFILE pEpClass, PPPDMACEPFILEMGR ppAioMgr, PDMACEPFILEMGRTYPE enmMgrType);
499
500int pdmacFileAioMgrAddEndpoint(PPDMACEPFILEMGR pAioMgr, PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint);
501
502PPDMACTASKFILE pdmacFileEpGetNewTasks(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint);
503PPDMACTASKFILE pdmacFileTaskAlloc(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint);
504void pdmacFileTaskFree(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint,
505 PPDMACTASKFILE pTask);
506
507int pdmacFileEpAddTask(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, PPDMACTASKFILE pTask);
508
509void pdmacFileEpTaskCompleted(PPDMACTASKFILE pTask, void *pvUser, int rc);
510
511int pdmacFileCacheInit(PPDMASYNCCOMPLETIONEPCLASSFILE pClassFile, PCFGMNODE pCfgNode);
512void pdmacFileCacheDestroy(PPDMASYNCCOMPLETIONEPCLASSFILE pClassFile);
513int pdmacFileEpCacheInit(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, PPDMASYNCCOMPLETIONEPCLASSFILE pClassFile);
514void pdmacFileEpCacheDestroy(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint);
515
516int pdmacFileEpCacheRead(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, PPDMASYNCCOMPLETIONTASKFILE pTask,
517 RTFOFF off, PCRTSGSEG paSegments, size_t cSegments,
518 size_t cbRead);
519int pdmacFileEpCacheWrite(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, PPDMASYNCCOMPLETIONTASKFILE pTask,
520 RTFOFF off, PCRTSGSEG paSegments, size_t cSegments,
521 size_t cbWrite);
522int pdmacFileEpCacheFlush(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint);
523
524RT_C_DECLS_END
525
526#endif
527
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