From e61ad3a9f37c158dd4103a94607516b0b30ee1a2 Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Thu, 12 Jul 2001 22:29:41 +0000 Subject: [PATCH] Implement overlapped completion routines. Don't use lpOverlapped->OffsetHigh to store bytes to transfer. --- dlls/kernel/comm.c | 2 ++ files/file.c | 20 ++++++++++---------- include/file.h | 2 ++ scheduler/synchro.c | 34 +++++++++++++++++++++++++--------- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/dlls/kernel/comm.c b/dlls/kernel/comm.c index 2cce7c757d7..850674be36c 100644 --- a/dlls/kernel/comm.c +++ b/dlls/kernel/comm.c @@ -2912,6 +2912,8 @@ static BOOL COMM_WaitCommEvent( ovp->func = COMM_WaitCommEventService; ovp->buffer = (char *)lpdwEvents; ovp->fd = fd; + ovp->count = 0; + ovp->completion_func = 0; ovp->next = NtCurrentTeb()->pending_list; ovp->prev = NULL; diff --git a/files/file.c b/files/file.c index e976bf3a478..addc7bb1cbc 100644 --- a/files/file.c +++ b/files/file.c @@ -1268,7 +1268,7 @@ static void FILE_AsyncReadService(async_private *ovp, int events) /* check to see if the data is ready (non-blocking) */ result = read(ovp->fd, &ovp->buffer[lpOverlapped->InternalHigh], - lpOverlapped->OffsetHigh - lpOverlapped->InternalHigh); + ovp->count - lpOverlapped->InternalHigh); if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR))) { @@ -1286,9 +1286,9 @@ static void FILE_AsyncReadService(async_private *ovp, int events) } lpOverlapped->InternalHigh += result; - TRACE("read %d more bytes %ld/%ld so far\n",result,lpOverlapped->InternalHigh,lpOverlapped->OffsetHigh); + TRACE("read %d more bytes %ld/%d so far\n",result,lpOverlapped->InternalHigh,ovp->count); - if(lpOverlapped->InternalHigh < lpOverlapped->OffsetHigh) + if(lpOverlapped->InternalHigh < ovp->count) r = STATUS_PENDING; else r = STATUS_SUCCESS; @@ -1334,8 +1334,6 @@ BOOL WINAPI ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, return FALSE; } - overlapped->Offset = 0; - overlapped->OffsetHigh = bytesToRead; /* FIXME: wrong */ overlapped->Internal = STATUS_PENDING; overlapped->InternalHigh = 0; @@ -1375,6 +1373,8 @@ BOOL WINAPI ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, return FALSE; } ovp->lpOverlapped = overlapped; + ovp->count = bytesToRead; + ovp->completion_func = lpCompletionRoutine; ovp->timeout = timeout; gettimeofday(&ovp->tv,NULL); add_timeout(&ovp->tv,timeout); @@ -1463,7 +1463,7 @@ static void FILE_AsyncWriteService(struct async_private *ovp, int events) /* write some data (non-blocking) */ result = write(ovp->fd, &ovp->buffer[lpOverlapped->InternalHigh], - lpOverlapped->OffsetHigh-lpOverlapped->InternalHigh); + ovp->count-lpOverlapped->InternalHigh); if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR))) { @@ -1480,9 +1480,9 @@ static void FILE_AsyncWriteService(struct async_private *ovp, int events) lpOverlapped->InternalHigh += result; - TRACE("wrote %d more bytes %ld/%ld so far\n",result,lpOverlapped->InternalHigh,lpOverlapped->OffsetHigh); + TRACE("wrote %d more bytes %ld/%d so far\n",result,lpOverlapped->InternalHigh,ovp->count); - if(lpOverlapped->InternalHigh < lpOverlapped->OffsetHigh) + if(lpOverlapped->InternalHigh < ovp->count) r = STATUS_PENDING; else r = STATUS_SUCCESS; @@ -1510,8 +1510,6 @@ BOOL WINAPI WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite, return FALSE; } - overlapped->Offset = 0; - overlapped->OffsetHigh = bytesToWrite; overlapped->Internal = STATUS_PENDING; overlapped->InternalHigh = 0; @@ -1545,6 +1543,8 @@ BOOL WINAPI WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite, ovp->event = POLLOUT; ovp->func = FILE_AsyncWriteService; ovp->buffer = (LPVOID) buffer; + ovp->count = bytesToWrite; + ovp->completion_func = lpCompletionRoutine; ovp->fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE ); if(ovp->fd <0) { diff --git a/include/file.h b/include/file.h index 2093d0e45ed..b661faf3bc7 100644 --- a/include/file.h +++ b/include/file.h @@ -43,6 +43,8 @@ typedef struct async_private int event; char *buffer; async_handler func; + int count; + LPOVERLAPPED_COMPLETION_ROUTINE completion_func; struct async_private *next; struct async_private *prev; } async_private; diff --git a/scheduler/synchro.c b/scheduler/synchro.c index f0e755d46b8..1f6ab934d44 100644 --- a/scheduler/synchro.c +++ b/scheduler/synchro.c @@ -44,8 +44,27 @@ static inline int time_before( struct timeval *t1, struct timeval *t2 ) ((t1->tv_sec == t2->tv_sec) && (t1->tv_usec < t2->tv_usec))); } -static void finish_async(async_private *ovp) +static void CALLBACK call_completion_routine(ULONG_PTR data) { + async_private* ovp = (async_private*)data; + + ovp->completion_func(ovp->lpOverlapped->Internal, + ovp->lpOverlapped->InternalHigh, + ovp->lpOverlapped); + ovp->completion_func=NULL; + HeapFree(GetProcessHeap(), 0, ovp); +} + +static void finish_async(async_private *ovp, DWORD status) +{ + ovp->lpOverlapped->Internal=status; + + /* call ReadFileEx/WriteFileEx's overlapped completion function */ + if(ovp->completion_func) + { + QueueUserAPC(call_completion_routine,GetCurrentThread(),(ULONG_PTR)ovp); + } + /* remove it from the active list */ if(ovp->prev) ovp->prev->next = ovp->next; @@ -60,7 +79,7 @@ static void finish_async(async_private *ovp) close(ovp->fd); NtSetEvent(ovp->lpOverlapped->hEvent,NULL); - HeapFree(GetProcessHeap(), 0, ovp); + if(!ovp->completion_func) HeapFree(GetProcessHeap(), 0, ovp); } /*********************************************************************** @@ -96,15 +115,13 @@ static void check_async_list(void) if(ovp->lpOverlapped->Internal!=STATUS_PENDING) { - ovp->lpOverlapped->Internal=STATUS_UNSUCCESSFUL; - finish_async(ovp); + finish_async(ovp,STATUS_UNSUCCESSFUL); continue; } if(ovp->timeout && time_before(&ovp->tv,&now)) { - ovp->lpOverlapped->Internal=STATUS_TIMEOUT; - finish_async(ovp); + finish_async(ovp,STATUS_TIMEOUT); continue; } @@ -135,8 +152,7 @@ static void check_async_list(void) if( r==0 ) { - timeout_user->lpOverlapped->Internal = STATUS_TIMEOUT; - finish_async(timeout_user); + finish_async(timeout_user, STATUS_TIMEOUT); continue; } @@ -147,7 +163,7 @@ static void check_async_list(void) user[i]->func(user[i],fds[i].revents); if(user[i]->lpOverlapped->Internal!=STATUS_PENDING) - finish_async(user[i]); + finish_async(user[i],user[i]->lpOverlapped->Internal); } if(fds[0].revents == POLLIN)