PDMAsyncCompletionFileInternal.h revision 0ecb3aa3b79c0c4b20b36a21f13bbc47857653db
/* $Id$ */
/** @file
* PDM Async I/O - Transport data asynchronous in R3 using EMT.
*/
/*
* Copyright (C) 2006-2008 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#include <iprt/semaphore.h>
#include <iprt/critsect.h>
#include <iprt/spinlock.h>
#include <iprt/memcache.h>
#include "PDMAsyncCompletionInternal.h"
/** @todo: Revise the caching of tasks. We have currently four caches:
* Per endpoint task cache
* Per class cache
* Per endpoint task segment cache
* Per class task segment cache
*
* We could use the RT heap for this probably or extend MMR3Heap (uses RTMemAlloc
* instead of managing larger blocks) to have this global for the whole VM.
*/
/** Enable for delay injection from the debugger. */
#if 0
# define PDM_ASYNC_COMPLETION_FILE_WITH_DELAY
#endif
/**
* A few forward declarations.
*/
typedef struct PDMASYNCCOMPLETIONENDPOINTFILE *PPDMASYNCCOMPLETIONENDPOINTFILE;
/** Pointer to a request segment. */
typedef struct PDMACTASKFILE *PPDMACTASKFILE;
/** Pointer to the endpoint class data. */
typedef struct PDMASYNCCOMPLETIONTASKFILE *PPDMASYNCCOMPLETIONTASKFILE;
/** Pointer to a cache LRU list. */
typedef struct PDMACFILELRULIST *PPDMACFILELRULIST;
/** Pointer to the global cache structure. */
typedef struct PDMACFILECACHEGLOBAL *PPDMACFILECACHEGLOBAL;
/** Pointer to a task segment. */
typedef struct PDMACFILETASKSEG *PPDMACFILETASKSEG;
/**
* Blocking event types.
*/
typedef enum PDMACEPFILEAIOMGRBLOCKINGEVENT
{
/** Invalid tye */
/** An endpoint is added to the manager. */
/** An endpoint is removed from the manager. */
/** An endpoint is about to be closed. */
/** The manager is requested to terminate */
/** The manager is requested to suspend */
/** The manager is requested to resume */
/** 32bit hack */
PDMACEPFILEAIOMGRBLOCKINGEVENT_32BIT_HACK = 0x7fffffff
/**
* I/O manager type.
*/
typedef enum PDMACEPFILEMGRTYPE
{
/** Simple aka failsafe */
/** Async I/O with host cache enabled. */
/** 32bit hack */
PDMACEPFILEMGRTYPE_32BIT_HACK = 0x7fffffff
/** Pointer to a I/O manager type */
typedef PDMACEPFILEMGRTYPE *PPDMACEPFILEMGRTYPE;
/**
* States of the I/O manager.
*/
typedef enum PDMACEPFILEMGRSTATE
{
/** Invalid state. */
/** Normal running state accepting new requests
* and processing them.
*/
/** Fault state - not accepting new tasks for endpoints but waiting for
* remaining ones to finish.
*/
/** Suspending state - not accepting new tasks for endpoints but waiting
* for remaining ones to finish.
*/
/** Shutdown state - not accepting new tasks for endpoints but waiting
* for remaining ones to finish.
*/
/** The I/O manager waits for all active requests to complete and doesn't queue
* new ones because it needs to grow to handle more requests.
*/
/** 32bit hack */
PDMACEPFILEMGRSTATE_32BIT_HACK = 0x7fffffff
/**
* State of a async I/O manager.
*/
typedef struct PDMACEPFILEMGR
{
/** Next Aio manager in the list. */
/** Previous Aio manager in the list. */
/** Manager type */
/** Current state of the manager. */
/** Event semaphore the manager sleeps on when waiting for new requests. */
/** Flag whether the thread waits in the event semaphore. */
volatile bool fWaitingEventSem;
/** Thread data */
/** The async I/O context for this manager. */
/** Flag whether the I/O manager was woken up. */
volatile bool fWokenUp;
/** List of endpoints assigned to this manager. */
/** Number of endpoints assigned to the manager. */
unsigned cEndpoints;
/** Number of requests active currently. */
unsigned cRequestsActive;
/** Number of maximum requests active. */
/** Pointer to an array of free async I/O request handles. */
/** Index of the next free entry in the cache. */
/** Size of the array. */
unsigned cReqEntries;
/** Memory cache for file range locks. */
/** Number of milliseconds to wait until the bandwidth is refreshed for at least
* one endpoint and it is possible to process more requests. */
/** Critical section protecting the blocking event handling. */
/** Event semaphore for blocking external events.
* The caller waits on it until the async I/O manager
* finished processing the event. */
/** Flag whether a blocking event is pending and needs
* processing by the I/O manager. */
volatile bool fBlockingEventPending;
/** Blocking event type */
/** Event type data */
union
{
/** Add endpoint event. */
struct
{
/** The endpoint to be added */
volatile PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint;
} AddEndpoint;
/** Remove endpoint event. */
struct
{
/** The endpoint to be removed */
volatile PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint;
/** Close endpoint event. */
struct
{
/** The endpoint to be closed */
volatile PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint;
/** Pointer to a async I/O manager state. */
typedef PDMACEPFILEMGR *PPDMACEPFILEMGR;
/** Pointer to a async I/O manager state pointer. */
typedef PPDMACEPFILEMGR *PPPDMACEPFILEMGR;
/**
* A file access range lock.
*/
typedef struct PDMACFILERANGELOCK
{
/** AVL node in the locked range tree of the endpoint. */
/** How many tasks have locked this range. */
/** Flag whether this is a read or write lock. */
bool fReadLock;
/** List of tasks which are waiting that the range gets unlocked. */
/** List of tasks which are waiting that the range gets unlocked. */
/**
* Backend type for the endpoint.
*/
typedef enum PDMACFILEEPBACKEND
{
/** Non buffered. */
/** Buffered (i.e host cache enabled) */
/** 32bit hack */
PDMACFILEEPBACKEND_32BIT_HACK = 0x7fffffff
/** Pointer to a backend type. */
typedef PDMACFILEEPBACKEND *PPDMACFILEEPBACKEND;
/**
* Global data for the file endpoint class.
*/
typedef struct PDMASYNCCOMPLETIONEPCLASSFILE
{
/** Common data. */
/** Override I/O manager type - set to SIMPLE after failure. */
/** Default backend type for the endpoint. */
/** Pointer to the head of the async I/O managers. */
/** Number of async I/O managers currently running. */
unsigned cAioMgrs;
/** Maximum number of segments to cache per endpoint */
unsigned cTasksCacheMax;
/** Maximum number of simultaneous outstandingrequests. */
/** Bitmask for checking the alignment of a buffer. */
/** Flag whether the out of resources warning was printed already. */
/** Pointer to the endpoint class data. */
typedef enum PDMACEPFILEBLOCKINGEVENT
{
/** The invalid event type */
/** A task is about to be canceled */
/** Usual 32bit hack */
PDMACEPFILEBLOCKINGEVENT_32BIT_HACK = 0x7fffffff
/**
* States of the endpoint.
*/
typedef enum PDMASYNCCOMPLETIONENDPOINTFILESTATE
{
/** Invalid state. */
/** Normal running state accepting new requests
* and processing them.
*/
/** The endpoint is about to be closed - not accepting new tasks for endpoints but waiting for
* remaining ones to finish.
*/
/** Removing from current I/O manager state - not processing new tasks for endpoints but waiting
* for remaining ones to finish.
*/
/** The current endpoint will be migrated to another I/O manager. */
/** 32bit hack */
PDMASYNCCOMPLETIONENDPOINTFILESTATE_32BIT_HACK = 0x7fffffff
typedef enum PDMACFILEREQTYPEDELAY
{
PDMACFILEREQTYPEDELAY_32BIT_HACK = 0x7fffffff
/**
* Data for the file endpoint.
*/
typedef struct PDMASYNCCOMPLETIONENDPOINTFILE
{
/** Common data. */
/** Current state of the endpoint. */
/** The backend to use for this endpoint. */
/** async I/O manager this endpoint is assigned to. */
/** Flags for opening the file. */
unsigned fFlags;
/** File handle. */
/** Real size of the file. Only updated if data is appended. */
/** List of new tasks. */
/** Head of the small cache for allocated task segments for exclusive
* use by this endpoint. */
/** Tail of the small cache for allocated task segments for exclusive
* use by this endpoint. */
/** Number of elements in the cache. */
volatile uint32_t cTasksCached;
/** Flag whether a flush request is currently active */
#ifdef VBOX_WITH_STATISTICS
/** Time spend in a read. */
/** Time spend in a write. */
#endif
/** Event semaphore for blocking external events.
* The caller waits on it until the async I/O manager
* finished processing the event. */
/** Flag whether caching is enabled for this file. */
bool fCaching;
/** Flag whether the file was opened readonly. */
bool fReadonly;
/** Flag whether the host supports the async flush API. */
bool fAsyncFlushSupported;
#ifdef VBOX_WITH_DEBUGGER
/** Status code to inject for the next complete read. */
volatile int rcReqRead;
/** Status code to inject for the next complete write. */
volatile int rcReqWrite;
#endif
/** Request delay. */
/** Number of requests to delay. */
volatile uint32_t cReqsDelay;
/** Task type to delay. */
/** The current task which gets delayed. */
#endif
/** Flag whether a blocking event is pending and needs
* processing by the I/O manager. */
bool fBlockingEventPending;
/** Blocking event type */
/** Additional data needed for the event types. */
union
{
/** Cancelation event. */
struct
{
/** The task to cancel. */
} Cancel;
/** Data for exclusive use by the assigned async I/O manager. */
struct
{
/** Pointer to the next endpoint assigned to the manager. */
/** Pointer to the previous endpoint assigned to the manager. */
/** List of pending requests (not submitted due to usage restrictions
* or a pending flush request) */
/** Tail of pending requests. */
/** Tree of currently locked ranges.
* If a write task is enqueued the range gets locked and any other
* task writing to that range has to wait until the task completes.
*/
/** Number of requests currently being processed for this endpoint
* (excluded flush requests). */
unsigned cRequestsActive;
/** Number of requests processed during the last second. */
unsigned cReqsPerSec;
/** Current number of processed requests for the current update period. */
unsigned cReqsProcessed;
/** Flag whether the endpoint is about to be moved to another manager. */
bool fMoving;
/** Destination I/O manager. */
} AioMgr;
/** Pointer to the endpoint class data. */
#ifdef VBOX_WITH_STATISTICS
#endif
/** Request completion function */
/** Pointer to a request completion function. */
typedef FNPDMACTASKCOMPLETED *PFNPDMACTASKCOMPLETED;
/**
* Transfer type.
*/
typedef enum PDMACTASKFILETRANSFER
{
/** Invalid. */
/** Read transfer. */
/** Write transfer. */
/** Flush transfer. */
/**
* Data of a request.
*/
typedef struct PDMACTASKFILE
{
/** Pointer to the range lock we are waiting for */
/** Next task in the list. (Depending on the state) */
struct PDMACTASKFILE *pNext;
/** Endpoint */
/** Transfer type. */
/** Start offset */
/** Data segment. */
/** When non-zero the segment uses a bounce buffer because the provided buffer
* doesn't meet host requirements. */
/** Pointer to the used bounce buffer if any. */
void *pvBounceBuffer;
/** Start offset in the bounce buffer to copy from. */
/** Flag whether this is a prefetch request. */
bool fPrefetch;
/** Already prepared native I/O request.
* Used if the request is prepared already but
* was not queued because the host has not enough
* resources. */
/** Completion function to call on completion. */
/** User data */
void *pvUser;
/**
* Per task data.
*/
typedef struct PDMASYNCCOMPLETIONTASKFILE
{
/** Common data. */
/** Number of bytes to transfer until this task completes. */
volatile int32_t cbTransferLeft;
/** Flag whether the task completed. */
volatile bool fCompleted;
/** Return code. */
volatile int rc;
volatile PPDMASYNCCOMPLETIONTASKFILE pDelayedNext;
/** Timestamp when the delay expires. */
#endif
int pdmacFileAioMgrCreate(PPDMASYNCCOMPLETIONEPCLASSFILE pEpClass, PPPDMACEPFILEMGR ppAioMgr, PDMACEPFILEMGRTYPE enmMgrType);
int pdmacFileEpCacheInit(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, PPDMASYNCCOMPLETIONEPCLASSFILE pClassFile);
int pdmacFileEpCacheRead(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, PPDMASYNCCOMPLETIONTASKFILE pTask,
int pdmacFileEpCacheWrite(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, PPDMASYNCCOMPLETIONTASKFILE pTask,
#endif