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