Changeset 19562 in vbox for trunk/src/VBox/Runtime/r3
- Timestamp:
- May 10, 2009 9:44:16 PM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 47117
- Location:
- trunk/src/VBox/Runtime/r3
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/freebsd/fileaio-freebsd.cpp
r19187 r19562 47 47 #include <sys/event.h> 48 48 #include <sys/time.h> 49 #include <sys/sysctl.h> 49 50 #include <aio.h> 50 51 #include <errno.h> … … 84 85 * element. */ 85 86 struct aiocb AioCB; 87 /** Current state the request is in. */ 88 RTFILEAIOREQSTATE enmState; 86 89 /** Flag whether this is a flush request. */ 87 90 bool fFlush; … … 107 110 #define AIO_MAXIMUM_REQUESTS_PER_CONTEXT 64 108 111 112 RTR3DECL(int) RTFileAioGetLimits(PRTFILEAIOLIMITS pAioLimits) 113 { 114 int rcBSD = 0; 115 AssertPtrReturn(pAioLimits, VERR_INVALID_POINTER); 116 117 /* 118 * The AIO API is implemented in a kernel module which is not 119 * loaded by default. 120 * If it is loaded there are additional sysctl parameters. 121 */ 122 int cReqsOutstandingMax = 0; 123 size_t cbParameter = sizeof(int); 124 125 rcBSD = sysctlbyname("vfs.aio.max_aio_per_proc", /* name */ 126 &cReqsOutstandingMax, /* Where to store the old value. */ 127 &cbParameter, /* Size of the memory pointed to. */ 128 NULL, /* Where the new value is located. */ 129 NULL); /* Where the size of the new value is stored. */ 130 if (rcBSD == -1) 131 { 132 /* ENOENT means the value is unknown thus the module is not loaded. */ 133 if (errno == ENOENT) 134 return VERR_NOT_SUPPORTED; 135 else 136 return RTErrConvertFromErrno(errno); 137 } 138 139 pAioLimits->cReqsOutstandingMax = cReqsOutstandingMax; 140 pAioLimits->cbBufferAlignment = 0; 141 142 return VINF_SUCCESS; 143 } 144 109 145 RTR3DECL(int) RTFileAioReqCreate(PRTFILEAIOREQ phReq) 110 146 { … … 120 156 pReqInt->pCtxInt = NULL; 121 157 pReqInt->u32Magic = RTFILEAIOREQ_MAGIC; 158 RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); 122 159 123 160 *phReq = (RTFILEAIOREQ)pReqInt; … … 126 163 } 127 164 128 RTDECL( void) RTFileAioReqDestroy(RTFILEAIOREQ hReq)165 RTDECL(int) RTFileAioReqDestroy(RTFILEAIOREQ hReq) 129 166 { 130 167 /* … … 132 169 */ 133 170 if (hReq == NIL_RTFILEAIOREQ) 134 return ;171 return VINF_SUCCESS; 135 172 PRTFILEAIOREQINTERNAL pReqInt = hReq; 136 RTFILEAIOREQ_VALID_RETURN_VOID(pReqInt); 173 RTFILEAIOREQ_VALID_RETURN(pReqInt); 174 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); 137 175 138 176 /* … … 141 179 ASMAtomicUoWriteU32(&pReqInt->u32Magic, ~RTFILEAIOREQ_MAGIC); 142 180 RTMemFree(pReqInt); 181 return VINF_SUCCESS; 143 182 } 144 183 … … 156 195 PRTFILEAIOREQINTERNAL pReqInt = hReq; 157 196 RTFILEAIOREQ_VALID_RETURN(pReqInt); 197 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); 158 198 Assert(hFile != NIL_RTFILE); 159 199 AssertPtr(pvBuf); … … 171 211 pReqInt->pCtxInt = NULL; 172 212 pReqInt->Rc = VERR_FILE_AIO_IN_PROGRESS; 213 RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); 173 214 174 215 return VINF_SUCCESS; … … 195 236 RTFILEAIOREQ_VALID_RETURN(pReqInt); 196 237 Assert(hFile != NIL_RTFILE); 238 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); 197 239 198 240 pReqInt->fFlush = true; 199 241 pReqInt->AioCB.aio_fildes = (int)hFile; 200 242 pReqInt->pvUser = pvUser; 243 RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); 201 244 202 245 return VINF_SUCCESS; … … 215 258 PRTFILEAIOREQINTERNAL pReqInt = hReq; 216 259 RTFILEAIOREQ_VALID_RETURN(pReqInt); 260 RTFILEAIOREQ_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_NOT_SUBMITTED); 261 217 262 218 263 int rcBSD = aio_cancel(pReqInt->AioCB.aio_fildes, &pReqInt->AioCB); … … 228 273 229 274 ASMAtomicDecS32(&pReqInt->pCtxInt->cRequests); 275 pReqInt->Rc = VERR_FILE_AIO_CANCELED; 276 RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); 230 277 return VINF_SUCCESS; 231 278 } … … 243 290 RTFILEAIOREQ_VALID_RETURN(pReqInt); 244 291 AssertPtrNull(pcbTransfered); 245 246 if ( (pReqInt->Rc != VERR_FILE_AIO_IN_PROGRESS) 292 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); 293 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, PREPARED, VERR_FILE_AIO_NOT_SUBMITTED); 294 295 if ( (RT_SUCCESS(pReqInt->Rc)) 247 296 && (pcbTransfered)) 248 297 *pcbTransfered = pReqInt->cbTransfered; … … 306 355 } 307 356 308 RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs , size_t *pcReqs)357 RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs) 309 358 { 310 359 /* 311 360 * Parameter validation. 312 361 */ 313 AssertPtrReturn(pcReqs, VERR_INVALID_POINTER); 314 *pcReqs = 0; 362 int rc = VINF_SUCCESS; 315 363 PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; 316 364 RTFILEAIOCTX_VALID_RETURN(pCtxInt); … … 330 378 { 331 379 pReqInt = pahReqs[i]; 332 RTFILEAIOREQ_VALID_RETURN(pReqInt); 380 if (RTFILEAIOREQ_IS_NOT_VALID(pReqInt)) 381 { 382 /* Undo everything and stop submitting. */ 383 for (size_t iUndo = 0; iUndo < i; iUndo++) 384 { 385 pReqInt = pahReqs[iUndo]; 386 RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); 387 pReqInt->pCtxInt = NULL; 388 pReqInt->AioCB.aio_sigevent.sigev_notify_kqueue = 0; 389 } 390 rc = VERR_INVALID_HANDLE; 391 break; 392 } 333 393 334 394 pReqInt->AioCB.aio_sigevent.sigev_notify_kqueue = pCtxInt->iKQueue; 335 395 pReqInt->pCtxInt = pCtxInt; 396 RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED); 336 397 337 398 if (pReqInt->fFlush) … … 346 407 rcBSD = lio_listio(LIO_NOWAIT, (struct aiocb **)pahReqs, cReqsSubmit, NULL); 347 408 if (RT_UNLIKELY(rcBSD < 0)) 348 return RTErrConvertFromErrno(errno); 409 { 410 if (rcBSD == EAGAIN) 411 rc = VERR_FILE_AIO_INSUFFICIENT_RESSOURCES; 412 else 413 rc = RTErrConvertFromErrno(errno); 414 415 /* Check which requests got actually submitted and which not. */ 416 for (i = 0; i < cReqs; i++) 417 { 418 pReqInt = pahReqs[i]; 419 rcBSD = aio_error(&pReqInt->AioCB); 420 if (rcBSD == EINVAL) 421 { 422 /* Was not submitted. */ 423 RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); 424 pReqInt->pCtxInt = NULL; 425 } 426 else if (rcBSD != EINPROGRESS) 427 { 428 /* The request encountered an error. */ 429 RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); 430 pReqInt->Rc = RTErrConvertFromErrno(rcBSD); 431 pReqInt->pCtxInt = NULL; 432 pReqInt->cbTransfered = 0; 433 } 434 } 435 break; 436 } 349 437 350 438 ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmit); 351 439 cReqs -= cReqsSubmit; 352 440 pahReqs += cReqsSubmit; 353 *pcReqs += cReqsSubmit;354 441 } 355 442 … … 368 455 rcBSD = aio_fsync(O_SYNC, &pReqInt->AioCB); 369 456 if (RT_UNLIKELY(rcBSD < 0)) 370 return RTErrConvertFromErrno(errno); 457 { 458 RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); 459 pReqInt->Rc = RTErrConvertFromErrno(errno); 460 pReqInt->cbTransfered = 0; 461 return pReqInt->Rc; 462 } 371 463 372 464 ASMAtomicIncS32(&pCtxInt->cRequests); 373 465 cReqs--; 374 466 pahReqs++; 375 *pcReqs++;376 467 } 377 468 } 378 469 } while (cReqs); 379 470 380 return VINF_SUCCESS;471 return rc; 381 472 } 382 473 … … 447 538 { 448 539 PRTFILEAIOREQINTERNAL pReqInt = (PRTFILEAIOREQINTERNAL)aKEvents[i].udata; 540 AssertPtr(pReqInt); 541 Assert(pReqInt->u32Magic == RTFILEAIOREQ_MAGIC); 449 542 450 543 /* … … 468 561 pReqInt->cbTransfered = cbTransfered; 469 562 } 563 RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); 470 564 pahReqs[cRequestsCompleted++] = (RTFILEAIOREQ)pReqInt; 471 565 } -
trunk/src/VBox/Runtime/r3/linux/fileaio-linux.cpp
r19371 r19562 190 190 * the structure! (see notes below) */ 191 191 LNXKAIOIOCB AioCB; 192 /** Current state the request is in. */ 193 RTFILEAIOREQSTATE enmState; 192 194 /** The I/O context this request is associated with. */ 193 195 aio_context_t AioContext; 194 196 /** Return code the request completed with. */ 195 197 int Rc; 196 /** Flag whether the request is in process or not. */197 bool fFinished;198 198 /** Number of bytes actually trasnfered. */ 199 199 size_t cbTransfered; … … 241 241 * Submits an array of I/O requests to the kernel. 242 242 */ 243 DECLINLINE(int) rtFileAsyncIoLinuxSubmit(aio_context_t AioContext, long cReqs, LNXKAIOIOCB **ppIoCB )243 DECLINLINE(int) rtFileAsyncIoLinuxSubmit(aio_context_t AioContext, long cReqs, LNXKAIOIOCB **ppIoCB, int *pcSubmitted) 244 244 { 245 245 int rc = syscall(__NR_io_submit, AioContext, cReqs, ppIoCB); … … 247 247 return RTErrConvertFromErrno(errno); 248 248 249 *pcSubmitted = rc; 250 249 251 return VINF_SUCCESS; 250 252 } … … 276 278 } 277 279 280 RTR3DECL(int) RTFileAioGetLimits(PRTFILEAIOLIMITS pAioLimits) 281 { 282 int rc = VINF_SUCCESS; 283 AssertPtrReturn(pAioLimits, VERR_INVALID_POINTER); 284 285 /* 286 * Check if the API is implemented by creating a 287 * completion port. 288 */ 289 aio_context_t AioContext = 0; 290 rc = rtFileAsyncIoLinuxCreate(1, &AioContext); 291 if (RT_FAILURE(rc)) 292 return rc; 293 294 rc = rtFileAsyncIoLinuxDestroy(AioContext); 295 if (RT_FAILURE(rc)) 296 return rc; 297 298 /* Supported - fill in the limits. The alignment is the only restriction. */ 299 pAioLimits->cReqsOutstandingMax = RTFILEAIO_UNLIMITED_REQS; 300 pAioLimits->cbBufferAlignment = 512; 301 302 return VINF_SUCCESS; 303 } 304 305 278 306 RTR3DECL(int) RTFileAioReqCreate(PRTFILEAIOREQ phReq) 279 307 { … … 287 315 return VERR_NO_MEMORY; 288 316 289 pReqInt->fFinished = false;290 317 pReqInt->pCtxInt = NULL; 291 318 pReqInt->u32Magic = RTFILEAIOREQ_MAGIC; 319 RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); 292 320 293 321 *phReq = (RTFILEAIOREQ)pReqInt; … … 296 324 297 325 298 RTDECL( void) RTFileAioReqDestroy(RTFILEAIOREQ hReq)326 RTDECL(int) RTFileAioReqDestroy(RTFILEAIOREQ hReq) 299 327 { 300 328 /* … … 302 330 */ 303 331 if (hReq == NIL_RTFILEAIOREQ) 304 return ;332 return VINF_SUCCESS; 305 333 PRTFILEAIOREQINTERNAL pReqInt = hReq; 306 RTFILEAIOREQ_VALID_RETURN_VOID(pReqInt); 334 RTFILEAIOREQ_VALID_RETURN(pReqInt); 335 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); 307 336 308 337 /* … … 311 340 ASMAtomicUoWriteU32(&pReqInt->u32Magic, ~RTFILEAIOREQ_MAGIC); 312 341 RTMemFree(pReqInt); 342 return VINF_SUCCESS; 313 343 } 314 344 … … 327 357 PRTFILEAIOREQINTERNAL pReqInt = hReq; 328 358 RTFILEAIOREQ_VALID_RETURN(pReqInt); 359 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); 329 360 Assert(hFile != NIL_RTFILE); 330 361 AssertPtr(pvBuf); … … 342 373 pReqInt->AioCB.pvUser = pvUser; 343 374 344 pReqInt->fFinished = false;345 375 pReqInt->pCtxInt = NULL; 376 RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); 346 377 347 378 return VINF_SUCCESS; … … 370 401 RTFILEAIOREQ_VALID_RETURN(pReqInt); 371 402 AssertReturn(hFile != NIL_RTFILE, VERR_INVALID_HANDLE); 403 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); 372 404 373 405 /** @todo: Flushing is not neccessary on Linux because O_DIRECT is mandatory … … 397 429 PRTFILEAIOREQINTERNAL pReqInt = hReq; 398 430 RTFILEAIOREQ_VALID_RETURN(pReqInt); 431 RTFILEAIOREQ_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_NOT_SUBMITTED); 399 432 400 433 LNXKAIOIOEVENT AioEvent; … … 410 443 411 444 ASMAtomicDecS32(&pReqInt->pCtxInt->cRequests); 445 pReqInt->Rc = VERR_FILE_AIO_CANCELED; 446 RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); 412 447 return VINF_SUCCESS; 413 448 } … … 423 458 RTFILEAIOREQ_VALID_RETURN(pReqInt); 424 459 AssertPtrNull(pcbTransfered); 425 426 if (!pReqInt->fFinished) 427 return VERR_FILE_AIO_IN_PROGRESS; 460 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); 461 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, PREPARED, VERR_FILE_AIO_NOT_SUBMITTED); 428 462 429 463 if ( pcbTransfered … … 509 543 } 510 544 511 RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs, size_t *pcReqs) 512 { 545 RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs) 546 { 547 int rc = VINF_SUCCESS; 548 513 549 /* 514 550 * Parameter validation. 515 551 */ 516 AssertPtrReturn(pcReqs, VERR_INVALID_POINTER);517 *pcReqs = 0;518 552 PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; 519 553 RTFILEAIOCTX_VALID_RETURN(pCtxInt); … … 521 555 AssertPtrReturn(pahReqs, VERR_INVALID_POINTER); 522 556 uint32_t i = cReqs; 557 PRTFILEAIOREQINTERNAL pReqInt = NULL; 523 558 524 559 /* … … 527 562 while (i-- > 0) 528 563 { 529 PRTFILEAIOREQINTERNAL pReqInt = pahReqs[i]; 530 RTFILEAIOREQ_VALID_RETURN(pReqInt); 564 pReqInt = pahReqs[i]; 565 if (RTFILEAIOREQ_IS_NOT_VALID(pReqInt)) 566 { 567 /* Undo everything and stop submitting. */ 568 size_t iUndo = cReqs; 569 while (iUndo-- > i) 570 { 571 pReqInt = pahReqs[iUndo]; 572 RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); 573 pReqInt->pCtxInt = NULL; 574 } 575 return VERR_INVALID_HANDLE; 576 } 531 577 532 578 pReqInt->AioContext = pCtxInt->AioContext; 533 579 pReqInt->pCtxInt = pCtxInt; 580 RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED); 534 581 } 535 582 536 /* 537 * Add the submitted requests to the counter 538 * to prevent destroying the context while 539 * it is still used. 540 */ 541 ASMAtomicAddS32(&pCtxInt->cRequests, cReqs); 542 543 /* 544 * We cast phReqs to the Linux iocb structure to avoid copying the requests 545 * into a temporary array. This is possible because the iocb structure is 546 * the first element in the request structure (see PRTFILEAIOCTXINTERNAL). 547 */ 548 int rc = rtFileAsyncIoLinuxSubmit(pCtxInt->AioContext, cReqs, (PLNXKAIOIOCB *)pahReqs); 549 if (RT_FAILURE(rc)) 550 ASMAtomicSubS32(&pCtxInt->cRequests, cReqs); 551 else 552 *pcReqs = cReqs; 583 do 584 { 585 /* 586 * We cast pahReqs to the Linux iocb structure to avoid copying the requests 587 * into a temporary array. This is possible because the iocb structure is 588 * the first element in the request structure (see PRTFILEAIOCTXINTERNAL). 589 */ 590 int cReqsSubmitted = 0; 591 rc = rtFileAsyncIoLinuxSubmit(pCtxInt->AioContext, cReqs, 592 (PLNXKAIOIOCB *)pahReqs, 593 &cReqsSubmitted); 594 if (RT_FAILURE(rc)) 595 { 596 /* 597 * We encountered an error. 598 * This means that the first IoCB 599 * is not correctly initialized 600 * (invalid buffer alignment or bad file descriptor). 601 * Revert every request into the prepared state except 602 * the first one which will switch to completed. 603 * Another reason could be insuffidient ressources. 604 */ 605 i = cReqs; 606 while (i-- > 0) 607 { 608 /* Already validated. */ 609 pReqInt = pahReqs[i]; 610 pReqInt->pCtxInt = NULL; 611 pReqInt->AioContext = 0; 612 RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); 613 } 614 615 if (rc == VERR_TRY_AGAIN) 616 return VERR_FILE_AIO_INSUFFICIENT_RESSOURCES; 617 else 618 { 619 /* The first request failed. */ 620 pReqInt = pahReqs[0]; 621 RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); 622 pReqInt->Rc = rc; 623 pReqInt->cbTransfered = 0; 624 return rc; 625 } 626 } 627 628 /* Advance. */ 629 cReqs -= cReqsSubmitted; 630 pahReqs += cReqsSubmitted; 631 ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmitted); 632 633 } while (cReqs); 553 634 554 635 return rc; … … 643 724 644 725 /* Mark the request as finished. */ 645 pReqInt->fFinished = true;726 RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); 646 727 647 728 pahReqs[cRequestsCompleted++] = (RTFILEAIOREQ)pReqInt; -
trunk/src/VBox/Runtime/r3/posix/fileaio-posix.cpp
r19370 r19562 45 45 #include "internal/fileaio.h" 46 46 47 #if defined(RT_OS_DARWIN) 48 # include <sys/types.h> 49 # include <sys/sysctl.h> /* for sysctlbyname */ 50 #endif 47 51 #include <aio.h> 48 52 #include <errno.h> … … 70 74 /** Next element in the chain. */ 71 75 struct RTFILEAIOREQINTERNAL *pNext; 76 /** Previous element in the chain. */ 77 struct RTFILEAIOREQINTERNAL *pPrev; 78 /** Current state the request is in. */ 79 RTFILEAIOREQSTATE enmState; 72 80 /** Flag whether this is a flush request. */ 73 81 bool fFlush; … … 183 191 pReqHead = pReqHead->pNext; 184 192 185 /* Clear pointer to next element just for safety. */193 /* Clear pointer to next and previous element just for safety. */ 186 194 pCtxInt->apReqs[pCtxInt->iFirstFree]->pNext = NULL; 195 pCtxInt->apReqs[pCtxInt->iFirstFree]->pPrev = NULL; 187 196 pCtxInt->iFirstFree++; 188 197 Assert(pCtxInt->iFirstFree <= pCtxInt->cMaxRequests); … … 210 219 } 211 220 221 RTR3DECL(int) RTFileAioGetLimits(PRTFILEAIOLIMITS pAioLimits) 222 { 223 int rcBSD = 0; 224 AssertPtrReturn(pAioLimits, VERR_INVALID_POINTER); 225 226 #if defined(RT_OS_DARWIN) 227 int cReqsOutstandingMax = 0; 228 size_t cbParameter = sizeof(int); 229 230 rcBSD = sysctlbyname("kern.aioprocmax", /* name */ 231 &cReqsOutstandingMax, /* Where to store the old value. */ 232 &cbParameter, /* Size of the memory pointed to. */ 233 NULL, /* Where the new value is located. */ 234 NULL); /* Where the size of the new value is stored. */ 235 if (rcBSD == -1) 236 return RTErrConvertFromErrno(errno); 237 238 pAioLimits->cReqsOutstandingMax = cReqsOutstandingMax; 239 pAioLimits->cbBufferAlignment = 0; 240 #else 241 pAioLimits->cReqsOutstandingMax = RTFILEAIO_UNLIMITED_REQS; 242 pAioLimits->cbBufferAlignment = 0; 243 #endif 244 245 return VINF_SUCCESS; 246 } 247 212 248 RTR3DECL(int) RTFileAioReqCreate(PRTFILEAIOREQ phReq) 213 249 { … … 220 256 pReqInt->pCtxInt = NULL; 221 257 pReqInt->u32Magic = RTFILEAIOREQ_MAGIC; 258 RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); 222 259 223 260 *phReq = (RTFILEAIOREQ)pReqInt; … … 227 264 228 265 229 RTDECL( void) RTFileAioReqDestroy(RTFILEAIOREQ hReq)266 RTDECL(int) RTFileAioReqDestroy(RTFILEAIOREQ hReq) 230 267 { 231 268 /* … … 233 270 */ 234 271 if (hReq == NIL_RTFILEAIOREQ) 235 return ;272 return VINF_SUCCESS; 236 273 PRTFILEAIOREQINTERNAL pReqInt = hReq; 237 RTFILEAIOREQ_VALID_RETURN_VOID(pReqInt); 274 RTFILEAIOREQ_VALID_RETURN(pReqInt); 275 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); 238 276 239 277 /* … … 242 280 ASMAtomicUoWriteU32(&pReqInt->u32Magic, ~RTFILEAIOREQ_MAGIC); 243 281 RTMemFree(pReqInt); 282 return VINF_SUCCESS; 244 283 } 245 284 … … 257 296 PRTFILEAIOREQINTERNAL pReqInt = hReq; 258 297 RTFILEAIOREQ_VALID_RETURN(pReqInt); 298 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); 259 299 Assert(hFile != NIL_RTFILE); 260 300 AssertPtr(pvBuf); … … 271 311 pReqInt->pCtxInt = NULL; 272 312 pReqInt->Rc = VERR_FILE_AIO_IN_PROGRESS; 313 RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); 273 314 274 315 return VINF_SUCCESS; … … 297 338 298 339 RTFILEAIOREQ_VALID_RETURN(pReqInt); 340 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); 299 341 Assert(hFile != NIL_RTFILE); 300 342 … … 302 344 pReqInt->AioCB.aio_fildes = (int)hFile; 303 345 pReqInt->pvUser = pvUser; 346 RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); 304 347 305 348 return VINF_SUCCESS; … … 320 363 PRTFILEAIOREQINTERNAL pReqInt = hReq; 321 364 RTFILEAIOREQ_VALID_RETURN(pReqInt); 365 RTFILEAIOREQ_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_NOT_SUBMITTED); 322 366 323 367 ASMAtomicXchgBool(&pReqInt->fCanceled, true); … … 343 387 344 388 ASMAtomicWritePtr((void* volatile*)&pCtxInt->pReqToCancel, NULL); 389 pReqInt->Rc = VERR_FILE_AIO_CANCELED; 390 RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); 345 391 return VINF_SUCCESS; 346 392 } … … 358 404 PRTFILEAIOREQINTERNAL pReqInt = hReq; 359 405 RTFILEAIOREQ_VALID_RETURN(pReqInt); 406 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); 407 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, PREPARED, VERR_FILE_AIO_NOT_SUBMITTED); 360 408 AssertPtrNull(pcbTransfered); 361 409 362 if ( ( pReqInt->Rc != VERR_FILE_AIO_IN_PROGRESS)410 if ( (RT_SUCCESS(pReqInt->Rc)) 363 411 && (pcbTransfered)) 364 412 *pcbTransfered = pReqInt->cbTransfered; … … 425 473 } 426 474 427 RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs , size_t *pcReqs)475 RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs) 428 476 { 429 477 int rc = VINF_SUCCESS; … … 452 500 { 453 501 pReqInt = pahReqs[i]; 454 RTFILEAIOREQ_VALID_RETURN(pReqInt); 502 if (RTFILEAIOREQ_IS_NOT_VALID(pReqInt)) 503 { 504 /* Undo everything and stop submitting. */ 505 for (size_t iUndo = 0; iUndo < i; iUndo++) 506 { 507 pReqInt = pahReqs[iUndo]; 508 RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); 509 pReqInt->pCtxInt = NULL; 510 511 /* Unlink from the list again. */ 512 PRTFILEAIOREQINTERNAL pNext, pPrev; 513 pNext = pReqInt->pNext; 514 pPrev = pReqInt->pPrev; 515 if (pNext) 516 pNext->pPrev = pPrev; 517 if (pPrev) 518 pPrev->pNext = pNext; 519 else 520 pHead = pNext; 521 } 522 rc = VERR_INVALID_HANDLE; 523 break; 524 } 455 525 456 526 pReqInt->pCtxInt = pCtxInt; … … 458 528 /* Link them together. */ 459 529 pReqInt->pNext = pHead; 530 if (pHead) 531 pHead->pPrev = pReqInt; 532 pReqInt->pPrev = NULL; 460 533 pHead = pReqInt; 534 RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED); 461 535 462 536 if (pReqInt->fFlush) … … 472 546 if (RT_UNLIKELY(rcPosix < 0)) 473 547 { 474 rc = RTErrConvertFromErrno(errno); 548 if (rcPosix == EAGAIN) 549 rc = VERR_FILE_AIO_INSUFFICIENT_RESSOURCES; 550 else 551 rc = RTErrConvertFromErrno(errno); 552 553 /* Check which ones were not submitted. */ 554 for (i = 0; i < cReqs; i++) 555 { 556 pReqInt = pahReqs[i]; 557 rcPosix = aio_error(&pReqInt->AioCB); 558 if (rcPosix != EINPROGRESS) 559 { 560 if (rcPosix == EINVAL) 561 { 562 /* Was not submitted. */ 563 RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED); 564 } 565 else 566 { 567 /* An error occured. */ 568 RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); 569 pReqInt->Rc = RTErrConvertFromErrno(rcPosix); 570 pReqInt->cbTransfered = 0; 571 } 572 /* Unlink from the list. */ 573 PRTFILEAIOREQINTERNAL pNext, pPrev; 574 pNext = pReqInt->pNext; 575 pPrev = pReqInt->pPrev; 576 if (pNext) 577 pNext->pPrev = pPrev; 578 if (pPrev) 579 pPrev->pNext = pNext; 580 else 581 pHead = pNext; 582 } 583 } 584 475 585 break; 476 586 } … … 479 589 cReqs -= cReqsSubmit; 480 590 pahReqs += cReqsSubmit; 481 *pcReqs += cReqsSubmit;482 591 } 483 592 … … 488 597 RTFILEAIOREQ_VALID_RETURN(pReqInt); 489 598 490 if (pReqInt->fFlush) 599 Assert(pReqInt->fFlush); 600 601 /* 602 * lio_listio does not work with flush requests so 603 * we have to use aio_fsync directly. 604 */ 605 rcPosix = aio_fsync(O_SYNC, &pReqInt->AioCB); 606 if (RT_UNLIKELY(rcPosix < 0)) 491 607 { 492 /* 493 * lio_listio does not work with flush requests so 494 * we have to use aio_fsync directly. 495 */ 496 rcPosix = aio_fsync(O_SYNC, &pReqInt->AioCB); 497 if (RT_UNLIKELY(rcPosix < 0)) 498 { 499 rc = RTErrConvertFromErrno(errno); 500 break; 501 } 502 503 ASMAtomicIncS32(&pCtxInt->cRequests); 504 cReqs--; 505 pahReqs++; 506 *pcReqs++; 608 rc = RTErrConvertFromErrno(errno); 609 RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); 610 pReqInt->Rc = rc; 611 pReqInt->cbTransfered = 0; 612 613 /* Unlink from the list. */ 614 PRTFILEAIOREQINTERNAL pNext, pPrev; 615 pNext = pReqInt->pNext; 616 pPrev = pReqInt->pPrev; 617 if (pNext) 618 pNext->pPrev = pPrev; 619 if (pPrev) 620 pPrev->pNext = pNext; 621 else 622 pHead = pNext; 623 break; 507 624 } 625 626 ASMAtomicIncS32(&pCtxInt->cRequests); 627 cReqs--; 628 pahReqs++; 508 629 } 509 630 } while (cReqs); … … 625 746 pReq->Rc = RTErrConvertFromErrno(rcReq); 626 747 748 /* Mark the request as finished. */ 749 RTFILEAIOREQ_SET_STATE(pReq, COMPLETED); 627 750 cDone++; 628 751 -
trunk/src/VBox/Runtime/r3/win/fileaio-win.cpp
r19186 r19562 90 90 /** Overlapped structure. */ 91 91 OVERLAPPED Overlapped; 92 /** Current state the request is in. */ 93 RTFILEAIOREQSTATE enmState; 92 94 /** The file handle. */ 93 95 HANDLE hFile; … … 122 124 #define OVERLAPPED_2_RTFILEAIOREQINTERNAL(pOverlapped) ( (PRTFILEAIOREQINTERNAL)((uintptr_t)(pOverlapped) - RT_OFFSETOF(RTFILEAIOREQINTERNAL, Overlapped)) ) 123 125 126 RTR3DECL(int) RTFileAioGetLimits(PRTFILEAIOLIMITS pAioLimits) 127 { 128 int rcBSD = 0; 129 AssertPtrReturn(pAioLimits, VERR_INVALID_POINTER); 130 131 /* No limits known. */ 132 pAioLimits->cReqsOutstandingMax = RTFILEAIO_UNLIMITED_REQS; 133 pAioLimits->cbBufferAlignment = 0; 134 135 return VINF_SUCCESS; 136 } 137 124 138 RTR3DECL(int) RTFileAioReqCreate(PRTFILEAIOREQ phReq) 125 139 { … … 133 147 pReqInt->fCompleted = false; 134 148 pReqInt->u32Magic = RTFILEAIOREQ_MAGIC; 149 RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); 135 150 136 151 *phReq = (RTFILEAIOREQ)pReqInt; … … 139 154 } 140 155 141 RTDECL( void) RTFileAioReqDestroy(RTFILEAIOREQ hReq)156 RTDECL(int) RTFileAioReqDestroy(RTFILEAIOREQ hReq) 142 157 { 143 158 /* … … 145 160 */ 146 161 if (hReq == NIL_RTFILEAIOREQ) 147 return ;162 return VINF_SUCCESS; 148 163 PRTFILEAIOREQINTERNAL pReqInt = hReq; 149 RTFILEAIOREQ_VALID_RETURN_VOID(pReqInt); 164 RTFILEAIOREQ_VALID_RETURN(pReqInt); 165 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); 150 166 151 167 /* … … 154 170 ASMAtomicUoWriteU32(&pReqInt->u32Magic, ~RTFILEAIOREQ_MAGIC); 155 171 RTMemFree(pReqInt); 172 return VINF_SUCCESS; 156 173 } 157 174 … … 169 186 PRTFILEAIOREQINTERNAL pReqInt = hReq; 170 187 RTFILEAIOREQ_VALID_RETURN(pReqInt); 188 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); 171 189 Assert(hFile != NIL_RTFILE); 172 190 AssertPtr(pvBuf); … … 204 222 PRTFILEAIOREQINTERNAL pReqInt = hReq; 205 223 RTFILEAIOREQ_VALID_RETURN(pReqInt); 224 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); 206 225 AssertReturn(hFile != NIL_RTFILE, VERR_INVALID_HANDLE); 207 226 … … 226 245 PRTFILEAIOREQINTERNAL pReqInt = hReq; 227 246 RTFILEAIOREQ_VALID_RETURN(pReqInt); 247 RTFILEAIOREQ_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_NOT_SUBMITTED); 228 248 229 249 /** … … 234 254 * is only available from Vista and up. 235 255 * The solution is to return VERR_FILE_AIO_IN_PROGRESS 236 * if the request didn't completed yet .256 * if the request didn't completed yet (checked above). 237 257 * Shouldn't be a big issue because a request is normally 238 258 * only canceled if it exceeds a timeout which is quite huge. 239 259 */ 240 if (pReqInt->fCompleted) 241 return VERR_FILE_AIO_COMPLETED; 242 else 243 return VERR_FILE_AIO_IN_PROGRESS; 260 return VERR_FILE_AIO_COMPLETED; 244 261 } 245 262 … … 249 266 PRTFILEAIOREQINTERNAL pReqInt = hReq; 250 267 RTFILEAIOREQ_VALID_RETURN(pReqInt); 251 252 if (pReqInt->fCompleted) 253 { 254 rc = pReqInt->Rc; 255 if (*pcbTransfered) 256 *pcbTransfered = pReqInt->cbTransfered; 257 } 258 else 259 rc = VERR_FILE_AIO_IN_PROGRESS; 268 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS); 269 RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, PREPARED, VERR_FILE_AIO_NOT_SUBMITTED); 270 271 rc = pReqInt->Rc; 272 if (pcbTransfered && RT_SUCCESS(rc)) 273 *pcbTransfered = pReqInt->cbTransfered; 260 274 261 275 return rc; … … 325 339 } 326 340 327 RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs , size_t *pcReqs)341 RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs) 328 342 { 329 343 /* 330 344 * Parameter validation. 331 345 */ 332 AssertPtrReturn(pcReqs, VERR_INVALID_POINTER);333 *pcReqs = 0;334 346 int rc = VINF_SUCCESS; 335 347 PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; … … 361 373 if (RT_UNLIKELY(!fSucceeded && GetLastError() != ERROR_IO_PENDING)) 362 374 { 375 RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); 363 376 rc = RTErrConvertFromWin32(GetLastError()); 377 pReqInt->Rc = rc; 364 378 break; 365 379 } 380 RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED); 366 381 } 367 382 368 *pcReqs = i;369 383 ASMAtomicAddS32(&pCtxInt->cRequests, i); 370 384 … … 440 454 441 455 /* Mark the request as finished. */ 442 pReqInt->fCompleted = true;456 RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED); 443 457 444 458 /* completion status. */
Note:
See TracChangeset
for help on using the changeset viewer.