fileaio-posix.cpp revision 10d739d22a5d5a13803f7e34de34de010099270c
1N/A * IPRT - File async I/O, native implementation for POSIX compliant host platforms. 1N/A * Copyright (C) 2006-2011 Oracle Corporation 1N/A * This file is part of VirtualBox Open Source Edition (OSE), as 1N/A * you can redistribute it and/or modify it under the terms of the GNU 1N/A * General Public License (GPL) as published by the Free Software 1N/A * Foundation, in version 2 as it comes in the "COPYING" file of the 1N/A * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 1N/A * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 1N/A * The contents of this file may alternatively be used under the terms 1N/A * of the Common Development and Distribution License Version 1.0 1N/A * (CDDL) only, as it comes in the "COPYING.CDDL" file of the 1N/A * VirtualBox OSE distribution, in which case the provisions of the 1N/A * CDDL are applicable instead of those of the GPL. 1N/A * You may elect to license modified versions of this file under the 1N/A * terms and conditions of either the GPL or the CDDL or both. 1N/A/******************************************************************************* 1N/A*******************************************************************************/ 1N/A * Linux does not define this value. 1N/A * Just define it with really big 1N/A#
if 0
/* Only used for debugging */ 1N/A/** Invalid entry in the waiting array. */ 1N/A/** No-op replacement for rtFileAioCtxDump for non debug builds */ 1N/A/******************************************************************************* 1N/A* Structures and Typedefs * 1N/A*******************************************************************************/ 1N/A * Async I/O request state. 1N/A /** The aio control block. FIRST ELEMENT! */ 1N/A /** Next element in the chain. */ 1N/A /** Previous element in the chain. */ 1N/A /** Current state the request is in. */ 1N/A /** Flag whether this is a flush request. */ 1N/A /** Flag indicating if the request was canceled. */ 1N/A /** Opaque user data. */ 1N/A /** Number of bytes actually transferred. */ 1N/A /** Completion context we are assigned to. */ 1N/A /** Entry in the waiting list the request is in. */ 1N/A /** Magic value (RTFILEAIOREQ_MAGIC). */ 1N/A * Async I/O completion context state. 1N/A /** Current number of requests active on this context. */ 1N/A /** Maximum number of requests this context can handle. */ 1N/A /** The ID of the thread which is currently waiting for requests. */ 1N/A /** Flag whether the thread was woken up. */ 1N/A /** Flag whether the thread is currently waiting in the syscall. */ 1N/A /** Flags given during creation. */ 1N/A /** Magic value (RTFILEAIOCTX_MAGIC). */ 1N/A /** Flag whether the thread was woken up due to a internal event. */ 1N/A /** List of new requests which needs to be inserted into apReqs by the 1N/A * waiting thread. */ 1N/A /** Special entry for requests which are canceled. Because only one 1N/A * request can be canceled at a time and the thread canceling the request 1N/A * has to wait we need only one entry. */ 1N/A /** Event semaphore the canceling thread is waiting for completion of 1N/A /** Head of submitted elements waiting to get into the array. */ 1N/A /** Tail of submitted elements waiting to get into the array. */ 1N/A /** Maximum number of elements in the waiting array. */ 1N/A /** First free slot in the waiting list. */ 1N/A /** List of requests we are currently waiting on. 1N/A * Size depends on cMaxRequests and AIO_LISTIO_MAX. */ 1N/A * Internal worker for waking up the waiting thread. 1N/A * Read the thread handle before the status flag. 1N/A * If we read the handle after the flag we might 1N/A * end up with an invalid handle because the thread 1N/A * waiting in RTFileAioCtxWakeup() might get scheduled 1N/A * before we read the flag and returns. 1N/A * We can ensure that the handle is valid if fWaiting is true 1N/A * when reading the handle before the status flag. 1N/A * If a thread waits the handle must be valid. 1N/A * It is possible that the thread returns from 1N/A * aio_suspend() before the signal is send. 1N/A * This is no problem because we already set fWokenUp 1N/A * to true which will let the thread return VERR_INTERRUPTED * and the next call to RTFileAioCtxWait() will not * return VERR_INTERRUPTED because signals are not saved * and will simply vanish if the destination thread can't * Internal worker processing events and inserting new requests into the waiting list. /* Process new requests first. */ /* Clear pointer to next and previous element just for safety. */ /* Append the rest to the wait list. */ /* Check if a request needs to be canceled. */ /* The request can be in the array waiting for completion or still in the list because it is full. */ /* Put it out of the waiting list. */ /* Unlink from the waiting list. */ /* We canceled the tail. */ /* We canceled the head. */ NULL,
/* Where the new value is located. */ 0);
/* Where the size of the new value is stored. */ * The AIO API is implemented in a kernel module which is not * If it is loaded there are additional sysctl parameters. NULL,
/* Where the new value is located. */ 0);
/* Where the size of the new value is stored. */ /* ENOENT means the value is unknown thus the module is not loaded. */ * Validate the handle and ignore nil. * Trash the magic and free it. * Worker setting up the request. * Notify the waiting thread that the request was canceled. (
"Invalid state. Request was canceled but wasn't submitted\n"));
/* Wait for acknowledge. */ /* Create event semaphore. */ * Dumps the state of a async I/O context. /* Check that we don't exceed the limit */ /* Undo everything and stop submitting. */ /* Unlink from the list again. */ /* Link them together. */ /* Check which ones were not submitted. */ * Looks like Apple and glibc interpret the standard in different ways. * glibc returns the error code which would be in errno but Apple returns * -1 and sets errno to the appropriate value /* Unlink from the list. */ * Check if we have a flush request now. * If not we hit the AIO_LISTIO_MAX limit * and will continue submitting requests * lio_listio does not work with flush requests so * we have to use aio_fsync directly. /* Link them together. */ * Forward successfully submitted requests to the thread waiting for requests. * We search for a free slot first and if we don't find one * we will grab the first one and append our list to the existing entries. /* Find the end of the current head and link the old list to the current. */ /* Set the internal wakeup flag and wakeup the thread if possible. */ LogFlowFunc((
"hAioCtx=%#p cMinReqs=%zu cMillies=%u pahReqs=%#p cReqs=%zu pcbReqs=%#p\n",
/* Wait for at least one. */ /* For the wakeup call. */ /* Update the waiting list once before we enter the loop. */ AssertMsgFailed((
"No request to wait for. pReqsWaitHead=%#p pReqsWaitTail=%#p\n",
/* Check that this is an external wakeup event. */ /* Remove completed requests from the waiting list. */ /* Completed store the return code. */ /* Call aio_return() to free resources. */ /* Mark the request as finished. */ /* If there are other entries waiting put the head into the now free entry. */ /* List is empty now. Clear tail too. */ * Move the last entry into the current position to avoid holes * but only if it is not the last element already. /* Put the request into the completed list. */ /* Recalculate the timeout. */ /* Check for new elements. */ /** @todo r=bird: Define the protocol for how to resume work after calling