Implement overlapped completion routines.
Don't use lpOverlapped->OffsetHigh to store bytes to transfer.
This commit is contained in:
parent
1fc39be64f
commit
e61ad3a9f3
|
@ -2912,6 +2912,8 @@ static BOOL COMM_WaitCommEvent(
|
||||||
ovp->func = COMM_WaitCommEventService;
|
ovp->func = COMM_WaitCommEventService;
|
||||||
ovp->buffer = (char *)lpdwEvents;
|
ovp->buffer = (char *)lpdwEvents;
|
||||||
ovp->fd = fd;
|
ovp->fd = fd;
|
||||||
|
ovp->count = 0;
|
||||||
|
ovp->completion_func = 0;
|
||||||
|
|
||||||
ovp->next = NtCurrentTeb()->pending_list;
|
ovp->next = NtCurrentTeb()->pending_list;
|
||||||
ovp->prev = NULL;
|
ovp->prev = NULL;
|
||||||
|
|
20
files/file.c
20
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) */
|
/* check to see if the data is ready (non-blocking) */
|
||||||
result = read(ovp->fd, &ovp->buffer[lpOverlapped->InternalHigh],
|
result = read(ovp->fd, &ovp->buffer[lpOverlapped->InternalHigh],
|
||||||
lpOverlapped->OffsetHigh - lpOverlapped->InternalHigh);
|
ovp->count - lpOverlapped->InternalHigh);
|
||||||
|
|
||||||
if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR)))
|
if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR)))
|
||||||
{
|
{
|
||||||
|
@ -1286,9 +1286,9 @@ static void FILE_AsyncReadService(async_private *ovp, int events)
|
||||||
}
|
}
|
||||||
|
|
||||||
lpOverlapped->InternalHigh += result;
|
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;
|
r = STATUS_PENDING;
|
||||||
else
|
else
|
||||||
r = STATUS_SUCCESS;
|
r = STATUS_SUCCESS;
|
||||||
|
@ -1334,8 +1334,6 @@ BOOL WINAPI ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
overlapped->Offset = 0;
|
|
||||||
overlapped->OffsetHigh = bytesToRead; /* FIXME: wrong */
|
|
||||||
overlapped->Internal = STATUS_PENDING;
|
overlapped->Internal = STATUS_PENDING;
|
||||||
overlapped->InternalHigh = 0;
|
overlapped->InternalHigh = 0;
|
||||||
|
|
||||||
|
@ -1375,6 +1373,8 @@ BOOL WINAPI ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
ovp->lpOverlapped = overlapped;
|
ovp->lpOverlapped = overlapped;
|
||||||
|
ovp->count = bytesToRead;
|
||||||
|
ovp->completion_func = lpCompletionRoutine;
|
||||||
ovp->timeout = timeout;
|
ovp->timeout = timeout;
|
||||||
gettimeofday(&ovp->tv,NULL);
|
gettimeofday(&ovp->tv,NULL);
|
||||||
add_timeout(&ovp->tv,timeout);
|
add_timeout(&ovp->tv,timeout);
|
||||||
|
@ -1463,7 +1463,7 @@ static void FILE_AsyncWriteService(struct async_private *ovp, int events)
|
||||||
|
|
||||||
/* write some data (non-blocking) */
|
/* write some data (non-blocking) */
|
||||||
result = write(ovp->fd, &ovp->buffer[lpOverlapped->InternalHigh],
|
result = write(ovp->fd, &ovp->buffer[lpOverlapped->InternalHigh],
|
||||||
lpOverlapped->OffsetHigh-lpOverlapped->InternalHigh);
|
ovp->count-lpOverlapped->InternalHigh);
|
||||||
|
|
||||||
if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR)))
|
if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR)))
|
||||||
{
|
{
|
||||||
|
@ -1480,9 +1480,9 @@ static void FILE_AsyncWriteService(struct async_private *ovp, int events)
|
||||||
|
|
||||||
lpOverlapped->InternalHigh += result;
|
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;
|
r = STATUS_PENDING;
|
||||||
else
|
else
|
||||||
r = STATUS_SUCCESS;
|
r = STATUS_SUCCESS;
|
||||||
|
@ -1510,8 +1510,6 @@ BOOL WINAPI WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
overlapped->Offset = 0;
|
|
||||||
overlapped->OffsetHigh = bytesToWrite;
|
|
||||||
overlapped->Internal = STATUS_PENDING;
|
overlapped->Internal = STATUS_PENDING;
|
||||||
overlapped->InternalHigh = 0;
|
overlapped->InternalHigh = 0;
|
||||||
|
|
||||||
|
@ -1545,6 +1543,8 @@ BOOL WINAPI WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
|
||||||
ovp->event = POLLOUT;
|
ovp->event = POLLOUT;
|
||||||
ovp->func = FILE_AsyncWriteService;
|
ovp->func = FILE_AsyncWriteService;
|
||||||
ovp->buffer = (LPVOID) buffer;
|
ovp->buffer = (LPVOID) buffer;
|
||||||
|
ovp->count = bytesToWrite;
|
||||||
|
ovp->completion_func = lpCompletionRoutine;
|
||||||
ovp->fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
|
ovp->fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
|
||||||
if(ovp->fd <0)
|
if(ovp->fd <0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,6 +43,8 @@ typedef struct async_private
|
||||||
int event;
|
int event;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
async_handler func;
|
async_handler func;
|
||||||
|
int count;
|
||||||
|
LPOVERLAPPED_COMPLETION_ROUTINE completion_func;
|
||||||
struct async_private *next;
|
struct async_private *next;
|
||||||
struct async_private *prev;
|
struct async_private *prev;
|
||||||
} async_private;
|
} async_private;
|
||||||
|
|
|
@ -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)));
|
((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 */
|
/* remove it from the active list */
|
||||||
if(ovp->prev)
|
if(ovp->prev)
|
||||||
ovp->prev->next = ovp->next;
|
ovp->prev->next = ovp->next;
|
||||||
|
@ -60,7 +79,7 @@ static void finish_async(async_private *ovp)
|
||||||
|
|
||||||
close(ovp->fd);
|
close(ovp->fd);
|
||||||
NtSetEvent(ovp->lpOverlapped->hEvent,NULL);
|
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)
|
if(ovp->lpOverlapped->Internal!=STATUS_PENDING)
|
||||||
{
|
{
|
||||||
ovp->lpOverlapped->Internal=STATUS_UNSUCCESSFUL;
|
finish_async(ovp,STATUS_UNSUCCESSFUL);
|
||||||
finish_async(ovp);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ovp->timeout && time_before(&ovp->tv,&now))
|
if(ovp->timeout && time_before(&ovp->tv,&now))
|
||||||
{
|
{
|
||||||
ovp->lpOverlapped->Internal=STATUS_TIMEOUT;
|
finish_async(ovp,STATUS_TIMEOUT);
|
||||||
finish_async(ovp);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,8 +152,7 @@ static void check_async_list(void)
|
||||||
|
|
||||||
if( r==0 )
|
if( r==0 )
|
||||||
{
|
{
|
||||||
timeout_user->lpOverlapped->Internal = STATUS_TIMEOUT;
|
finish_async(timeout_user, STATUS_TIMEOUT);
|
||||||
finish_async(timeout_user);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +163,7 @@ static void check_async_list(void)
|
||||||
user[i]->func(user[i],fds[i].revents);
|
user[i]->func(user[i],fds[i].revents);
|
||||||
|
|
||||||
if(user[i]->lpOverlapped->Internal!=STATUS_PENDING)
|
if(user[i]->lpOverlapped->Internal!=STATUS_PENDING)
|
||||||
finish_async(user[i]);
|
finish_async(user[i],user[i]->lpOverlapped->Internal);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fds[0].revents == POLLIN)
|
if(fds[0].revents == POLLIN)
|
||||||
|
|
Loading…
Reference in New Issue