Changeset 19126 in vbox for trunk/src/VBox/Runtime/r3/linux
- Timestamp:
- Apr 22, 2009 10:52:02 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/linux/fileaio-linux.cpp
r19054 r19126 61 61 #include <iprt/log.h> 62 62 #include <iprt/thread.h> 63 #include "internal/ magics.h"63 #include "internal/fileaio.h" 64 64 65 65 #include <linux/aio_abi.h> … … 159 159 160 160 /** 161 * Async I/O request state.162 */163 typedef struct RTFILEAIOREQINTERNAL164 {165 /** The aio control block. This must be the FIRST elment in166 * the structure! (see notes below) */167 LNXKAIOIOCB AioCB;168 /** The I/O context this request is associated with. */169 aio_context_t AioContext;170 /** Return code the request completed with. */171 int Rc;172 /** Flag whether the request is in process or not. */173 bool fFinished;174 /** Number of bytes actually trasnfered. */175 size_t cbTransfered;176 /** Magic value (RTFILEAIOREQ_MAGIC). */177 uint32_t u32Magic;178 } RTFILEAIOREQINTERNAL;179 /** Pointer to an internal request structure. */180 typedef RTFILEAIOREQINTERNAL *PRTFILEAIOREQINTERNAL;181 182 /**183 161 * Async I/O completion context state. 184 162 */ … … 203 181 typedef RTFILEAIOCTXINTERNAL *PRTFILEAIOCTXINTERNAL; 204 182 183 /** 184 * Async I/O request state. 185 */ 186 typedef struct RTFILEAIOREQINTERNAL 187 { 188 /** The aio control block. This must be the FIRST elment in 189 * the structure! (see notes below) */ 190 LNXKAIOIOCB AioCB; 191 /** The I/O context this request is associated with. */ 192 aio_context_t AioContext; 193 /** Return code the request completed with. */ 194 int Rc; 195 /** Flag whether the request is in process or not. */ 196 bool fFinished; 197 /** Number of bytes actually trasnfered. */ 198 size_t cbTransfered; 199 /** Completion context we are assigned to. */ 200 PRTFILEAIOCTXINTERNAL pCtxInt; 201 /** Magic value (RTFILEAIOREQ_MAGIC). */ 202 uint32_t u32Magic; 203 } RTFILEAIOREQINTERNAL; 204 /** Pointer to an internal request structure. */ 205 typedef RTFILEAIOREQINTERNAL *PRTFILEAIOREQINTERNAL; 206 205 207 206 208 /******************************************************************************* … … 210 212 #define AIO_MAXIMUM_REQUESTS_PER_CONTEXT 64 211 213 212 /** Validates a context handle and returns VERR_INVALID_HANDLE if not valid. */213 #define RTFILEAIOREQ_VALID_RETURN_RC(pReq, rc) \214 do { \215 AssertPtrReturn((pReq), (rc)); \216 AssertReturn((pReq)->u32Magic == RTFILEAIOREQ_MAGIC, (rc)); \217 } while (0)218 219 /** Validates a context handle and returns VERR_INVALID_HANDLE if not valid. */220 #define RTFILEAIOREQ_VALID_RETURN(pReq) RTFILEAIOREQ_VALID_RETURN_RC((pReq), VERR_INVALID_HANDLE)221 222 /** Validates a context handle and returns (void) if not valid. */223 #define RTFILEAIOREQ_VALID_RETURN_VOID(pReq) \224 do { \225 AssertPtrReturnVoid(pReq); \226 AssertReturnVoid((pReq)->u32Magic == RTFILEAIOREQ_MAGIC); \227 } while (0)228 229 /** Validates a context handle and returns the specified rc if not valid. */230 #define RTFILEAIOCTX_VALID_RETURN_RC(pCtx, rc) \231 do { \232 AssertPtrReturn((pCtx), (rc)); \233 AssertReturn((pCtx)->u32Magic == RTFILEAIOCTX_MAGIC, (rc)); \234 } while (0)235 236 /** Validates a context handle and returns VERR_INVALID_HANDLE if not valid. */237 #define RTFILEAIOCTX_VALID_RETURN(pCtx) RTFILEAIOCTX_VALID_RETURN_RC((pCtx), VERR_INVALID_HANDLE)238 239 214 240 215 /** … … 300 275 } 301 276 302 303 277 RTR3DECL(int) RTFileAioReqCreate(PRTFILEAIOREQ phReq) 304 278 { … … 313 287 314 288 pReqInt->fFinished = false; 315 pReqInt->u32Magic = RTFILEAIOREQ_MAGIC; 289 pReqInt->pCtxInt = NULL; 290 pReqInt->u32Magic = RTFILEAIOREQ_MAGIC; 316 291 317 292 *phReq = (RTFILEAIOREQ)pReqInt; … … 367 342 368 343 pReqInt->fFinished = false; 344 pReqInt->pCtxInt = NULL; 369 345 370 346 return VINF_SUCCESS; … … 425 401 if (RT_SUCCESS(rc)) 426 402 { 427 /* Examine rc in the event structure. */ 403 /* 404 * Decrement request count because the request will never arrive at the 405 * completion port. 406 */ 407 AssertMsg(VALID_PTR(pReqInt->pCtxInt), 408 ("Invalid state. Request was canceled but wasn't submitted\n")); 409 410 ASMAtomicDecS32(&pReqInt->pCtxInt->cRequests); 428 411 return VINF_SUCCESS; 429 412 } … … 528 511 AssertPtrReturn(pahReqs, VERR_INVALID_POINTER); 529 512 uint32_t i = cReqs; 513 514 /* 515 * Vaildate requests and associate with the context. 516 */ 530 517 while (i-- > 0) 531 518 { 532 519 PRTFILEAIOREQINTERNAL pReqInt = pahReqs[i]; 533 520 RTFILEAIOREQ_VALID_RETURN(pReqInt); 521 522 pReqInt->AioContext = pCtxInt->AioContext; 523 pReqInt->pCtxInt = pCtxInt; 534 524 } 535 525 536 526 /* 537 * Add descriptive comment.538 * /539 /** @todo r=bird: Why this particular order?540 * Perhaps combine the AioContext initialization with the validation? */527 * Add the submitted requests to the counter 528 * to prevent destroying the context while 529 * it is still used. 530 */ 541 531 ASMAtomicAddS32(&pCtxInt->cRequests, cReqs); 542 543 for (unsigned i = 0; i < cReqs; i++)544 {545 PRTFILEAIOREQINTERNAL pReqInt = pahReqs[i];546 pReqInt->AioContext = pCtxInt->AioContext;547 }548 532 549 533 /* … … 600 584 /* For the wakeup call. */ 601 585 Assert(pCtxInt->hThreadWait == NIL_RTTHREAD); 602 pCtxInt->hThreadWait = RTThreadSelf();586 ASMAtomicWriteHandle(&pCtxInt->hThreadWait, RTThreadSelf()); 603 587 604 588 /* … … 683 667 ASMAtomicSubS32(&pCtxInt->cRequests, cRequestsCompleted); 684 668 Assert(pCtxInt->hThreadWait == RTThreadSelf()); 685 pCtxInt->hThreadWait = NIL_RTTHREAD;669 ASMAtomicWriteHandle(&pCtxInt->hThreadWait, NIL_RTTHREAD); 686 670 687 671 /* … … 707 691 * this function. */ 708 692 709 bool fWokenUp = ASMAtomicXchgBool(&pCtxInt->fWokenUp, true); 693 bool fWokenUp = ASMAtomicXchgBool(&pCtxInt->fWokenUp, true); 694 695 /* 696 * Read the thread handle before the status flag. 697 * If we read the handle after the flag we might 698 * end up with an invalid handle because the thread 699 * waiting in RTFileAioCtxWakeup() might get scheduled 700 * before we read the flag and returns. 701 * We can ensure that the handle is valid if fWaiting is true 702 * when reading the handle before the status flag. 703 */ 704 RTTHREAD hThread; 705 ASMAtomicReadHandle(&pCtxInt->hThreadWait, &hThread); 706 bool fWaiting = ASMAtomicReadBool(&pCtxInt->fWaiting); 710 707 if ( !fWokenUp 711 && pCtxInt->fWaiting) 712 RTThreadPoke(pCtxInt->hThreadWait); 708 && fWaiting) 709 { 710 /* 711 * If a thread waits the handle must be valid. 712 * It is possible that the thread returns from 713 * rtFileAsyncIoLinuxGetEvents() before the signal 714 * is send. 715 * This is no problem because we already set fWokenUp 716 * to true which will let the thread return VERR_INTERRUPTED 717 * and the next call to RTFileAioCtxWait() will not 718 * return VERR_INTERRUPTED because signals are not saved 719 * and will simply vanish if the destination thread can't 720 * receive it. 721 */ 722 Assert(hThread != NIL_RTTHREAD); 723 RTThreadPoke(hThread); 724 } 713 725 714 726 return VINF_SUCCESS;
Note:
See TracChangeset
for help on using the changeset viewer.