VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/ioqueue/ioqueue-stdfile-provider.cpp@ 98103

Last change on this file since 98103 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.7 KB
Line 
1/* $Id: ioqueue-stdfile-provider.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - I/O queue, Standard file provider.
4 */
5
6/*
7 * Copyright (C) 2019-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#define LOG_GROUP RTLOGGROUP_IOQUEUE
42#include <iprt/ioqueue.h>
43
44#include <iprt/asm.h>
45#include <iprt/errcore.h>
46#include <iprt/file.h>
47#include <iprt/log.h>
48#include <iprt/mem.h>
49#include <iprt/semaphore.h>
50#include <iprt/string.h>
51#include <iprt/thread.h>
52
53#include "internal/ioqueue.h"
54
55
56/*********************************************************************************************************************************
57* Defined Constants And Macros *
58*********************************************************************************************************************************/
59
60/** The I/O queue worker thread needs to wake up the waiting thread when requests completed. */
61#define RTIOQUEUE_STDFILE_PROV_STATE_F_EVTWAIT_NEED_WAKEUP RT_BIT(0)
62/** The waiting thread was interrupted by the external wakeup call. */
63#define RTIOQUEUE_STDFILE_PROV_STATE_F_EVTWAIT_INTR RT_BIT(1)
64#define RTIOQUEUE_STDFILE_PROV_STATE_F_EVTWAIT_INTR_BIT 1
65/** The I/O queue worker thread needs to be woken up to process new requests. */
66#define RTIOQUEUE_STDFILE_PROV_STATE_F_WORKER_NEED_WAKEUP RT_BIT(2)
67#define RTIOQUEUE_STDFILE_PROV_STATE_F_WORKER_NEED_WAKEUP_BIT 2
68
69
70/*********************************************************************************************************************************
71* Structures and Typedefs *
72*********************************************************************************************************************************/
73
74
75/**
76 * Submission queue entry.
77 */
78typedef struct RTIOQUEUESSQENTRY
79{
80 /** The file to work on. */
81 RTFILE hFile;
82 /** I/O operation. */
83 RTIOQUEUEOP enmOp;
84 /** Start offset. */
85 uint64_t off;
86 /** Additional request flags. */
87 uint32_t fReqFlags;
88 /** Size of the request. */
89 size_t cbReq;
90 /** Opaque user data passed on completion. */
91 void *pvUser;
92 /** Flag whether this is a S/G or standard request. */
93 bool fSg;
94 /** Type dependent data. */
95 union
96 {
97 /** Pointer to buffer for non S/G requests. */
98 void *pvBuf;
99 /** Pointer to S/G buffer. */
100 PCRTSGBUF pSgBuf;
101 } u;
102} RTIOQUEUESSQENTRY;
103/** Pointer to a submission queue entry. */
104typedef RTIOQUEUESSQENTRY *PRTIOQUEUESSQENTRY;
105/** Pointer to a constant submission queue entry. */
106typedef const RTIOQUEUESSQENTRY *PCRTIOQUEUESSQENTRY;
107
108
109/**
110 * Internal I/O queue provider instance data.
111 */
112typedef struct RTIOQUEUEPROVINT
113{
114 /** Size of the submission queue in entries. */
115 uint32_t cSqEntries;
116 /** Size of the completion queue in entries. */
117 uint32_t cCqEntries;
118 /** Pointer to the submission queue base. */
119 PRTIOQUEUESSQENTRY paSqEntryBase;
120 /** Submission queue producer index. */
121 volatile uint32_t idxSqProd;
122 /** Submission queue producer value for any uncommitted requests. */
123 uint32_t idxSqProdUncommit;
124 /** Submission queue consumer index. */
125 volatile uint32_t idxSqCons;
126 /** Pointer to the completion queue base. */
127 PRTIOQUEUECEVT paCqEntryBase;
128 /** Completion queue producer index. */
129 volatile uint32_t idxCqProd;
130 /** Completion queue consumer index. */
131 volatile uint32_t idxCqCons;
132 /** Various state flags for synchronizing the worker thread with other participants. */
133 volatile uint32_t fState;
134 /** The worker thread handle. */
135 RTTHREAD hThrdWork;
136 /** Event semaphore the worker thread waits on for work. */
137 RTSEMEVENT hSemEvtWorker;
138 /** Event semaphore the caller waits for completion events. */
139 RTSEMEVENT hSemEvtWaitEvts;
140 /** Flag whether to shutdown the worker thread. */
141 volatile bool fShutdown;
142} RTIOQUEUEPROVINT;
143/** Pointer to the internal I/O queue provider instance data. */
144typedef RTIOQUEUEPROVINT *PRTIOQUEUEPROVINT;
145
146
147/*********************************************************************************************************************************
148* Internal Functions *
149*********************************************************************************************************************************/
150
151
152/**
153 * Processes the given submission queue entry and reports back the result in the completion queue.
154 *
155 * @returns nothing.
156 * @param pSqEntry The submission queue entry to process.
157 * @param pCqEntry The comppletion queue entry to store the result in.
158 */
159static void rtIoQueueStdFileProv_SqEntryProcess(PCRTIOQUEUESSQENTRY pSqEntry, PRTIOQUEUECEVT pCqEntry)
160{
161 int rcReq = VINF_SUCCESS;
162
163 switch (pSqEntry->enmOp)
164 {
165 case RTIOQUEUEOP_READ:
166 if (!pSqEntry->fSg)
167 rcReq = RTFileReadAt(pSqEntry->hFile, pSqEntry->off, pSqEntry->u.pvBuf, pSqEntry->cbReq, NULL);
168 else
169 {
170 RTSGBUF SgBuf;
171 RTSgBufClone(&SgBuf, pSqEntry->u.pSgBuf);
172 rcReq = RTFileSgReadAt(pSqEntry->hFile, pSqEntry->off, &SgBuf, pSqEntry->cbReq, NULL);
173 }
174 break;
175 case RTIOQUEUEOP_WRITE:
176 if (!pSqEntry->fSg)
177 rcReq = RTFileWriteAt(pSqEntry->hFile, pSqEntry->off, pSqEntry->u.pvBuf, pSqEntry->cbReq, NULL);
178 else
179 {
180 RTSGBUF SgBuf;
181 RTSgBufClone(&SgBuf, pSqEntry->u.pSgBuf);
182 rcReq = RTFileSgWriteAt(pSqEntry->hFile, pSqEntry->off, &SgBuf, pSqEntry->cbReq, NULL);
183 }
184 break;
185 case RTIOQUEUEOP_SYNC:
186 rcReq = RTFileFlush(pSqEntry->hFile);
187 break;
188 default:
189 AssertMsgFailedReturnVoid(("Invalid I/O queue operation: %d\n", pSqEntry->enmOp));
190 }
191
192 /* Write the result back into the completion queue. */
193 pCqEntry->rcReq = rcReq;
194 pCqEntry->pvUser = pSqEntry->pvUser;
195 pCqEntry->cbXfered = RT_SUCCESS(rcReq) ? pSqEntry->cbReq : 0;
196}
197
198
199/**
200 * The main I/O queue worker loop which processes the incoming I/O requests.
201 */
202static DECLCALLBACK(int) rtIoQueueStdFileProv_WorkerLoop(RTTHREAD hThrdSelf, void *pvUser)
203{
204 PRTIOQUEUEPROVINT pThis = (PRTIOQUEUEPROVINT)pvUser;
205
206 /* Signal that we started up. */
207 int rc = RTThreadUserSignal(hThrdSelf);
208 AssertRC(rc);
209
210 while (!ASMAtomicReadBool(&pThis->fShutdown))
211 {
212 /* Wait for some work. */
213 ASMAtomicOrU32(&pThis->fState, RTIOQUEUE_STDFILE_PROV_STATE_F_WORKER_NEED_WAKEUP);
214 uint32_t idxSqProd = ASMAtomicReadU32(&pThis->idxSqProd);
215 uint32_t idxSqCons = ASMAtomicReadU32(&pThis->idxSqCons);
216 uint32_t idxCqCons = ASMAtomicReadU32(&pThis->idxCqCons);
217
218 if (idxSqCons == idxSqProd)
219 {
220 rc = RTSemEventWait(pThis->hSemEvtWorker, RT_INDEFINITE_WAIT);
221 AssertRC(rc);
222
223 idxSqProd = ASMAtomicReadU32(&pThis->idxSqProd);
224 idxSqCons = ASMAtomicReadU32(&pThis->idxSqCons);
225 idxCqCons = ASMAtomicReadU32(&pThis->idxCqCons);
226 }
227
228 ASMAtomicBitTestAndClear(&pThis->fState, RTIOQUEUE_STDFILE_PROV_STATE_F_WORKER_NEED_WAKEUP_BIT);
229
230 /* Process all requests. */
231 uint32_t cCqFree = 0;
232 if (idxCqCons > pThis->idxCqProd)
233 cCqFree = pThis->cCqEntries - (pThis->cCqEntries - idxCqCons) - pThis->idxCqProd;
234 else
235 cCqFree = pThis->cCqEntries - pThis->idxCqProd - idxCqCons;
236 do
237 {
238 while ( idxSqCons != idxSqProd
239 && cCqFree)
240 {
241 PCRTIOQUEUESSQENTRY pSqEntry = &pThis->paSqEntryBase[idxSqCons];
242 PRTIOQUEUECEVT pCqEntry = &pThis->paCqEntryBase[pThis->idxCqProd];
243
244 rtIoQueueStdFileProv_SqEntryProcess(pSqEntry, pCqEntry);
245 ASMWriteFence();
246
247 idxSqCons = (idxSqCons + 1) % pThis->cSqEntries;
248 cCqFree--;
249 pThis->idxCqProd = (pThis->idxCqProd + 1) % pThis->cCqEntries;
250 ASMAtomicWriteU32(&pThis->idxSqCons, idxSqCons);
251 ASMWriteFence();
252 if (ASMAtomicReadU32(&pThis->fState) & RTIOQUEUE_STDFILE_PROV_STATE_F_EVTWAIT_NEED_WAKEUP)
253 {
254 rc = RTSemEventSignal(pThis->hSemEvtWaitEvts);
255 AssertRC(rc);
256 }
257 }
258
259 idxSqProd = ASMAtomicReadU32(&pThis->idxSqProd);
260 } while ( idxSqCons != idxSqProd
261 && cCqFree);
262 }
263
264 return VINF_SUCCESS;
265}
266
267
268/** @interface_method_impl{RTIOQUEUEPROVVTABLE,pfnIsSupported} */
269static DECLCALLBACK(bool) rtIoQueueStdFileProv_IsSupported(void)
270{
271 /* The common code/public API already checked for the proper handle type. */
272 return true;
273}
274
275
276/** @interface_method_impl{RTIOQUEUEPROVVTABLE,pfnQueueInit} */
277static DECLCALLBACK(int) rtIoQueueStdFileProv_QueueInit(RTIOQUEUEPROV hIoQueueProv, uint32_t fFlags,
278 uint32_t cSqEntries, uint32_t cCqEntries)
279{
280 RT_NOREF(fFlags);
281
282 PRTIOQUEUEPROVINT pThis = hIoQueueProv;
283 int rc = VINF_SUCCESS;
284
285 cSqEntries++;
286 cCqEntries++;
287
288 pThis->cSqEntries = cSqEntries;
289 pThis->cCqEntries = cCqEntries;
290 pThis->idxSqProd = 0;
291 pThis->idxSqProdUncommit = 0;
292 pThis->idxSqCons = 0;
293 pThis->idxCqProd = 0;
294 pThis->idxCqCons = 0;
295 pThis->fShutdown = false;
296 pThis->fState = 0;
297
298 pThis->paSqEntryBase = (PRTIOQUEUESSQENTRY)RTMemAllocZ(cSqEntries * sizeof(RTIOQUEUESSQENTRY));
299 if (RT_LIKELY(pThis->paSqEntryBase))
300 {
301 pThis->paCqEntryBase = (PRTIOQUEUECEVT)RTMemAllocZ(cCqEntries * sizeof(RTIOQUEUECEVT));
302 if (RT_LIKELY(pThis->paSqEntryBase))
303 {
304 rc = RTSemEventCreate(&pThis->hSemEvtWorker);
305 if (RT_SUCCESS(rc))
306 {
307 rc = RTSemEventCreate(&pThis->hSemEvtWaitEvts);
308 if (RT_SUCCESS(rc))
309 {
310 /* Spin up the worker thread. */
311 rc = RTThreadCreate(&pThis->hThrdWork, rtIoQueueStdFileProv_WorkerLoop, pThis, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE,
312 "IoQ-StdFile");
313 if (RT_SUCCESS(rc))
314 {
315 rc = RTThreadUserWait(pThis->hThrdWork, 10 * RT_MS_1SEC);
316 AssertRC(rc);
317
318 return VINF_SUCCESS;
319 }
320
321 RTSemEventDestroy(pThis->hSemEvtWaitEvts);
322 }
323
324 RTSemEventDestroy(pThis->hSemEvtWorker);
325 }
326
327 RTMemFree(pThis->paCqEntryBase);
328 }
329 else
330 rc = VERR_NO_MEMORY;
331
332 RTMemFree(pThis->paSqEntryBase);
333 }
334 else
335 rc = VERR_NO_MEMORY;
336
337 return rc;
338}
339
340
341/** @interface_method_impl{RTIOQUEUEPROVVTABLE,pfnQueueDestroy} */
342static DECLCALLBACK(void) rtIoQueueStdFileProv_QueueDestroy(RTIOQUEUEPROV hIoQueueProv)
343{
344 PRTIOQUEUEPROVINT pThis = hIoQueueProv;
345
346 ASMAtomicXchgBool(&pThis->fShutdown, true);
347 RTSemEventSignal(pThis->hSemEvtWorker);
348
349 int rc = RTThreadWait(pThis->hThrdWork, 60 * RT_MS_1SEC, NULL);
350 AssertRC(rc);
351
352 RTSemEventDestroy(pThis->hSemEvtWaitEvts);
353 RTSemEventDestroy(pThis->hSemEvtWorker);
354 RTMemFree(pThis->paCqEntryBase);
355 RTMemFree(pThis->paSqEntryBase);
356 RT_BZERO(pThis, sizeof(*pThis));
357}
358
359
360/** @interface_method_impl{RTIOQUEUEPROVVTABLE,pfnHandleRegister} */
361static DECLCALLBACK(int) rtIoQueueStdFileProv_HandleRegister(RTIOQUEUEPROV hIoQueueProv, PCRTHANDLE pHandle)
362{
363 RT_NOREF(hIoQueueProv, pHandle);
364
365 /* Nothing to do here. */
366 return VINF_SUCCESS;
367}
368
369
370/** @interface_method_impl{RTIOQUEUEPROVVTABLE,pfnHandleDeregister} */
371static DECLCALLBACK(int) rtIoQueueStdFileProv_HandleDeregister(RTIOQUEUEPROV hIoQueueProv, PCRTHANDLE pHandle)
372{
373 RT_NOREF(hIoQueueProv, pHandle);
374
375 /* Nothing to do here. */
376 return VINF_SUCCESS;
377}
378
379
380/** @interface_method_impl{RTIOQUEUEPROVVTABLE,pfnReqPrepare} */
381static DECLCALLBACK(int) rtIoQueueStdFileProv_ReqPrepare(RTIOQUEUEPROV hIoQueueProv, PCRTHANDLE pHandle, RTIOQUEUEOP enmOp,
382 uint64_t off, void *pvBuf, size_t cbBuf, uint32_t fReqFlags,
383 void *pvUser)
384{
385 PRTIOQUEUEPROVINT pThis = hIoQueueProv;
386 PRTIOQUEUESSQENTRY pSqEntry = &pThis->paSqEntryBase[pThis->idxSqProdUncommit];
387
388 pSqEntry->hFile = pHandle->u.hFile;
389 pSqEntry->enmOp = enmOp;
390 pSqEntry->off = off;
391 pSqEntry->fReqFlags = fReqFlags;
392 pSqEntry->cbReq = cbBuf;
393 pSqEntry->pvUser = pvUser;
394 pSqEntry->fSg = false;
395 pSqEntry->u.pvBuf = pvBuf;
396
397 pThis->idxSqProdUncommit = (pThis->idxSqProdUncommit + 1) % pThis->cSqEntries;
398 return VINF_SUCCESS;
399}
400
401
402/** @interface_method_impl{RTIOQUEUEPROVVTABLE,pfnReqPrepareSg} */
403static DECLCALLBACK(int) rtIoQueueStdFileProv_ReqPrepareSg(RTIOQUEUEPROV hIoQueueProv, PCRTHANDLE pHandle, RTIOQUEUEOP enmOp,
404 uint64_t off, PCRTSGBUF pSgBuf, size_t cbSg, uint32_t fReqFlags,
405 void *pvUser)
406{
407 PRTIOQUEUEPROVINT pThis = hIoQueueProv;
408 PRTIOQUEUESSQENTRY pSqEntry = &pThis->paSqEntryBase[pThis->idxSqProdUncommit];
409
410 pSqEntry->hFile = pHandle->u.hFile;
411 pSqEntry->enmOp = enmOp;
412 pSqEntry->off = off;
413 pSqEntry->fReqFlags = fReqFlags;
414 pSqEntry->cbReq = cbSg;
415 pSqEntry->pvUser = pvUser;
416 pSqEntry->fSg = true;
417 pSqEntry->u.pSgBuf = pSgBuf;
418
419 pThis->idxSqProdUncommit = (pThis->idxSqProdUncommit + 1) % pThis->cSqEntries;
420 return VINF_SUCCESS;
421}
422
423
424/** @interface_method_impl{RTIOQUEUEPROVVTABLE,pfnCommit} */
425static DECLCALLBACK(int) rtIoQueueStdFileProv_Commit(RTIOQUEUEPROV hIoQueueProv, uint32_t *pcReqsCommitted)
426{
427 PRTIOQUEUEPROVINT pThis = hIoQueueProv;
428
429 if (pThis->idxSqProd > pThis->idxSqProdUncommit)
430 *pcReqsCommitted = pThis->cSqEntries - pThis->idxSqProd + pThis->idxSqProdUncommit;
431 else
432 *pcReqsCommitted = pThis->idxSqProdUncommit - pThis->idxSqProd;
433
434 ASMWriteFence();
435 ASMAtomicWriteU32(&pThis->idxSqProd, pThis->idxSqProdUncommit);
436 return RTSemEventSignal(pThis->hSemEvtWorker);
437}
438
439
440/** @interface_method_impl{RTIOQUEUEPROVVTABLE,pfnEvtWait} */
441static DECLCALLBACK(int) rtIoQueueStdFileProv_EvtWait(RTIOQUEUEPROV hIoQueueProv, PRTIOQUEUECEVT paCEvt, uint32_t cCEvt,
442 uint32_t cMinWait, uint32_t *pcCEvt, uint32_t fFlags)
443{
444 RT_NOREF(fFlags);
445
446 PRTIOQUEUEPROVINT pThis = hIoQueueProv;
447 int rc = VINF_SUCCESS;
448 uint32_t idxCEvt = 0;
449
450 while ( RT_SUCCESS(rc)
451 && cMinWait
452 && cCEvt)
453 {
454 ASMAtomicOrU32(&pThis->fState, RTIOQUEUE_STDFILE_PROV_STATE_F_EVTWAIT_NEED_WAKEUP);
455 uint32_t idxCqProd = ASMAtomicReadU32(&pThis->idxCqProd);
456 uint32_t idxCqCons = ASMAtomicReadU32(&pThis->idxCqCons);
457
458 if (idxCqCons == idxCqProd)
459 {
460 rc = RTSemEventWait(pThis->hSemEvtWaitEvts, RT_INDEFINITE_WAIT);
461 AssertRC(rc);
462 if (ASMAtomicBitTestAndClear(&pThis->fState, RTIOQUEUE_STDFILE_PROV_STATE_F_EVTWAIT_INTR_BIT))
463 {
464 rc = VERR_INTERRUPTED;
465 ASMAtomicBitTestAndClear(&pThis->fState, RTIOQUEUE_STDFILE_PROV_STATE_F_WORKER_NEED_WAKEUP_BIT);
466 break;
467 }
468
469 idxCqProd = ASMAtomicReadU32(&pThis->idxCqProd);
470 idxCqCons = ASMAtomicReadU32(&pThis->idxCqCons);
471 }
472
473 ASMAtomicBitTestAndClear(&pThis->fState, RTIOQUEUE_STDFILE_PROV_STATE_F_WORKER_NEED_WAKEUP_BIT);
474
475 /* Process all requests. */
476 while ( idxCqCons != idxCqProd
477 && cCEvt)
478 {
479 PRTIOQUEUECEVT pCqEntry = &pThis->paCqEntryBase[idxCqCons];
480
481 paCEvt[idxCEvt].rcReq = pCqEntry->rcReq;
482 paCEvt[idxCEvt].pvUser = pCqEntry->pvUser;
483 paCEvt[idxCEvt].cbXfered = pCqEntry->cbXfered;
484 ASMReadFence();
485
486 idxCEvt++;
487 cCEvt--;
488 cMinWait--;
489
490 idxCqCons = (idxCqCons + 1) % pThis->cCqEntries;
491 pThis->idxCqCons = (pThis->idxCqCons + 1) % pThis->cCqEntries;
492 ASMWriteFence();
493 }
494 }
495
496 *pcCEvt = idxCEvt;
497 return rc;
498}
499
500
501/** @interface_method_impl{RTIOQUEUEPROVVTABLE,pfnEvtWaitWakeup} */
502static DECLCALLBACK(int) rtIoQueueStdFileProv_EvtWaitWakeup(RTIOQUEUEPROV hIoQueueProv)
503{
504 PRTIOQUEUEPROVINT pThis = hIoQueueProv;
505
506 ASMAtomicOrU32(&pThis->fState, RTIOQUEUE_STDFILE_PROV_STATE_F_EVTWAIT_INTR);
507 return RTSemEventSignal(pThis->hSemEvtWaitEvts);
508}
509
510
511/**
512 * Standard file I/O queue provider virtual method table.
513 */
514RT_DECL_DATA_CONST(RTIOQUEUEPROVVTABLE const) g_RTIoQueueStdFileProv =
515{
516 /** uVersion */
517 RTIOQUEUEPROVVTABLE_VERSION,
518 /** pszId */
519 "StdFile",
520 /** cbIoQueueProv */
521 sizeof(RTIOQUEUEPROVINT),
522 /** enmHnd */
523 RTHANDLETYPE_FILE,
524 /** fFlags */
525 0,
526 /** pfnIsSupported */
527 rtIoQueueStdFileProv_IsSupported,
528 /** pfnQueueInit */
529 rtIoQueueStdFileProv_QueueInit,
530 /** pfnQueueDestroy */
531 rtIoQueueStdFileProv_QueueDestroy,
532 /** pfnHandleRegister */
533 rtIoQueueStdFileProv_HandleRegister,
534 /** pfnHandleDeregister */
535 rtIoQueueStdFileProv_HandleDeregister,
536 /** pfnReqPrepare */
537 rtIoQueueStdFileProv_ReqPrepare,
538 /** pfnReqPrepareSg */
539 rtIoQueueStdFileProv_ReqPrepareSg,
540 /** pfnCommit */
541 rtIoQueueStdFileProv_Commit,
542 /** pfnEvtWait */
543 rtIoQueueStdFileProv_EvtWait,
544 /** pfnEvtWaitWakeup */
545 rtIoQueueStdFileProv_EvtWaitWakeup,
546 /** uEndMarker */
547 RTIOQUEUEPROVVTABLE_VERSION
548};
549
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