922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync/* $Id$ */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync/** @file
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * IPRT - File async I/O, native implementation for the Windows host platform.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync/*
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2006-2012 Oracle Corporation
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync *
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * available from http://www.virtualbox.org. This file is free software;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * you can redistribute it and/or modify it under the terms of the GNU
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * General Public License (GPL) as published by the Free Software
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync *
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * The contents of this file may alternatively be used under the terms
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * of the Common Development and Distribution License Version 1.0
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * VirtualBox OSE distribution, in which case the provisions of the
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * CDDL are applicable instead of those of the GPL.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync *
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * You may elect to license modified versions of this file under the
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * terms and conditions of either the GPL or the CDDL or both.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync/*******************************************************************************
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync* Header Files *
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync*******************************************************************************/
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#define LOG_GROUP RTLOGGROUP_DIR
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <iprt/asm.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <iprt/file.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <iprt/mem.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <iprt/assert.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <iprt/string.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <iprt/err.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <iprt/log.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include "internal/fileaio.h"
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#include <Windows.h>
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync/*******************************************************************************
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync* Structures and Typedefs *
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync*******************************************************************************/
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync/**
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * Transfer direction.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsynctypedef enum TRANSFERDIRECTION
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync TRANSFERDIRECTION_INVALID = 0,
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /** Read. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync TRANSFERDIRECTION_READ,
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /** Write. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync TRANSFERDIRECTION_WRITE,
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /** The usual 32-bit hack. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync TRANSFERDIRECTION_32BIT_HACK = 0x7fffffff
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync} TRANSFERDIRECTION;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync/**
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * Async I/O completion context state.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsynctypedef struct RTFILEAIOCTXINTERNAL
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /** handle to I/O completion port. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync HANDLE hIoCompletionPort;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /** Current number of requests pending. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync volatile int32_t cRequests;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /** Flag whether the thread was woken up. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync volatile bool fWokenUp;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /** Flag whether the thread is currently waiting. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync volatile bool fWaiting;
10d739d22a5d5a13803f7e34de34de010099270cvboxsync /** Flags given during creation. */
10d739d22a5d5a13803f7e34de34de010099270cvboxsync uint32_t fFlags;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /** Magic value (RTFILEAIOCTX_MAGIC). */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync uint32_t u32Magic;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync} RTFILEAIOCTXINTERNAL;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync/** Pointer to an internal context structure. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsynctypedef RTFILEAIOCTXINTERNAL *PRTFILEAIOCTXINTERNAL;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync/**
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * Async I/O request state.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsynctypedef struct RTFILEAIOREQINTERNAL
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /** Overlapped structure. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync OVERLAPPED Overlapped;
be196d173cf52fa33016912e4745dbe1170ac53avboxsync /** Current state the request is in. */
be196d173cf52fa33016912e4745dbe1170ac53avboxsync RTFILEAIOREQSTATE enmState;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /** The file handle. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync HANDLE hFile;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /** Kind of transfer Read/Write. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync TRANSFERDIRECTION enmTransferDirection;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /** Number of bytes to transfer. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync size_t cbTransfer;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /** Pointer to the buffer. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync void *pvBuf;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /** Opaque user data. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync void *pvUser;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /** Flag whether the request completed. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync bool fCompleted;
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync /** Number of bytes transferred successfully. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync size_t cbTransfered;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /** Error code of the completed request. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync int Rc;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /** Completion context we are assigned to. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync PRTFILEAIOCTXINTERNAL pCtxInt;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /** Magic value (RTFILEAIOREQ_MAGIC). */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync uint32_t u32Magic;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync} RTFILEAIOREQINTERNAL;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync/** Pointer to an internal request structure. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsynctypedef RTFILEAIOREQINTERNAL *PRTFILEAIOREQINTERNAL;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync/*******************************************************************************
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync* Defined Constants And Macros *
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync*******************************************************************************/
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync/** Id for the wakeup event. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#define AIO_CONTEXT_WAKEUP_EVENT 1
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync/** Converts a pointer to an OVERLAPPED structure to a internal request. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync#define OVERLAPPED_2_RTFILEAIOREQINTERNAL(pOverlapped) ( (PRTFILEAIOREQINTERNAL)((uintptr_t)(pOverlapped) - RT_OFFSETOF(RTFILEAIOREQINTERNAL, Overlapped)) )
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
be196d173cf52fa33016912e4745dbe1170ac53avboxsyncRTR3DECL(int) RTFileAioGetLimits(PRTFILEAIOLIMITS pAioLimits)
be196d173cf52fa33016912e4745dbe1170ac53avboxsync{
be196d173cf52fa33016912e4745dbe1170ac53avboxsync int rcBSD = 0;
be196d173cf52fa33016912e4745dbe1170ac53avboxsync AssertPtrReturn(pAioLimits, VERR_INVALID_POINTER);
be196d173cf52fa33016912e4745dbe1170ac53avboxsync
be196d173cf52fa33016912e4745dbe1170ac53avboxsync /* No limits known. */
be196d173cf52fa33016912e4745dbe1170ac53avboxsync pAioLimits->cReqsOutstandingMax = RTFILEAIO_UNLIMITED_REQS;
be196d173cf52fa33016912e4745dbe1170ac53avboxsync pAioLimits->cbBufferAlignment = 0;
be196d173cf52fa33016912e4745dbe1170ac53avboxsync
be196d173cf52fa33016912e4745dbe1170ac53avboxsync return VINF_SUCCESS;
be196d173cf52fa33016912e4745dbe1170ac53avboxsync}
be196d173cf52fa33016912e4745dbe1170ac53avboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncRTR3DECL(int) RTFileAioReqCreate(PRTFILEAIOREQ phReq)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync AssertPtrReturn(phReq, VERR_INVALID_POINTER);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync PRTFILEAIOREQINTERNAL pReqInt = (PRTFILEAIOREQINTERNAL)RTMemAllocZ(sizeof(RTFILEAIOREQINTERNAL));
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (RT_UNLIKELY(!pReqInt))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return VERR_NO_MEMORY;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync pReqInt->pCtxInt = NULL;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync pReqInt->fCompleted = false;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync pReqInt->u32Magic = RTFILEAIOREQ_MAGIC;
be196d173cf52fa33016912e4745dbe1170ac53avboxsync RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync *phReq = (RTFILEAIOREQ)pReqInt;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return VINF_SUCCESS;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
be196d173cf52fa33016912e4745dbe1170ac53avboxsyncRTDECL(int) RTFileAioReqDestroy(RTFILEAIOREQ hReq)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /*
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * Validate the handle and ignore nil.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (hReq == NIL_RTFILEAIOREQ)
be196d173cf52fa33016912e4745dbe1170ac53avboxsync return VINF_SUCCESS;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync PRTFILEAIOREQINTERNAL pReqInt = hReq;
be196d173cf52fa33016912e4745dbe1170ac53avboxsync RTFILEAIOREQ_VALID_RETURN(pReqInt);
be196d173cf52fa33016912e4745dbe1170ac53avboxsync RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /*
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * Trash the magic and free it.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync ASMAtomicUoWriteU32(&pReqInt->u32Magic, ~RTFILEAIOREQ_MAGIC);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTMemFree(pReqInt);
be196d173cf52fa33016912e4745dbe1170ac53avboxsync return VINF_SUCCESS;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync/**
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * Worker setting up the request.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncDECLINLINE(int) rtFileAioReqPrepareTransfer(RTFILEAIOREQ hReq, RTFILE hFile,
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync TRANSFERDIRECTION enmTransferDirection,
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTFOFF off, void *pvBuf, size_t cbTransfer,
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync void *pvUser)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /*
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * Validate the input.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync PRTFILEAIOREQINTERNAL pReqInt = hReq;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTFILEAIOREQ_VALID_RETURN(pReqInt);
be196d173cf52fa33016912e4745dbe1170ac53avboxsync RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync Assert(hFile != NIL_RTFILE);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync AssertPtr(pvBuf);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync Assert(off >= 0);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync Assert(cbTransfer > 0);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync pReqInt->enmTransferDirection = enmTransferDirection;
cecfddc5f644039b889734369f7087dcdeb42e85vboxsync pReqInt->hFile = (HANDLE)RTFileToNative(hFile);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync pReqInt->Overlapped.Offset = (DWORD)(off & 0xffffffff);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync pReqInt->Overlapped.OffsetHigh = (DWORD)(off >> 32);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync pReqInt->cbTransfer = cbTransfer;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync pReqInt->pvBuf = pvBuf;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync pReqInt->pvUser = pvUser;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync pReqInt->fCompleted = false;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return VINF_SUCCESS;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncRTDECL(int) RTFileAioReqPrepareRead(RTFILEAIOREQ hReq, RTFILE hFile, RTFOFF off,
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync void *pvBuf, size_t cbRead, void *pvUser)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return rtFileAioReqPrepareTransfer(hReq, hFile, TRANSFERDIRECTION_READ,
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync off, pvBuf, cbRead, pvUser);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncRTDECL(int) RTFileAioReqPrepareWrite(RTFILEAIOREQ hReq, RTFILE hFile, RTFOFF off,
88acfa6629a7976c0583c1712d2b5b22a87a5121vboxsync void const *pvBuf, size_t cbWrite, void *pvUser)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return rtFileAioReqPrepareTransfer(hReq, hFile, TRANSFERDIRECTION_WRITE,
88acfa6629a7976c0583c1712d2b5b22a87a5121vboxsync off, (void *)pvBuf, cbWrite, pvUser);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncRTDECL(int) RTFileAioReqPrepareFlush(RTFILEAIOREQ hReq, RTFILE hFile, void *pvUser)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync PRTFILEAIOREQINTERNAL pReqInt = hReq;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTFILEAIOREQ_VALID_RETURN(pReqInt);
be196d173cf52fa33016912e4745dbe1170ac53avboxsync RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync AssertReturn(hFile != NIL_RTFILE, VERR_INVALID_HANDLE);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
eab872ee272cc9e799e0b68735b660deb84b8629vboxsync return VERR_NOT_SUPPORTED;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncRTDECL(void *) RTFileAioReqGetUser(RTFILEAIOREQ hReq)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync PRTFILEAIOREQINTERNAL pReqInt = hReq;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTFILEAIOREQ_VALID_RETURN_RC(pReqInt, NULL);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return pReqInt->pvUser;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncRTDECL(int) RTFileAioReqCancel(RTFILEAIOREQ hReq)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync PRTFILEAIOREQINTERNAL pReqInt = hReq;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTFILEAIOREQ_VALID_RETURN(pReqInt);
be196d173cf52fa33016912e4745dbe1170ac53avboxsync RTFILEAIOREQ_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_NOT_SUBMITTED);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /**
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * @todo r=aeichner It is not possible to cancel specific
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * requests on Windows before Vista.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * CancelIo cancels all requests for a file issued by the
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * calling thread and CancelIoEx which does what we need
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * is only available from Vista and up.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * The solution is to return VERR_FILE_AIO_IN_PROGRESS
be196d173cf52fa33016912e4745dbe1170ac53avboxsync * if the request didn't completed yet (checked above).
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * Shouldn't be a big issue because a request is normally
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * only canceled if it exceeds a timeout which is quite huge.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync */
be196d173cf52fa33016912e4745dbe1170ac53avboxsync return VERR_FILE_AIO_COMPLETED;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncRTDECL(int) RTFileAioReqGetRC(RTFILEAIOREQ hReq, size_t *pcbTransfered)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync int rc = VINF_SUCCESS;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync PRTFILEAIOREQINTERNAL pReqInt = hReq;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTFILEAIOREQ_VALID_RETURN(pReqInt);
be196d173cf52fa33016912e4745dbe1170ac53avboxsync RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
be196d173cf52fa33016912e4745dbe1170ac53avboxsync RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, PREPARED, VERR_FILE_AIO_NOT_SUBMITTED);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
be196d173cf52fa33016912e4745dbe1170ac53avboxsync rc = pReqInt->Rc;
be196d173cf52fa33016912e4745dbe1170ac53avboxsync if (pcbTransfered && RT_SUCCESS(rc))
be196d173cf52fa33016912e4745dbe1170ac53avboxsync *pcbTransfered = pReqInt->cbTransfered;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return rc;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
10d739d22a5d5a13803f7e34de34de010099270cvboxsyncRTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax,
10d739d22a5d5a13803f7e34de34de010099270cvboxsync uint32_t fFlags)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync PRTFILEAIOCTXINTERNAL pCtxInt;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync AssertPtrReturn(phAioCtx, VERR_INVALID_POINTER);
10d739d22a5d5a13803f7e34de34de010099270cvboxsync AssertReturn(!(fFlags & ~RTFILEAIOCTX_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync pCtxInt = (PRTFILEAIOCTXINTERNAL)RTMemAllocZ(sizeof(RTFILEAIOCTXINTERNAL));
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (RT_UNLIKELY(!pCtxInt))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return VERR_NO_MEMORY;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync pCtxInt->hIoCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync NULL,
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync 0,
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync 0);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (RT_UNLIKELY(!pCtxInt->hIoCompletionPort))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTMemFree(pCtxInt);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return VERR_NO_MEMORY;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
10d739d22a5d5a13803f7e34de34de010099270cvboxsync pCtxInt->fFlags = fFlags;
10d739d22a5d5a13803f7e34de34de010099270cvboxsync pCtxInt->u32Magic = RTFILEAIOCTX_MAGIC;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync *phAioCtx = (RTFILEAIOCTX)pCtxInt;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return VINF_SUCCESS;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncRTDECL(int) RTFileAioCtxDestroy(RTFILEAIOCTX hAioCtx)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /* Validate the handle and ignore nil. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (hAioCtx == NIL_RTFILEAIOCTX)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return VINF_SUCCESS;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTFILEAIOCTX_VALID_RETURN(pCtxInt);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /* Cannot destroy a busy context. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (RT_UNLIKELY(pCtxInt->cRequests))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return VERR_FILE_AIO_BUSY;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync CloseHandle(pCtxInt->hIoCompletionPort);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync ASMAtomicUoWriteU32(&pCtxInt->u32Magic, RTFILEAIOCTX_MAGIC_DEAD);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTMemFree(pCtxInt);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return VINF_SUCCESS;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncRTDECL(int) RTFileAioCtxAssociateWithFile(RTFILEAIOCTX hAioCtx, RTFILE hFile)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync int rc = VINF_SUCCESS;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTFILEAIOCTX_VALID_RETURN(pCtxInt);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
cecfddc5f644039b889734369f7087dcdeb42e85vboxsync HANDLE hTemp = CreateIoCompletionPort((HANDLE)RTFileToNative(hFile), pCtxInt->hIoCompletionPort, 0, 1);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (hTemp != pCtxInt->hIoCompletionPort)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync rc = RTErrConvertFromWin32(GetLastError());
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return rc;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncRTDECL(uint32_t) RTFileAioCtxGetMaxReqCount(RTFILEAIOCTX hAioCtx)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return RTFILEAIO_UNLIMITED_REQS;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
be196d173cf52fa33016912e4745dbe1170ac53avboxsyncRTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /*
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * Parameter validation.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync int rc = VINF_SUCCESS;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTFILEAIOCTX_VALID_RETURN(pCtxInt);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync AssertReturn(cReqs > 0, VERR_INVALID_PARAMETER);
27de6b7fcf72c0add242c8dbefff24fbdc7869ebvboxsync Assert(cReqs <= INT32_MAX);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync AssertPtrReturn(pahReqs, VERR_INVALID_POINTER);
78817f40cd3fec6cba19ad8a2df2a690970c5895vboxsync size_t i;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync for (i = 0; i < cReqs; i++)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync PRTFILEAIOREQINTERNAL pReqInt = pahReqs[i];
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync BOOL fSucceeded;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
0aa150e34ed49f14aaa37368c2e6999ec89e5f43vboxsync Assert(pReqInt->cbTransfer == (DWORD)pReqInt->cbTransfer);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (pReqInt->enmTransferDirection == TRANSFERDIRECTION_READ)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync fSucceeded = ReadFile(pReqInt->hFile, pReqInt->pvBuf,
0aa150e34ed49f14aaa37368c2e6999ec89e5f43vboxsync (DWORD)pReqInt->cbTransfer, NULL,
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync &pReqInt->Overlapped);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else if (pReqInt->enmTransferDirection == TRANSFERDIRECTION_WRITE)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync fSucceeded = WriteFile(pReqInt->hFile, pReqInt->pvBuf,
0aa150e34ed49f14aaa37368c2e6999ec89e5f43vboxsync (DWORD)pReqInt->cbTransfer, NULL,
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync &pReqInt->Overlapped);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync else
b64d5de6949f62d8b70658f77d9f28f58b0d4668vboxsync {
b64d5de6949f62d8b70658f77d9f28f58b0d4668vboxsync fSucceeded = false;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync AssertMsgFailed(("Invalid transfer direction\n"));
b64d5de6949f62d8b70658f77d9f28f58b0d4668vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (RT_UNLIKELY(!fSucceeded && GetLastError() != ERROR_IO_PENDING))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
be196d173cf52fa33016912e4745dbe1170ac53avboxsync RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync rc = RTErrConvertFromWin32(GetLastError());
be196d173cf52fa33016912e4745dbe1170ac53avboxsync pReqInt->Rc = rc;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync break;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
be196d173cf52fa33016912e4745dbe1170ac53avboxsync RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
27de6b7fcf72c0add242c8dbefff24fbdc7869ebvboxsync ASMAtomicAddS32(&pCtxInt->cRequests, (int32_t)i);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return rc;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsyncRTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, RTMSINTERVAL cMillies,
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync PRTFILEAIOREQ pahReqs, size_t cReqs, uint32_t *pcReqs)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /*
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * Validate the parameters, making sure to always set pcReqs.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync AssertPtrReturn(pcReqs, VERR_INVALID_POINTER);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync *pcReqs = 0; /* always set */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTFILEAIOCTX_VALID_RETURN(pCtxInt);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync AssertPtrReturn(pahReqs, VERR_INVALID_POINTER);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync AssertReturn(cReqs != 0, VERR_INVALID_PARAMETER);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync AssertReturn(cReqs >= cMinReqs, VERR_OUT_OF_RANGE);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /*
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * Can't wait if there are no requests around.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync */
10d739d22a5d5a13803f7e34de34de010099270cvboxsync if ( RT_UNLIKELY(ASMAtomicUoReadS32(&pCtxInt->cRequests) == 0)
10d739d22a5d5a13803f7e34de34de010099270cvboxsync && !(pCtxInt->fFlags & RTFILEAIOCTX_FLAGS_WAIT_WITHOUT_PENDING_REQUESTS))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return VERR_FILE_AIO_NO_REQUEST;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /* Wait for at least one. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (!cMinReqs)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync cMinReqs = 1;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /*
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * Loop until we're woken up, hit an error (incl timeout), or
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * have collected the desired number of requests.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync int rc = VINF_SUCCESS;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync int cRequestsCompleted = 0;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync while ( !pCtxInt->fWokenUp
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync && cMinReqs > 0)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync uint64_t StartNanoTS = 0;
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync DWORD dwTimeout = cMillies == RT_INDEFINITE_WAIT ? INFINITE : cMillies;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync DWORD cbTransfered;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync LPOVERLAPPED pOverlapped;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync ULONG_PTR lCompletionKey;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync BOOL fSucceeded;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync if (cMillies != RT_INDEFINITE_WAIT)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync StartNanoTS = RTTimeNanoTS();
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync ASMAtomicXchgBool(&pCtxInt->fWaiting, true);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync fSucceeded = GetQueuedCompletionStatus(pCtxInt->hIoCompletionPort,
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync &cbTransfered,
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync &lCompletionKey,
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync &pOverlapped,
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync dwTimeout);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync ASMAtomicXchgBool(&pCtxInt->fWaiting, false);
f2ffcc39cf4469a87fea28faf36a3918493bf7c1vboxsync if ( !fSucceeded
f2ffcc39cf4469a87fea28faf36a3918493bf7c1vboxsync && !pOverlapped)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
f2ffcc39cf4469a87fea28faf36a3918493bf7c1vboxsync /* The call failed to dequeue a completion packet, includes VERR_TIMEOUT */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync rc = RTErrConvertFromWin32(GetLastError());
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync break;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /* Check if we got woken up. */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (lCompletionKey == AIO_CONTEXT_WAKEUP_EVENT)
f2ffcc39cf4469a87fea28faf36a3918493bf7c1vboxsync {
e41b10cedab46ca3ff69b2db87291a74ec1ddd61vboxsync Assert(fSucceeded && !pOverlapped);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync break;
f2ffcc39cf4469a87fea28faf36a3918493bf7c1vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync /* A request completed. */
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync PRTFILEAIOREQINTERNAL pReqInt = OVERLAPPED_2_RTFILEAIOREQINTERNAL(pOverlapped);
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync AssertPtr(pReqInt);
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync Assert(pReqInt->u32Magic == RTFILEAIOREQ_MAGIC);
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync /* Mark the request as finished. */
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync pReqInt->cbTransfered = cbTransfered;
f2ffcc39cf4469a87fea28faf36a3918493bf7c1vboxsync if (fSucceeded)
f2ffcc39cf4469a87fea28faf36a3918493bf7c1vboxsync pReqInt->Rc = VINF_SUCCESS;
f2ffcc39cf4469a87fea28faf36a3918493bf7c1vboxsync else
b7c1d1e088392fc0698ab8732e2c24f54d92dcbdvboxsync {
b7c1d1e088392fc0698ab8732e2c24f54d92dcbdvboxsync DWORD errCode = GetLastError();
b7c1d1e088392fc0698ab8732e2c24f54d92dcbdvboxsync pReqInt->Rc = RTErrConvertFromWin32(errCode);
b7c1d1e088392fc0698ab8732e2c24f54d92dcbdvboxsync if (pReqInt->Rc == VERR_UNRESOLVED_ERROR)
b7c1d1e088392fc0698ab8732e2c24f54d92dcbdvboxsync LogRel(("AIO/win: Request %#p returned rc=%Rrc (native %u\n)", pReqInt, pReqInt->Rc, errCode));
b7c1d1e088392fc0698ab8732e2c24f54d92dcbdvboxsync }
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync pahReqs[cRequestsCompleted++] = (RTFILEAIOREQ)pReqInt;
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync /* Update counter. */
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync cMinReqs--;
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync if (cMillies != RT_INDEFINITE_WAIT)
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync {
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync /* Recalculate timeout. */
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync uint64_t NanoTS = RTTimeNanoTS();
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync uint64_t cMilliesElapsed = (NanoTS - StartNanoTS) / 1000000;
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync if (cMilliesElapsed < cMillies)
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync cMillies -= cMilliesElapsed;
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync else
b79e4344bf4eb8033fd06d560cd864192728bd0bvboxsync cMillies = 0;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /*
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * Update the context state and set the return value.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync */
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync *pcReqs = cRequestsCompleted;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync ASMAtomicSubS32(&pCtxInt->cRequests, cRequestsCompleted);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync /*
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync * Clear the wakeup flag and set rc.
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync */
6757b795f7bfac39777e1e86a49fa120f86def25vboxsync bool fWokenUp = ASMAtomicXchgBool(&pCtxInt->fWokenUp, false);
6757b795f7bfac39777e1e86a49fa120f86def25vboxsync
6757b795f7bfac39777e1e86a49fa120f86def25vboxsync if ( fWokenUp
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync && RT_SUCCESS(rc))
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync rc = VERR_INTERRUPTED;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return rc;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsyncRTDECL(int) RTFileAioCtxWakeup(RTFILEAIOCTX hAioCtx)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync{
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync int rc = VINF_SUCCESS;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync RTFILEAIOCTX_VALID_RETURN(pCtxInt);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync bool fWokenUp = ASMAtomicXchgBool(&pCtxInt->fWokenUp, true);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync bool fWaiting = ASMAtomicReadBool(&pCtxInt->fWaiting);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if ( !fWokenUp
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync && fWaiting)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync {
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync BOOL fSucceeded = PostQueuedCompletionStatus(pCtxInt->hIoCompletionPort,
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync 0, AIO_CONTEXT_WAKEUP_EVENT,
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync NULL);
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync if (!fSucceeded)
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync rc = RTErrConvertFromWin32(GetLastError());
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync }
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync return rc;
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync}
922f46b2f42ccb05e3c9cba34bbd1d2c19e04120vboxsync