--- IOCompletionQ.cpp Fri Feb 13 20:49:41 2004 +++ IOCompletionQ.cpp.mod Fri Feb 13 20:49:22 2004 @@ -52,7 +52,12 @@ /* ## ## */ /* ## ------------------------------------------------------------------- ## */ /* ## ## */ -/* ## Changes ...: 2003-10-15 (daniel.scheibli@edelbyte.org) ## */ +/* ## Changes ...: 2004-02-12 (daniel.scheibli@edelbyte.org) ## */ +/* ## - Modified the GetQueuedCompletionStatus() function ## */ +/* ## according to the proposed code by Doug Haigh. This ## */ +/* ## ensures, that even in the case of an error, the ## */ +/* ## completion_key is set. ## */ +/* ## 2003-10-15 (daniel.scheibli@edelbyte.org) ## */ /* ## - Moved to the use of the IOMTR_[OSFAMILY|OS|CPU]_* ## */ /* ## global defines. ## */ /* ## - Integrated the License Statement into this header. ## */ @@ -206,11 +211,11 @@ BOOL GetQueuedCompletionStatus(HANDLE cq, LPDWORD bytes_transferred, LPDWORD completion_key, LPOVERLAPPED *lpOverlapped, DWORD tmout) { - struct timespec *timeoutp; - struct timespec timeout; - struct IOCQ *cqid; - int i, j; - int aio_error_return; + struct timespec *timeoutp; + struct timespec timeout; + struct IOCQ *cqid; + int i, j; + int aio_error_return; cqid = (struct IOCQ *)cq; @@ -241,40 +246,58 @@ // Network AIOs can be speeded up a bit by having an initial tagging loop that // will tag and break when an AIO completion is detected. // - // // IO Return Loop - return one AIO completion. + i = cqid->position; - for (j = 0; j < cqid->size; j++) - { - if (i == cqid->size) + + for( j = 0; j < cqid->size; j++ ) { + + if( i == cqid->size ) { i = 0; + } + + if( cqid->element_list[i].done == TRUE ) { - if (cqid->element_list[i].done == TRUE) - { // IO operation completed with either success or failure. + + *completion_key = cqid->element_list[i].completion_key; + + // Always set completion key + + *lpOverlapped = (LPOVERLAPPED)cqid->element_list[i].data; + + // Always set overlap data + cqid->element_list[i].done = FALSE; - cqid->last_freed = i; - cqid->position = i+1; - *bytes_transferred = cqid->element_list[i].bytes_transferred; - // We are returning the status of this aio. Set it to NULL to - // free the slot. + cqid->last_freed = i; + cqid->position = i + 1; + *bytes_transferred = cqid->element_list[i].bytes_transferred; + + // We are returning the status of this aio. Set it to NULL to free the slot. + cqid->aiocb_list[i] = 0; - if ((long )*bytes_transferred < 0) - { + + if( (long )*bytes_transferred < 0 ) { *bytes_transferred = 0; - *completion_key = 0; - if (cqid->element_list[i].error) - SetLastError(cqid->element_list[i].error); - return(FALSE); + // TODO: Here - and in the other locations where SetLastError() + // is called in this method - we have the problem, that it is + // set to + // a.) defines defined by us - like WAIT_TIMEOUT + // b.) whatever is in the errno variable + // We can not realy be shure what each one is and if there is + // maybe an overlaps, so we have to consolidate that in some + // way. + // As this method is called by CQAIO::GetStatus() (only?), we + // have to considere changes there as well. + SetLastError( cqid->element_list[i].error ); + return( FALSE ); } - else - { - *completion_key = cqid->element_list[i].completion_key; - *lpOverlapped = (LPOVERLAPPED)cqid->element_list[i].data; - return(TRUE); + else { + return( TRUE ); } } + i++; } // end of IO Return loop. @@ -292,33 +315,30 @@ timeoutp = &timeout; } - if (aio_suspend64(cqid->aiocb_list, cqid->size, timeoutp) < 0) + if( aio_suspend64( cqid->aiocb_list, cqid->size, timeoutp ) < 0 ) { - *lpOverlapped = NULL; + *lpOverlapped = NULL; *bytes_transferred = 0; - *completion_key = 0; + *completion_key = 0; if ( (errno == EAGAIN) || (errno == EINVAL) ) { #if defined(IOMTR_OS_LINUX) assert(errno == EAGAIN); #endif - SetLastError(WAIT_TIMEOUT); + SetLastError( WAIT_TIMEOUT ); } else { - SetLastError(errno); + SetLastError( errno ); } return(FALSE); } // Tagging loop - to tag completed AIOs. - for (j = 0; j < cqid->size; j++) - { + for( j = 0; j < cqid->size; j++ ) { errno = 0; - if (cqid->aiocb_list[j]) - { - if ((aio_error_return = aio_error64(cqid->aiocb_list[j])) != EINPROGRESS) - { + if( cqid->aiocb_list[j] ) { + if( ( aio_error_return = aio_error64( cqid->aiocb_list[j] ) ) != EINPROGRESS ) { cqid->element_list[j].bytes_transferred = - aio_return64(cqid->aiocb_list[j]); + aio_return64( cqid->aiocb_list[j] ); // // We have done an aio_return() on this element. Anull it. // The slot will be picked up by the next request.