527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/* $Id$ */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/** @file
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * IPRT - Async I/O manager.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/*
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * Copyright (C) 2013 Oracle Corporation
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync *
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * available from http://www.virtualbox.org. This file is free software;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * you can redistribute it and/or modify it under the terms of the GNU
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * General Public License (GPL) as published by the Free Software
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync *
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * The contents of this file may alternatively be used under the terms
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * of the Common Development and Distribution License Version 1.0
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * VirtualBox OSE distribution, in which case the provisions of the
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * CDDL are applicable instead of those of the GPL.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync *
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * You may elect to license modified versions of this file under the
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * terms and conditions of either the GPL or the CDDL or both.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/*******************************************************************************
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync* Header Files *
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync*******************************************************************************/
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync#include <iprt/aiomgr.h>
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync#include <iprt/err.h>
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync#include <iprt/asm.h>
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync#include <iprt/mem.h>
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync#include <iprt/file.h>
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync#include <iprt/list.h>
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync#include <iprt/thread.h>
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync#include <iprt/assert.h>
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync#include <iprt/string.h>
377d3eefbc092f9d4220535d896c510d560bbd74vboxsync#include <iprt/critsect.h>
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync#include <iprt/memcache.h>
377d3eefbc092f9d4220535d896c510d560bbd74vboxsync#include <iprt/semaphore.h>
377d3eefbc092f9d4220535d896c510d560bbd74vboxsync#include <iprt/queueatomic.h>
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync#include "internal/magics.h"
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/*******************************************************************************
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync* Structures and Typedefs *
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync*******************************************************************************/
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/** Pointer to an internal async I/O file instance. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsynctypedef struct RTAIOMGRFILEINT *PRTAIOMGRFILEINT;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/**
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * Blocking event types.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsynctypedef enum RTAIOMGREVENT
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync{
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Invalid tye */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync RTAIOMGREVENT_INVALID = 0,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** No event pending. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTAIOMGREVENT_NO_EVENT,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** A file is added to the manager. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTAIOMGREVENT_FILE_ADD,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** A file is about to be closed. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTAIOMGREVENT_FILE_CLOSE,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** The async I/O manager is shut down. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTAIOMGREVENT_SHUTDOWN,
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** 32bit hack */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync RTAIOMGREVENT_32BIT_HACK = 0x7fffffff
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync} RTAIOMGREVENT;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/**
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * Async I/O manager instance data.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsynctypedef struct RTAIOMGRINT
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync{
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Magic value. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync uint32_t u32Magic;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Reference count. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync volatile uint32_t cRefs;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Async I/O context handle. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync RTFILEAIOCTX hAioCtx;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** async I/O thread. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync RTTHREAD hThread;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** List of files assigned to this manager. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTLISTANCHOR ListFiles;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Number of requests active currently. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync unsigned cReqsActive;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Number of maximum requests active. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync uint32_t cReqsActiveMax;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Memory cache for requests. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTMEMCACHE hMemCacheReqs;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Critical section protecting the blocking event handling. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync RTCRITSECT CritSectBlockingEvent;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Event semaphore for blocking external events.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * The caller waits on it until the async I/O manager
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * finished processing the event. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTSEMEVENT hEventSemBlock;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Blocking event type */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync volatile RTAIOMGREVENT enmBlockingEvent;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Event type data */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync union
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync {
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** The file to be added */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync volatile PRTAIOMGRFILEINT pFileAdd;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** The file to be closed */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync volatile PRTAIOMGRFILEINT pFileClose;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync } BlockingEventData;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync} RTAIOMGRINT;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/** Pointer to an internal async I/O manager instance. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsynctypedef RTAIOMGRINT *PRTAIOMGRINT;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/**
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * Async I/O manager file instance data.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsynctypedef struct RTAIOMGRFILEINT
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync{
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Magic value. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync uint32_t u32Magic;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Reference count. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync volatile uint32_t cRefs;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Flags. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync uint32_t fFlags;
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync /** Opaque user data passed on creation. */
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync void *pvUser;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** File handle. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync RTFILE hFile;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** async I/O manager this file belongs to. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync PRTAIOMGRINT pAioMgr;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Work queue for new requests. */
377d3eefbc092f9d4220535d896c510d560bbd74vboxsync RTQUEUEATOMIC QueueReqs;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Completion callback for this file. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PFNRTAIOMGRREQCOMPLETE pfnReqCompleted;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Data for exclusive use by the assigned async I/O manager. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync struct
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** List node of assigned files for a async I/O manager. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTLISTNODE NodeAioMgrFiles;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** List of requests waiting for submission. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTLISTANCHOR ListWaitingReqs;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync /** Number of requests currently being processed for this endpoint
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * (excluded flush requests). */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync unsigned cReqsActive;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync } AioMgr;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync} RTAIOMGRFILEINT;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/** Flag whether the file is closed. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync#define RTAIOMGRFILE_FLAGS_CLOSING RT_BIT_32(1)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Request type.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsynctypedef enum RTAIOMGRREQTYPE
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Invalid request type. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTAIOMGRREQTYPE_INVALID = 0,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Read reques type. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTAIOMGRREQTYPE_READ,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Write request. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTAIOMGRREQTYPE_WRITE,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Flush request. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTAIOMGRREQTYPE_FLUSH,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Prefetech request. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTAIOMGRREQTYPE_PREFETCH,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** 32bit hack. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTAIOMGRREQTYPE_32BIT_HACK = 0x7fffffff
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync} RTAIOMGRREQTYPE;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/** Pointer to a reques type. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsynctypedef RTAIOMGRREQTYPE *PRTAIOMGRREQTYPE;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Async I/O manager request.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsynctypedef struct RTAIOMGRREQ
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Atomic queue work item. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTQUEUEATOMICITEM WorkItem;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Node for a waiting list. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTLISTNODE NodeWaitingList;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Request flags. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync uint32_t fFlags;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Transfer type. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTAIOMGRREQTYPE enmType;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Assigned file request. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTFILEAIOREQ hReqIo;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** File the request belongs to. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRFILEINT pFile;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Opaque user data. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync void *pvUser;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Start offset */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTFOFF off;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Data segment. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTSGSEG DataSeg;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** When non-zero the segment uses a bounce buffer because the provided buffer
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * doesn't meet host requirements. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync size_t cbBounceBuffer;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Pointer to the used bounce buffer if any. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync void *pvBounceBuffer;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** Start offset in the bounce buffer to copy from. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync uint32_t offBounceBuffer;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync} RTAIOMGRREQ;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/** Pointer to a I/O manager request. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsynctypedef RTAIOMGRREQ *PRTAIOMGRREQ;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/** Flag whether the request was prepared already. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync#define RTAIOMGRREQ_FLAGS_PREPARED RT_BIT_32(0)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/*******************************************************************************
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync* Defined Constants And Macros *
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync*******************************************************************************/
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/** Validates a handle and returns VERR_INVALID_HANDLE if not valid. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync#define RTAIOMGR_VALID_RETURN_RC(a_hAioMgr, a_rc) \
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync do { \
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertPtrReturn((a_hAioMgr), (a_rc)); \
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertReturn((a_hAioMgr)->u32Magic == RTAIOMGR_MAGIC, (a_rc)); \
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync } while (0)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/** Validates a handle and returns VERR_INVALID_HANDLE if not valid. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync#define RTAIOMGR_VALID_RETURN(a_hAioMgr) RTAIOMGR_VALID_RETURN_RC((hAioMgr), VERR_INVALID_HANDLE)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/** Validates a handle and returns (void) if not valid. */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync#define RTAIOMGR_VALID_RETURN_VOID(a_hAioMgr) \
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync do { \
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertPtrReturnVoid(a_hAioMgr); \
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertReturnVoid((a_hAioMgr)->u32Magic == RTAIOMGR_MAGIC); \
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync } while (0)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/*******************************************************************************
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync* Internal Functions *
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync*******************************************************************************/
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrReqsEnqueue(PRTAIOMGRINT pThis, PRTAIOMGRFILEINT pFile,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTFILEAIOREQ pahReqs, unsigned cReqs);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Removes an endpoint from the currently assigned manager.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync *
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns TRUE if there are still requests pending on the current manager for this endpoint.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * FALSE otherwise.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pEndpointRemove The endpoint to remove.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic bool rtAioMgrFileRemove(PRTAIOMGRFILEINT pFile)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Make sure that there is no request pending on this manager for the endpoint. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (!pFile->AioMgr.cReqsActive)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTListNodeRemove(&pFile->AioMgr.NodeAioMgrFiles);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return false;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return true;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Allocate a new I/O request.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync *
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns Pointer to the allocated request or NULL if out of memory.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager instance.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic PRTAIOMGRREQ rtAioMgrReqAlloc(PRTAIOMGRINT pThis)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return (PRTAIOMGRREQ)RTMemCacheAlloc(pThis->hMemCacheReqs);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Frees an I/O request.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync *
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns nothing.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager instance.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pReq The request to free.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic void rtAioMgrReqFree(PRTAIOMGRINT pThis, PRTAIOMGRREQ pReq)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (pReq->cbBounceBuffer)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertPtr(pReq->pvBounceBuffer);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTMemPageFree(pReq->pvBounceBuffer, pReq->cbBounceBuffer);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->pvBounceBuffer = NULL;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->cbBounceBuffer = 0;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->fFlags = 0;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTAioMgrFileRelease(pReq->pFile);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTMemCacheFree(pThis->hMemCacheReqs, pReq);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic void rtAioMgrReqCompleteRc(PRTAIOMGRINT pThis, PRTAIOMGRREQ pReq,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rcReq, size_t cbTransfered)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rc = VINF_SUCCESS;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRFILEINT pFile;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pFile = pReq->pFile;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pThis->cReqsActive--;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pFile->AioMgr.cReqsActive--;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /*
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * It is possible that the request failed on Linux with kernels < 2.6.23
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * if the passed buffer was allocated with remap_pfn_range or if the file
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * is on an NFS endpoint which does not support async and direct I/O at the same time.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * The endpoint will be migrated to a failsafe manager in case a request fails.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (RT_FAILURE(rcReq))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pFile->pfnReqCompleted(pFile, rcReq, pReq->pvUser);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rtAioMgrReqFree(pThis, pReq);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /*
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Restart an incomplete transfer.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * This usually means that the request will return an error now
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * but to get the cause of the error (disk full, file too big, I/O error, ...)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * the transfer needs to be continued.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (RT_UNLIKELY( cbTransfered < pReq->DataSeg.cbSeg
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync || ( pReq->cbBounceBuffer
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync && cbTransfered < pReq->cbBounceBuffer)))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTFOFF offStart;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync size_t cbToTransfer;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync uint8_t *pbBuf = NULL;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync Assert(cbTransfered % 512 == 0);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (pReq->cbBounceBuffer)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertPtr(pReq->pvBounceBuffer);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync offStart = (pReq->off & ~((RTFOFF)512-1)) + cbTransfered;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync cbToTransfer = pReq->cbBounceBuffer - cbTransfered;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pbBuf = (uint8_t *)pReq->pvBounceBuffer + cbTransfered;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync Assert(!pReq->pvBounceBuffer);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync offStart = pReq->off + cbTransfered;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync cbToTransfer = pReq->DataSeg.cbSeg - cbTransfered;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pbBuf = (uint8_t *)pReq->DataSeg.pvSeg + cbTransfered;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if ( pReq->enmType == RTAIOMGRREQTYPE_PREFETCH
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync || pReq->enmType == RTAIOMGRREQTYPE_READ)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = RTFileAioReqPrepareRead(pReq->hReqIo, pFile->hFile, offStart,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pbBuf, cbToTransfer, pReq);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(pReq->enmType == RTAIOMGRREQTYPE_WRITE,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ("Invalid transfer type\n"));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = RTFileAioReqPrepareWrite(pReq->hReqIo, pFile->hFile, offStart,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pbBuf, cbToTransfer, pReq);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertRC(rc);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrReqsEnqueue(pThis, pFile, &pReq->hReqIo, 1);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(RT_SUCCESS(rc) || (rc == VERR_FILE_AIO_INSUFFICIENT_RESSOURCES),
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ("Unexpected return code rc=%Rrc\n", rc));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else if (pReq->enmType == RTAIOMGRREQTYPE_PREFETCH)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync Assert(pReq->cbBounceBuffer);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->enmType = RTAIOMGRREQTYPE_WRITE;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync memcpy(((uint8_t *)pReq->pvBounceBuffer) + pReq->offBounceBuffer,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->DataSeg.pvSeg,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->DataSeg.cbSeg);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Write it now. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTFOFF offStart = pReq->off & ~(RTFOFF)(512-1);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync size_t cbToTransfer = RT_ALIGN_Z(pReq->DataSeg.cbSeg + (pReq->off - offStart), 512);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = RTFileAioReqPrepareWrite(pReq->hReqIo, pFile->hFile,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync offStart, pReq->pvBounceBuffer, cbToTransfer, pReq);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertRC(rc);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrReqsEnqueue(pThis, pFile, &pReq->hReqIo, 1);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(RT_SUCCESS(rc) || (rc == VERR_FILE_AIO_INSUFFICIENT_RESSOURCES),
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ("Unexpected return code rc=%Rrc\n", rc));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (RT_SUCCESS(rc) && pReq->cbBounceBuffer)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (pReq->enmType == RTAIOMGRREQTYPE_READ)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync memcpy(pReq->DataSeg.pvSeg,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ((uint8_t *)pReq->pvBounceBuffer) + pReq->offBounceBuffer,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->DataSeg.cbSeg);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Call completion callback */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pFile->pfnReqCompleted(pFile, rcReq, pReq->pvUser);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rtAioMgrReqFree(pThis, pReq);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync } /* request completed successfully */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Wrapper around rtAioMgrReqCompleteRc().
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic void rtAioMgrReqComplete(PRTAIOMGRINT pThis, RTFILEAIOREQ hReq)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync size_t cbTransfered = 0;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rcReq = RTFileAioReqGetRC(hReq, &cbTransfered);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRREQ pReq = (PRTAIOMGRREQ)RTFileAioReqGetUser(hReq);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rtAioMgrReqCompleteRc(pThis, pReq, rcReq, cbTransfered);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Wrapper around RTFIleAioCtxSubmit() which is also doing error handling.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrReqsEnqueue(PRTAIOMGRINT pThis, PRTAIOMGRFILEINT pFile,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTFILEAIOREQ pahReqs, unsigned cReqs)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pThis->cReqsActive += cReqs;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pFile->AioMgr.cReqsActive += cReqs;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rc = RTFileAioCtxSubmit(pThis->hAioCtx, pahReqs, cReqs);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (RT_FAILURE(rc))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (rc == VERR_FILE_AIO_INSUFFICIENT_RESSOURCES)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Append any not submitted task to the waiting list. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync for (size_t i = 0; i < cReqs; i++)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rcReq = RTFileAioReqGetRC(pahReqs[i], NULL);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (rcReq != VERR_FILE_AIO_IN_PROGRESS)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRREQ pReq = (PRTAIOMGRREQ)RTFileAioReqGetUser(pahReqs[i]);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync Assert(pReq->hReqIo == pahReqs[i]);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTListAppend(&pFile->AioMgr.ListWaitingReqs, &pReq->NodeWaitingList);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pThis->cReqsActive--;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pFile->AioMgr.cReqsActive--;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pThis->cReqsActiveMax = pThis->cReqsActive;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = VINF_SUCCESS;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else /* Another kind of error happened (full disk, ...) */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* An error happened. Find out which one caused the error and resubmit all other tasks. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync for (size_t i = 0; i < cReqs; i++)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRREQ pReq = (PRTAIOMGRREQ)RTFileAioReqGetUser(pahReqs[i]);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rcReq = RTFileAioReqGetRC(pahReqs[i], NULL);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (rcReq == VERR_FILE_AIO_NOT_SUBMITTED)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* We call ourself again to do any error handling which might come up now. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrReqsEnqueue(pThis, pFile, &pahReqs[i], 1);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertRC(rc);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else if (rcReq != VERR_FILE_AIO_IN_PROGRESS)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rtAioMgrReqCompleteRc(pThis, pReq, rcReq, 0);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return VINF_SUCCESS;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Adds a list of requests to the waiting list.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync *
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns nothing.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pFile The file instance to add the requests to.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pReqsHead The head of the request list to add.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic void rtAioMgrFileAddReqsToWaitingList(PRTAIOMGRFILEINT pFile, PRTAIOMGRREQ pReqsHead)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync while (pReqsHead)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRREQ pReqCur = pReqsHead;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReqsHead = (PRTAIOMGRREQ)pReqsHead->WorkItem.pNext;
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync pReqCur->WorkItem.pNext = NULL;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTListAppend(&pFile->AioMgr.ListWaitingReqs, &pReqCur->NodeWaitingList);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Prepare the native I/o request ensuring that all alignment prerequisites of
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * the host are met.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync *
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT statuse code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pFile The file instance data.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pReq The request to prepare.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrReqPrepareNonBuffered(PRTAIOMGRFILEINT pFile, PRTAIOMGRREQ pReq)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rc = VINF_SUCCESS;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTFOFF offStart = pReq->off & ~(RTFOFF)(512-1);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync size_t cbToTransfer = RT_ALIGN_Z(pReq->DataSeg.cbSeg + (pReq->off - offStart), 512);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync void *pvBuf = pReq->DataSeg.pvSeg;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync bool fAlignedReq = cbToTransfer == pReq->DataSeg.cbSeg
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync && offStart == pReq->off;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /*
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Check if the alignment requirements are met.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Offset, transfer size and buffer address
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * need to be on a 512 boundary.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if ( !fAlignedReq
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** @todo: || ((pEpClassFile->uBitmaskAlignment & (RTR3UINTPTR)pvBuf) != (RTR3UINTPTR)pvBuf) */)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Create bounce buffer. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->cbBounceBuffer = cbToTransfer;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(pReq->off >= offStart, ("Overflow in calculation off=%llu offStart=%llu\n",
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->off, offStart));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->offBounceBuffer = pReq->off - offStart;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** @todo: I think we need something like a RTMemAllocAligned method here.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Current assumption is that the maximum alignment is 4096byte
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * (GPT disk on Windows)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * so we can use RTMemPageAlloc here.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->pvBounceBuffer = RTMemPageAlloc(cbToTransfer);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (RT_LIKELY(pReq->pvBounceBuffer))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pvBuf = pReq->pvBounceBuffer;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (pReq->enmType == RTAIOMGRREQTYPE_WRITE)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if ( RT_UNLIKELY(cbToTransfer != pReq->DataSeg.cbSeg)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync || RT_UNLIKELY(offStart != pReq->off))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* We have to fill the buffer first before we can update the data. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->enmType = RTAIOMGRREQTYPE_WRITE;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync memcpy(pvBuf, pReq->DataSeg.pvSeg, pReq->DataSeg.cbSeg);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = VERR_NO_MEMORY;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->cbBounceBuffer = 0;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (RT_SUCCESS(rc))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (pReq->enmType == RTAIOMGRREQTYPE_WRITE)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = RTFileAioReqPrepareWrite(pReq->hReqIo, pFile->hFile,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync offStart, pvBuf, cbToTransfer, pReq);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else /* Read or prefetch request. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = RTFileAioReqPrepareRead(pReq->hReqIo, pFile->hFile,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync offStart, pvBuf, cbToTransfer, pReq);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertRC(rc);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->fFlags |= RTAIOMGRREQ_FLAGS_PREPARED;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return rc;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Prepare a new request for enqueuing.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync *
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pReq The request to prepare.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param phReqIo Where to store the handle to the native I/O request on success.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrPrepareReq(PRTAIOMGRREQ pReq, PRTFILEAIOREQ phReqIo)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rc = VINF_SUCCESS;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRFILEINT pFile = pReq->pFile;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync switch (pReq->enmType)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync case RTAIOMGRREQTYPE_FLUSH:
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = RTFileAioReqPrepareFlush(pReq->hReqIo, pFile->hFile, pReq);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync break;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync case RTAIOMGRREQTYPE_READ:
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync case RTAIOMGRREQTYPE_WRITE:
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrReqPrepareNonBuffered(pFile, pReq);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync break;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync default:
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsgFailed(("Invalid transfer type %d\n", pReq->enmType));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync } /* switch transfer type */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (RT_SUCCESS(rc))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync *phReqIo = pReq->hReqIo;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return rc;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Prepare newly submitted requests for processing.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync *
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager instance data.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pFile The file instance.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pReqsNew The list of new requests to prepare.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrPrepareNewReqs(PRTAIOMGRINT pThis,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRFILEINT pFile,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRREQ pReqsNew)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTFILEAIOREQ apReqs[20];
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync unsigned cRequests = 0;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rc = VINF_SUCCESS;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Go through the list and queue the requests. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync while ( pReqsNew
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync && (pThis->cReqsActive + cRequests < pThis->cReqsActiveMax)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync && RT_SUCCESS(rc))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRREQ pCurr = pReqsNew;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReqsNew = (PRTAIOMGRREQ)pReqsNew->WorkItem.pNext;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pCurr->WorkItem.pNext = NULL;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(VALID_PTR(pCurr->pFile) && (pCurr->pFile == pFile),
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ("Files do not match\n"));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(!(pCurr->fFlags & RTAIOMGRREQ_FLAGS_PREPARED),
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ("Request on the new list is already prepared\n"));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrPrepareReq(pCurr, &apReqs[cRequests]);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (RT_FAILURE(rc))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rtAioMgrReqCompleteRc(pThis, pCurr, rc, 0);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync cRequests++;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Queue the requests if the array is full. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (cRequests == RT_ELEMENTS(apReqs))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrReqsEnqueue(pThis, pFile, apReqs, cRequests);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync cRequests = 0;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(RT_SUCCESS(rc) || (rc == VERR_FILE_AIO_INSUFFICIENT_RESSOURCES),
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ("Unexpected return code\n"));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (cRequests)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrReqsEnqueue(pThis, pFile, apReqs, cRequests);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(RT_SUCCESS(rc) || (rc == VERR_FILE_AIO_INSUFFICIENT_RESSOURCES),
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ("Unexpected return code rc=%Rrc\n", rc));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (pReqsNew)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Add the rest of the tasks to the pending list */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rtAioMgrFileAddReqsToWaitingList(pFile, pReqsNew);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Insufficient resources are not fatal. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (rc == VERR_FILE_AIO_INSUFFICIENT_RESSOURCES)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = VINF_SUCCESS;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return rc;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Queues waiting requests.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync *
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager instance data.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pFile The file to get the requests from.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrQueueWaitingReqs(PRTAIOMGRINT pThis, PRTAIOMGRFILEINT pFile)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTFILEAIOREQ apReqs[20];
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync unsigned cRequests = 0;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rc = VINF_SUCCESS;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRREQ pReqIt;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRREQ pReqItNext;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Go through the list and queue the requests. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTListForEachSafe(&pFile->AioMgr.ListWaitingReqs, pReqIt, pReqItNext, RTAIOMGRREQ, NodeWaitingList)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTListNodeRemove(&pReqIt->NodeWaitingList);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(VALID_PTR(pReqIt->pFile) && (pReqIt->pFile == pFile),
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ("Files do not match\n"));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (!(pReqIt->fFlags & RTAIOMGRREQ_FLAGS_PREPARED))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrPrepareReq(pReqIt, &apReqs[cRequests]);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (RT_FAILURE(rc))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rtAioMgrReqCompleteRc(pThis, pReqIt, rc, 0);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync cRequests++;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync apReqs[cRequests] = pReqIt->hReqIo;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync cRequests++;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Queue the requests if the array is full. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (cRequests == RT_ELEMENTS(apReqs))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrReqsEnqueue(pThis, pFile, apReqs, cRequests);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync cRequests = 0;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(RT_SUCCESS(rc) || (rc == VERR_FILE_AIO_INSUFFICIENT_RESSOURCES),
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ("Unexpected return code\n"));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (cRequests)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrReqsEnqueue(pThis, pFile, apReqs, cRequests);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(RT_SUCCESS(rc) || (rc == VERR_FILE_AIO_INSUFFICIENT_RESSOURCES),
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ("Unexpected return code rc=%Rrc\n", rc));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Insufficient resources are not fatal. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (rc == VERR_FILE_AIO_INSUFFICIENT_RESSOURCES)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = VINF_SUCCESS;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return rc;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Adds all pending requests for the given file.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync *
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager instance data.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pFile The file to get the requests from.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrQueueReqs(PRTAIOMGRINT pThis, PRTAIOMGRFILEINT pFile)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rc = VINF_SUCCESS;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRFILEINT pReqsHead = NULL;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Check the pending list first */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (!RTListIsEmpty(&pFile->AioMgr.ListWaitingReqs))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrQueueWaitingReqs(pThis, pFile);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if ( RT_SUCCESS(rc)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync && RTListIsEmpty(&pFile->AioMgr.ListWaitingReqs))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRREQ pReqsNew = (PRTAIOMGRREQ)RTQueueAtomicRemoveAll(&pFile->QueueReqs);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (pReqsNew)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrPrepareNewReqs(pThis, pFile, pReqsNew);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertRC(rc);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return rc;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Checks all files for new requests.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync *
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The I/O manager instance data.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrCheckFiles(PRTAIOMGRINT pThis)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rc = VINF_SUCCESS;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRFILEINT pIt;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTListForEach(&pThis->ListFiles, pIt, RTAIOMGRFILEINT, AioMgr.NodeAioMgrFiles)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrQueueReqs(pThis, pIt);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (RT_FAILURE(rc))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return rc;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return rc;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Process a blocking event from the outside.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync *
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager instance data.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrProcessBlockingEvent(PRTAIOMGRINT pThis)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rc = VINF_SUCCESS;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync bool fNotifyWaiter = false;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync switch (pThis->enmBlockingEvent)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync case RTAIOMGREVENT_NO_EVENT:
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Nothing to do. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync break;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync case RTAIOMGREVENT_FILE_ADD:
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRFILEINT pFile = ASMAtomicReadPtrT(&pThis->BlockingEventData.pFileAdd, PRTAIOMGRFILEINT);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(VALID_PTR(pFile), ("Adding file event without a file to add\n"));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTListAppend(&pThis->ListFiles, &pFile->AioMgr.NodeAioMgrFiles);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync fNotifyWaiter = true;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync break;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync case RTAIOMGREVENT_FILE_CLOSE:
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRFILEINT pFile = ASMAtomicReadPtrT(&pThis->BlockingEventData.pFileClose, PRTAIOMGRFILEINT);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertMsg(VALID_PTR(pFile), ("Close file event without a file to close\n"));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (!(pFile->fFlags & RTAIOMGRFILE_FLAGS_CLOSING))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Make sure all requests finished. Process the queues a last time first. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrQueueReqs(pThis, pFile);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertRC(rc);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pFile->fFlags |= RTAIOMGRFILE_FLAGS_CLOSING;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync fNotifyWaiter = !rtAioMgrFileRemove(pFile);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else if (!pFile->AioMgr.cReqsActive)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync fNotifyWaiter = true;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync break;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync case RTAIOMGREVENT_SHUTDOWN:
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (!pThis->cReqsActive)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync fNotifyWaiter = true;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync break;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync default:
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertReleaseMsgFailed(("Invalid event type %d\n", pThis->enmBlockingEvent));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (fNotifyWaiter)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Release the waiting thread. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = RTSemEventSignal(pThis->hEventSemBlock);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertRC(rc);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return rc;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/**
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * async I/O manager worker loop.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync *
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * @returns IPRT status code.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * @param hThreadSelf The thread handle this worker belongs to.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * @param pvUser Opaque user data (Pointer to async I/O manager instance).
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsyncstatic DECLCALLBACK(int) rtAioMgrWorker(RTTHREAD hThreadSelf, void *pvUser)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync{
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync PRTAIOMGRINT pThis = (PRTAIOMGRINT)pvUser;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync bool fRunning = true;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rc = VINF_SUCCESS;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync do
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync {
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync uint32_t cReqsCompleted = 0;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync RTFILEAIOREQ ahReqsCompleted[32];
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = RTFileAioCtxWait(pThis->hAioCtx, 1, RT_INDEFINITE_WAIT, &ahReqsCompleted[0],
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RT_ELEMENTS(ahReqsCompleted), &cReqsCompleted);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (rc == VERR_INTERRUPTED)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Process external event. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rtAioMgrProcessBlockingEvent(pThis);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrCheckFiles(pThis);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else if (RT_FAILURE(rc))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Something bad happened. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** @todo: */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Requests completed. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync for (uint32_t i = 0; i < cReqsCompleted; i++)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rtAioMgrReqComplete(pThis, ahReqsCompleted[i]);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Check files for new requests and queue waiting requests. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrCheckFiles(pThis);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync } while ( fRunning
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync && RT_SUCCESS(rc));
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return rc;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Wakes up the async I/O manager.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync *
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrWakeup(PRTAIOMGRINT pThis)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return RTFileAioCtxWakeup(pThis->hAioCtx);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Waits until the async I/O manager handled the given event.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync *
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param enmEvent The event to pass to the manager.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrWaitForBlockingEvent(PRTAIOMGRINT pThis, RTAIOMGREVENT enmEvent)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync Assert(pThis->enmBlockingEvent == RTAIOMGREVENT_NO_EVENT);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ASMAtomicWriteU32((volatile uint32_t *)&pThis->enmBlockingEvent, enmEvent);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Wakeup the async I/O manager */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rc = rtAioMgrWakeup(pThis);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (RT_FAILURE(rc))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return rc;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Wait for completion. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = RTSemEventWait(pThis->hEventSemBlock, RT_INDEFINITE_WAIT);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertRC(rc);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ASMAtomicWriteU32((volatile uint32_t *)&pThis->enmBlockingEvent, RTAIOMGREVENT_NO_EVENT);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return rc;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Add a given file to the given I/O manager.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync *
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pFile The file to add.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrAddFile(PRTAIOMGRINT pThis, PRTAIOMGRFILEINT pFile)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /* Update the assigned I/O manager. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ASMAtomicWritePtr(&pFile->pAioMgr, pThis);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rc = RTCritSectEnter(&pThis->CritSectBlockingEvent);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertRCReturn(rc, rc);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ASMAtomicWritePtr(&pThis->BlockingEventData.pFileAdd, pFile);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrWaitForBlockingEvent(pThis, RTAIOMGREVENT_FILE_ADD);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ASMAtomicWriteNullPtr(&pThis->BlockingEventData.pFileAdd);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTCritSectLeave(&pThis->CritSectBlockingEvent);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return rc;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Removes a given file from the given I/O manager.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync *
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pFile The file to remove.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrCloseFile(PRTAIOMGRINT pThis, PRTAIOMGRFILEINT pFile)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rc = RTCritSectEnter(&pThis->CritSectBlockingEvent);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertRCReturn(rc, rc);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ASMAtomicWritePtr(&pThis->BlockingEventData.pFileClose, pFile);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrWaitForBlockingEvent(pThis, RTAIOMGREVENT_FILE_CLOSE);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync ASMAtomicWriteNullPtr(&pThis->BlockingEventData.pFileClose);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTCritSectLeave(&pThis->CritSectBlockingEvent);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return rc;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Process a shutdown event.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync *
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pThis The async I/O manager to shut down.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrShutdown(PRTAIOMGRINT pThis)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rc = RTCritSectEnter(&pThis->CritSectBlockingEvent);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertRCReturn(rc, rc);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrWaitForBlockingEvent(pThis, RTAIOMGREVENT_SHUTDOWN);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTCritSectLeave(&pThis->CritSectBlockingEvent);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return rc;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync}
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/**
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * Destroys an async I/O manager.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync *
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * @returns nothing.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * @param pThis The async I/O manager instance to destroy.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsyncstatic void rtAioMgrDestroy(PRTAIOMGRINT pThis)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync{
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync int rc;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = rtAioMgrShutdown(pThis);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertRC(rc);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync rc = RTThreadWait(pThis->hThread, RT_INDEFINITE_WAIT, NULL);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertRC(rc);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync rc = RTFileAioCtxDestroy(pThis->hAioCtx);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertRC(rc);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = RTMemCacheDestroy(pThis->hMemCacheReqs);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertRC(rc);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pThis->hThread = NIL_RTTHREAD;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pThis->hAioCtx = NIL_RTFILEAIOCTX;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pThis->hMemCacheReqs = NIL_RTMEMCACHE;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pThis->u32Magic = ~RTAIOMGR_MAGIC;
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync RTCritSectDelete(&pThis->CritSectBlockingEvent);
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync RTSemEventDestroy(pThis->hEventSemBlock);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync RTMemFree(pThis);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync}
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Queues a new request for processing.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic void rtAioMgrFileQueueReq(PRTAIOMGRFILEINT pThis, PRTAIOMGRREQ pReq)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTAioMgrFileRetain(pThis);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTQueueAtomicInsert(&pThis->QueueReqs, &pReq->WorkItem);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rtAioMgrWakeup(pThis->pAioMgr);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync/**
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * Destroys an async I/O manager file.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync *
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * @returns nothing.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync * @param pThis The async I/O manager file.
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync */
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsyncstatic void rtAioMgrFileDestroy(PRTAIOMGRFILEINT pThis)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync{
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync pThis->u32Magic = ~RTAIOMGRFILE_MAGIC;
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync rtAioMgrCloseFile(pThis->pAioMgr, pThis);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTAioMgrRelease(pThis->pAioMgr);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync RTMemFree(pThis);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync}
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Queues a new I/O request.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync *
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param hAioMgrFile The I/O manager file handle.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param off Start offset of the I/o request.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pSgBuf Data S/G buffer.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param cbIo How much to transfer.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pvUser Opaque user data.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param enmType I/O direction type (read/write).
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic int rtAioMgrFileIoReqCreate(RTAIOMGRFILE hAioMgrFile, RTFOFF off, PRTSGBUF pSgBuf,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync size_t cbIo, void *pvUser, RTAIOMGRREQTYPE enmType)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rc;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRFILEINT pFile = hAioMgrFile;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRINT pAioMgr;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertPtrReturn(pFile, VERR_INVALID_HANDLE);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pAioMgr = pFile->pAioMgr;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRREQ pReq = rtAioMgrReqAlloc(pAioMgr);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (RT_LIKELY(pReq))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync unsigned cSeg = 1;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync size_t cbSeg = RTSgBufSegArrayCreate(pSgBuf, &pReq->DataSeg, &cSeg, cbIo);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (cbSeg == cbIo)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->enmType = enmType;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->pFile = pFile;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->pvUser = pvUser;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->off = off;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rtAioMgrFileQueueReq(pFile, pReq);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = VERR_FILE_AIO_IN_PROGRESS;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync /** @todo: Real S/G buffer support. */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rtAioMgrReqFree(pAioMgr, pReq);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = VERR_NOT_SUPPORTED;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync else
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rc = VERR_NO_MEMORY;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return rc;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Request constructor for the memory cache.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync *
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @returns IPRT status code.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param hMemCache The cache handle.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pvObj The memory object that should be initialized.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pvUser The user argument.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic DECLCALLBACK(int) rtAioMgrReqCtor(RTMEMCACHE hMemCache, void *pvObj, void *pvUser)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRREQ pReq = (PRTAIOMGRREQ)pvObj;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync memset(pReq, 0, sizeof(RTAIOMGRREQ));
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return RTFileAioReqCreate(&pReq->hReqIo);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync/**
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * Request destructor for the memory cache.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync *
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param hMemCache The cache handle.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pvObj The memory object that should be destroyed.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync * @param pvUser The user argument.
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync */
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsyncstatic DECLCALLBACK(void) rtAioMgrReqDtor(RTMEMCACHE hMemCache, void *pvObj, void *pvUser)
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRREQ pReq = (PRTAIOMGRREQ)pvObj;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync int rc = RTFileAioReqDestroy(pReq->hReqIo);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertRC(rc);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync}
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsyncRTDECL(int) RTAioMgrCreate(PRTAIOMGR phAioMgr, uint32_t cReqsMax)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync{
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync int rc = VINF_SUCCESS;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync PRTAIOMGRINT pThis;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertPtrReturn(phAioMgr, VERR_INVALID_POINTER);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertReturn(cReqsMax > 0, VERR_INVALID_PARAMETER);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync pThis = (PRTAIOMGRINT)RTMemAllocZ(sizeof(RTAIOMGRINT));
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync if (pThis)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync {
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync pThis->u32Magic = RTAIOMGR_MAGIC;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync pThis->cRefs = 1;
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync pThis->enmBlockingEvent = RTAIOMGREVENT_NO_EVENT;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTListInit(&pThis->ListFiles);
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync rc = RTCritSectInit(&pThis->CritSectBlockingEvent);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync if (RT_SUCCESS(rc))
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync {
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync rc = RTSemEventCreate(&pThis->hEventSemBlock);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (RT_SUCCESS(rc))
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync {
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync rc = RTMemCacheCreate(&pThis->hMemCacheReqs, sizeof(RTAIOMGRREQ),
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync 0, UINT32_MAX, rtAioMgrReqCtor, rtAioMgrReqDtor, NULL, 0);
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync if (RT_SUCCESS(rc))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync {
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync rc = RTFileAioCtxCreate(&pThis->hAioCtx, cReqsMax == UINT32_MAX
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync ? RTFILEAIO_UNLIMITED_REQS
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync : cReqsMax,
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync RTFILEAIOCTX_FLAGS_WAIT_WITHOUT_PENDING_REQUESTS);
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync if (RT_SUCCESS(rc))
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync {
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync rc = RTThreadCreateF(&pThis->hThread, rtAioMgrWorker, pThis, 0, RTTHREADTYPE_IO,
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync RTTHREADFLAGS_WAITABLE, "AioMgr-%u", cReqsMax);
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync if (RT_FAILURE(rc))
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync {
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync rc = RTFileAioCtxDestroy(pThis->hAioCtx);
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync AssertRC(rc);
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync }
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync }
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync if (RT_FAILURE(rc))
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync RTMemCacheDestroy(pThis->hMemCacheReqs);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync }
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync if (RT_FAILURE(rc))
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync RTSemEventDestroy(pThis->hEventSemBlock);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (RT_FAILURE(rc))
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync RTCritSectDelete(&pThis->CritSectBlockingEvent);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync }
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync if (RT_FAILURE(rc))
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync RTMemFree(pThis);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync }
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync else
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync rc = VERR_NO_MEMORY;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync if (RT_SUCCESS(rc))
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync *phAioMgr = pThis;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync return rc;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync}
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsyncRTDECL(uint32_t) RTAioMgrRetain(RTAIOMGR hAioMgr)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync{
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync PRTAIOMGRINT pThis = hAioMgr;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertReturn(hAioMgr != NIL_RTAIOMGR, UINT32_MAX);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertPtrReturn(pThis, UINT32_MAX);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertReturn(pThis->u32Magic == RTAIOMGR_MAGIC, UINT32_MAX);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertMsg(cRefs > 1 && cRefs < _1G, ("%#x %p\n", cRefs, pThis));
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync return cRefs;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync}
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsyncRTDECL(uint32_t) RTAioMgrRelease(RTAIOMGR hAioMgr)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync{
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync PRTAIOMGRINT pThis = hAioMgr;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync if (pThis == NIL_RTAIOMGR)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync return 0;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertPtrReturn(pThis, UINT32_MAX);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertReturn(pThis->u32Magic == RTAIOMGR_MAGIC, UINT32_MAX);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertMsg(cRefs < _1G, ("%#x %p\n", cRefs, pThis));
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync if (cRefs == 0)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync rtAioMgrDestroy(pThis);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync return cRefs;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync}
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsyncRTDECL(int) RTAioMgrFileCreate(RTAIOMGR hAioMgr, RTFILE hFile, PFNRTAIOMGRREQCOMPLETE pfnReqComplete,
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync void *pvUser, PRTAIOMGRFILE phAioMgrFile)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync{
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync int rc = VINF_SUCCESS;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync PRTAIOMGRFILEINT pThis;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertReturn(hAioMgr != NIL_RTAIOMGR, VERR_INVALID_HANDLE);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertReturn(hFile != NIL_RTFILE, VERR_INVALID_HANDLE);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertPtrReturn(pfnReqComplete, VERR_INVALID_POINTER);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertPtrReturn(phAioMgrFile, VERR_INVALID_POINTER);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync pThis = (PRTAIOMGRFILEINT)RTMemAllocZ(sizeof(RTAIOMGRFILEINT));
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync if (pThis)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync {
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync pThis->u32Magic = RTAIOMGRFILE_MAGIC;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync pThis->cRefs = 1;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync pThis->hFile = hFile;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync pThis->pAioMgr = hAioMgr;
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync pThis->pvUser = pvUser;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pThis->pfnReqCompleted = pfnReqComplete;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTQueueAtomicInit(&pThis->QueueReqs);
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync RTListInit(&pThis->AioMgr.ListWaitingReqs);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTAioMgrRetain(hAioMgr);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync rc = RTFileAioCtxAssociateWithFile(pThis->pAioMgr->hAioCtx, hFile);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync if (RT_FAILURE(rc))
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync rtAioMgrFileDestroy(pThis);
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync else
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync rtAioMgrAddFile(pThis->pAioMgr, pThis);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync }
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync else
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync rc = VERR_NO_MEMORY;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync if (RT_SUCCESS(rc))
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync *phAioMgrFile = pThis;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync return rc;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync}
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsyncRTDECL(uint32_t) RTAioMgrFileRetain(RTAIOMGRFILE hAioMgrFile)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync{
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync PRTAIOMGRFILEINT pThis = hAioMgrFile;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertReturn(hAioMgrFile != NIL_RTAIOMGRFILE, UINT32_MAX);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertPtrReturn(pThis, UINT32_MAX);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertReturn(pThis->u32Magic == RTAIOMGRFILE_MAGIC, UINT32_MAX);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertMsg(cRefs > 1 && cRefs < _1G, ("%#x %p\n", cRefs, pThis));
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync return cRefs;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync}
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsyncRTDECL(uint32_t) RTAioMgrFileRelease(RTAIOMGRFILE hAioMgrFile)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync{
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync PRTAIOMGRFILEINT pThis = hAioMgrFile;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync if (pThis == NIL_RTAIOMGRFILE)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync return 0;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertPtrReturn(pThis, UINT32_MAX);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertReturn(pThis->u32Magic == RTAIOMGRFILE_MAGIC, UINT32_MAX);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync AssertMsg(cRefs < _1G, ("%#x %p\n", cRefs, pThis));
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync if (cRefs == 0)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync rtAioMgrFileDestroy(pThis);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync return cRefs;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync}
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
0840e09d42a5c78e8aea037e99676c212c40a441vboxsyncRTDECL(void *) RTAioMgrFileGetUser(RTAIOMGRFILE hAioMgrFile)
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync{
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync PRTAIOMGRFILEINT pThis = hAioMgrFile;
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync AssertPtrReturn(pThis, NULL);
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync return pThis->pvUser;
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync}
0840e09d42a5c78e8aea037e99676c212c40a441vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsyncRTDECL(int) RTAioMgrFileRead(RTAIOMGRFILE hAioMgrFile, RTFOFF off,
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync PRTSGBUF pSgBuf, size_t cbRead, void *pvUser)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return rtAioMgrFileIoReqCreate(hAioMgrFile, off, pSgBuf, cbRead, pvUser,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTAIOMGRREQTYPE_READ);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync}
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsyncRTDECL(int) RTAioMgrFileWrite(RTAIOMGRFILE hAioMgrFile, RTFOFF off,
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync PRTSGBUF pSgBuf, size_t cbWrite, void *pvUser)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return rtAioMgrFileIoReqCreate(hAioMgrFile, off, pSgBuf, cbWrite, pvUser,
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync RTAIOMGRREQTYPE_WRITE);
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync}
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsyncRTDECL(int) RTAioMgrFileFlush(RTAIOMGRFILE hAioMgrFile, void *pvUser)
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync{
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRFILEINT pFile = hAioMgrFile;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRINT pAioMgr;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync AssertPtrReturn(pFile, VERR_INVALID_HANDLE);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pAioMgr = pFile->pAioMgr;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync PRTAIOMGRREQ pReq = rtAioMgrReqAlloc(pAioMgr);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync if (RT_UNLIKELY(!pReq))
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return VERR_NO_MEMORY;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->pFile = pFile;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->enmType = RTAIOMGRREQTYPE_FLUSH;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync pReq->pvUser = pvUser;
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync rtAioMgrFileQueueReq(pFile, pReq);
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync
13476a0a3d8f5639dc4d6f453b7ff43218fb5dd8vboxsync return VERR_FILE_AIO_IN_PROGRESS;
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync}
527eff46676ca64c098dc7d1bf0857408c3a6f82vboxsync