VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/misc/aiomgr.cpp@ 46185

Last change on this file since 46185 was 46185, checked in by vboxsync, 12 years ago

Runtime: Rename RTWorkQueue to RTQueueAtomic

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.6 KB
Line 
1/* $Id: aiomgr.cpp 46185 2013-05-21 06:28:49Z vboxsync $ */
2/** @file
3 * IPRT - Async I/O manager.
4 */
5
6/*
7 * Copyright (C) 2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/*******************************************************************************
28* Header Files *
29*******************************************************************************/
30
31#include <iprt/aiomgr.h>
32#include <iprt/err.h>
33#include <iprt/asm.h>
34#include <iprt/mem.h>
35#include <iprt/file.h>
36#include <iprt/thread.h>
37#include <iprt/assert.h>
38#include <iprt/critsect.h>
39#include <iprt/semaphore.h>
40#include <iprt/queueatomic.h>
41
42#include "internal/magics.h"
43
44/*******************************************************************************
45* Structures and Typedefs *
46*******************************************************************************/
47
48/** Pointer to an internal async I/O file instance. */
49typedef struct RTAIOMGRFILEINT *PRTAIOMGRFILEINT;
50
51/**
52 * Blocking event types.
53 */
54typedef enum RTAIOMGREVENT
55{
56 /** Invalid tye */
57 RTAIOMGREVENT_INVALID = 0,
58 /** An endpoint is added to the manager. */
59 RTAIOMGREVENT_ADD_FILE,
60 /** An endpoint is about to be closed. */
61 RTAIOMGREVENT_CLOSE_FILE,
62 /** 32bit hack */
63 RTAIOMGREVENT_32BIT_HACK = 0x7fffffff
64} RTAIOMGREVENT;
65
66/**
67 * Async I/O manager instance data.
68 */
69typedef struct RTAIOMGRINT
70{
71 /** Magic value. */
72 uint32_t u32Magic;
73 /** Reference count. */
74 volatile uint32_t cRefs;
75 /** Running flag. */
76 volatile bool fRunning;
77 /** Async I/O context handle. */
78 RTFILEAIOCTX hAioCtx;
79 /** async I/O thread. */
80 RTTHREAD hThread;
81 /** List of files assigned to this manager. */
82 PRTAIOMGRFILEINT pFilesHead;
83 /** Number of requests active currently. */
84 unsigned cReqsActive;
85 /** Number of maximum requests active. */
86 uint32_t cReqsActiveMax;
87 /** Pointer to an array of free async I/O request handles. */
88 RTFILEAIOREQ *pahReqsFree;
89 /** Index of the next free entry in the cache. */
90 uint32_t iFreeEntry;
91 /** Size of the array. */
92 unsigned cReqEntries;
93 /** Critical section protecting the blocking event handling. */
94 RTCRITSECT CritSectBlockingEvent;
95 /** Event semaphore for blocking external events.
96 * The caller waits on it until the async I/O manager
97 * finished processing the event. */
98 RTSEMEVENT EventSemBlock;
99 /** Flag whether a blocking event is pending and needs
100 * processing by the I/O manager. */
101 volatile bool fBlockingEventPending;
102 /** Blocking event type */
103 volatile RTAIOMGREVENT enmBlockingEvent;
104 /** Event type data */
105 union
106 {
107 /** The file to be added */
108 volatile PRTAIOMGRFILEINT pFileAdd;
109 /** The file to be closed */
110 volatile PRTAIOMGRFILEINT pFileClose;
111 } BlockingEventData;
112} RTAIOMGRINT;
113/** Pointer to an internal async I/O manager instance. */
114typedef RTAIOMGRINT *PRTAIOMGRINT;
115
116/**
117 * Async I/O manager file instance data.
118 */
119typedef struct RTAIOMGRFILEINT
120{
121 /** Magic value. */
122 uint32_t u32Magic;
123 /** Reference count. */
124 volatile uint32_t cRefs;
125 /** File handle. */
126 RTFILE hFile;
127 /** async I/O manager this file belongs to. */
128 PRTAIOMGRINT pAioMgr;
129 /** Work queue for new requests. */
130 RTQUEUEATOMIC QueueReqs;
131 /** Data for exclusive use by the assigned async I/O manager. */
132 struct
133 {
134 /** Pointer to the next file assigned to the manager. */
135 PRTAIOMGRFILEINT pNext;
136#if 0
137 /** List of pending requests (not submitted due to usage restrictions
138 * or a pending flush request) */
139 R3PTRTYPE(PPDMACTASKFILE) pReqsPendingHead;
140 /** Tail of pending requests. */
141 R3PTRTYPE(PPDMACTASKFILE) pReqsPendingTail;
142 /** Tree of currently locked ranges.
143 * If a write task is enqueued the range gets locked and any other
144 * task writing to that range has to wait until the task completes.
145 */
146 PAVLRFOFFTREE pTreeRangesLocked;
147 /** Number of requests with a range lock active. */
148 unsigned cLockedReqsActive;
149 /** Number of requests currently being processed for this endpoint
150 * (excluded flush requests). */
151 unsigned cRequestsActive;
152#endif
153 } AioMgr;
154} RTAIOMGRFILEINT;
155
156/*******************************************************************************
157* Defined Constants And Macros *
158*******************************************************************************/
159
160/** Validates a handle and returns VERR_INVALID_HANDLE if not valid. */
161#define RTAIOMGR_VALID_RETURN_RC(a_hAioMgr, a_rc) \
162 do { \
163 AssertPtrReturn((a_hAioMgr), (a_rc)); \
164 AssertReturn((a_hAioMgr)->u32Magic == RTAIOMGR_MAGIC, (a_rc)); \
165 } while (0)
166
167/** Validates a handle and returns VERR_INVALID_HANDLE if not valid. */
168#define RTAIOMGR_VALID_RETURN(a_hAioMgr) RTAIOMGR_VALID_RETURN_RC((hAioMgr), VERR_INVALID_HANDLE)
169
170/** Validates a handle and returns (void) if not valid. */
171#define RTAIOMGR_VALID_RETURN_VOID(a_hAioMgr) \
172 do { \
173 AssertPtrReturnVoid(a_hAioMgr); \
174 AssertReturnVoid((a_hAioMgr)->u32Magic == RTAIOMGR_MAGIC); \
175 } while (0)
176
177/*******************************************************************************
178* Internal Functions *
179*******************************************************************************/
180
181/**
182 * async I/O manager worker loop.
183 *
184 * @returns IPRT status code.
185 * @param hThreadSelf The thread handle this worker belongs to.
186 * @param pvUser Opaque user data (Pointer to async I/O manager instance).
187 */
188static DECLCALLBACK(int) rtAioMgrWorker(RTTHREAD hThreadSelf, void *pvUser)
189{
190 PRTAIOMGRINT pThis = (PRTAIOMGRINT)pvUser;
191 bool fRunning = true;
192
193 do
194 {
195 uint32_t cReqsCompleted = 0;
196 RTFILEAIOREQ ahReqsCompleted[32];
197 int rc = RTFileAioCtxWait(pThis->hAioCtx, 1, RT_INDEFINITE_WAIT, &ahReqsCompleted[0],
198 RT_ELEMENTS(ahReqsCompleted), &cReqsCompleted);
199 if (RT_FAILURE(rc) && rc != VERR_INTERRUPTED)
200 {
201 }
202 fRunning = ASMAtomicUoReadBool(&pThis->fRunning);
203 } while (fRunning);
204
205 return VINF_SUCCESS;
206}
207
208/**
209 * Destroys an async I/O manager.
210 *
211 * @returns nothing.
212 * @param pThis The async I/O manager instance to destroy.
213 */
214static void rtAioMgrDestroy(PRTAIOMGRINT pThis)
215{
216 int rc;
217
218 ASMAtomicXchgBool(&pThis->fRunning, false);
219 rc = RTFileAioCtxWakeup(pThis->hAioCtx);
220 AssertRC(rc);
221
222 rc = RTThreadWait(pThis->hThread, RT_INDEFINITE_WAIT, NULL);
223 AssertRC(rc);
224
225 rc = RTFileAioCtxDestroy(pThis->hAioCtx);
226 AssertRC(rc);
227
228 pThis->hThread = NIL_RTTHREAD;
229 pThis->hAioCtx = NIL_RTFILEAIOCTX;
230 pThis->u32Magic = ~RTAIOMGR_MAGIC;
231 RTMemFree(pThis);
232}
233
234/**
235 * Destroys an async I/O manager file.
236 *
237 * @returns nothing.
238 * @param pThis The async I/O manager file.
239 */
240static void rtAioMgrFileDestroy(PRTAIOMGRFILEINT pThis)
241{
242 pThis->u32Magic = ~RTAIOMGRFILE_MAGIC;
243 RTMemFree(pThis);
244}
245
246RTDECL(int) RTAioMgrCreate(PRTAIOMGR phAioMgr, uint32_t cReqsMax)
247{
248 int rc = VINF_SUCCESS;
249 PRTAIOMGRINT pThis;
250
251 AssertPtrReturn(phAioMgr, VERR_INVALID_POINTER);
252 AssertReturn(cReqsMax > 0, VERR_INVALID_PARAMETER);
253
254 pThis = (PRTAIOMGRINT)RTMemAllocZ(sizeof(RTAIOMGRINT));
255 if (pThis)
256 {
257 pThis->u32Magic = RTAIOMGR_MAGIC;
258 pThis->cRefs = 1;
259 pThis->fRunning = true;
260 rc = RTFileAioCtxCreate(&pThis->hAioCtx, cReqsMax == UINT32_MAX
261 ? RTFILEAIO_UNLIMITED_REQS
262 : cReqsMax,
263 RTFILEAIOCTX_FLAGS_WAIT_WITHOUT_PENDING_REQUESTS);
264 if (RT_SUCCESS(rc))
265 {
266 rc = RTThreadCreateF(&pThis->hThread, rtAioMgrWorker, pThis, 0, RTTHREADTYPE_IO,
267 RTTHREADFLAGS_WAITABLE, "AioMgr-%p", pThis);
268 if (RT_FAILURE(rc))
269 {
270 rc = RTFileAioCtxDestroy(pThis->hAioCtx);
271 AssertRC(rc);
272 }
273 }
274 if (RT_FAILURE(rc))
275 RTMemFree(pThis);
276 }
277 else
278 rc = VERR_NO_MEMORY;
279
280 if (RT_SUCCESS(rc))
281 *phAioMgr = pThis;
282
283 return rc;
284}
285
286RTDECL(uint32_t) RTAioMgrRetain(RTAIOMGR hAioMgr)
287{
288 PRTAIOMGRINT pThis = hAioMgr;
289 AssertReturn(hAioMgr != NIL_RTAIOMGR, UINT32_MAX);
290 AssertPtrReturn(pThis, UINT32_MAX);
291 AssertReturn(pThis->u32Magic == RTAIOMGR_MAGIC, UINT32_MAX);
292
293 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
294 AssertMsg(cRefs > 1 && cRefs < _1G, ("%#x %p\n", cRefs, pThis));
295 return cRefs;
296}
297
298RTDECL(uint32_t) RTAioMgrRelease(RTAIOMGR hAioMgr)
299{
300 PRTAIOMGRINT pThis = hAioMgr;
301 if (pThis == NIL_RTAIOMGR)
302 return 0;
303 AssertPtrReturn(pThis, UINT32_MAX);
304 AssertReturn(pThis->u32Magic == RTAIOMGR_MAGIC, UINT32_MAX);
305
306 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
307 AssertMsg(cRefs < _1G, ("%#x %p\n", cRefs, pThis));
308 if (cRefs == 0)
309 rtAioMgrDestroy(pThis);
310 return cRefs;
311}
312
313RTDECL(int) RTAioMgrFileCreate(RTAIOMGR hAioMgr, RTFILE hFile, PFNRTAIOMGRREQCOMPLETE pfnReqComplete,
314 PRTAIOMGRFILE phAioMgrFile)
315{
316 int rc = VINF_SUCCESS;
317 PRTAIOMGRFILEINT pThis;
318
319 AssertReturn(hAioMgr != NIL_RTAIOMGR, VERR_INVALID_HANDLE);
320 AssertReturn(hFile != NIL_RTFILE, VERR_INVALID_HANDLE);
321 AssertPtrReturn(pfnReqComplete, VERR_INVALID_POINTER);
322 AssertPtrReturn(phAioMgrFile, VERR_INVALID_POINTER);
323
324 pThis = (PRTAIOMGRFILEINT)RTMemAllocZ(sizeof(RTAIOMGRFILEINT));
325 if (pThis)
326 {
327 pThis->u32Magic = RTAIOMGRFILE_MAGIC;
328 pThis->cRefs = 1;
329 pThis->hFile = hFile;
330 pThis->pAioMgr = hAioMgr;
331 rc = RTFileAioCtxAssociateWithFile(pThis->pAioMgr->hAioCtx, hFile);
332 if (RT_FAILURE(rc))
333 rtAioMgrFileDestroy(pThis);
334 }
335 else
336 rc = VERR_NO_MEMORY;
337
338 if (RT_SUCCESS(rc))
339 *phAioMgrFile = pThis;
340
341 return rc;
342}
343
344RTDECL(uint32_t) RTAioMgrFileRetain(RTAIOMGRFILE hAioMgrFile)
345{
346 PRTAIOMGRFILEINT pThis = hAioMgrFile;
347 AssertReturn(hAioMgrFile != NIL_RTAIOMGRFILE, UINT32_MAX);
348 AssertPtrReturn(pThis, UINT32_MAX);
349 AssertReturn(pThis->u32Magic == RTAIOMGRFILE_MAGIC, UINT32_MAX);
350
351 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
352 AssertMsg(cRefs > 1 && cRefs < _1G, ("%#x %p\n", cRefs, pThis));
353 return cRefs;
354}
355
356RTDECL(uint32_t) RTAioMgrFileRelease(RTAIOMGRFILE hAioMgrFile)
357{
358 PRTAIOMGRFILEINT pThis = hAioMgrFile;
359 if (pThis == NIL_RTAIOMGRFILE)
360 return 0;
361 AssertPtrReturn(pThis, UINT32_MAX);
362 AssertReturn(pThis->u32Magic == RTAIOMGRFILE_MAGIC, UINT32_MAX);
363
364 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
365 AssertMsg(cRefs < _1G, ("%#x %p\n", cRefs, pThis));
366 if (cRefs == 0)
367 rtAioMgrFileDestroy(pThis);
368 return cRefs;
369}
370
371RTDECL(int) RTAioMgrFileRead(RTAIOMGRFILE hAioMgrFile, RTFOFF off,
372 PRTSGBUF pSgBuf, size_t cbRead, void *pvUser)
373{
374 return VERR_NOT_IMPLEMENTED;
375}
376
377RTDECL(int) RTAioMgrFileWrite(RTAIOMGRFILE hAioMgrFile, RTFOFF off,
378 PRTSGBUF pSgBuf, size_t cbWrite, void *pvUser)
379{
380 return VERR_NOT_IMPLEMENTED;
381}
382
383RTDECL(int) RTAioMgrFileFlush(RTAIOMGRFILE hAioMgrFile, void *pvUser)
384{
385 return VERR_NOT_IMPLEMENTED;
386}
387
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette