The patch below implements my ideas from the
"struct async_private needs generalization for Winsock"
thread.
It's a patch against CVS 2002-01-08.
The Winsock stuff is still missing, that's the next step.
This is only a trivial recoding of the File IO (compiles, successfully
tested with my async file IO test code), whith the
"generic" fields in async_private and the "fileio-specific" fields
in the rest of the async_fileio structure.
Note: Since it seems agreeable to use the lpOverlapped in Winsock
the same way as for file IO, I made lpOverlapped a "generic" field.
Mike (or other people interested), if you can test this against your
serial port code I'd be grateful.
Martin
Patch file: async_private.diff
Purpose: New winsock-friendly async_private implementation
Created: 2002-01-08
Applies: CVS 2002-01-08
ChangeLog:
wine/include/file.h:
struct async_private:
- remove buffer, count, completion_func fields.
- add call_completion field (callback function
that calls the completion function).
struct async_fileio:
- "Derived" from async_private, contains.
remove buffer, count, completion_func fields.
wine/scheduler/synchro.c:
call_completion_routine(): function removed.
finish_async(): use ovp->completion_func instead of
call_completion_routine.
check_async_list(): Initialize ovp.
wine/files/file.c:
fileio_call_completion_func(): New function, FileIO-specific callback.
FILE_AsyncReadService():
- use struct async_fileio for specific fields.
FILE_AsyncWriteService():
- dito.
FILE_ReadFileEx():
- use async_fileio struct for overlapped initialization.
- initialize ovp->call_completion field.
FILE_WriteFileEx():
- dito.
dlls/kernel/comm.c:
COMM_WaitCommEventService():
- use struct async_fileio for "buffer" field.
COMM_WaitCommEvent():
- see FILE_ReadFileEx().
Martin Wilck <Martin.Wilck(a)Fujitsu-Siemens.com>
diff -ruX diffignore CVS/wine/dlls/kernel/comm.c MW/wine/dlls/kernel/comm.c
--- CVS/wine/dlls/kernel/comm.c Tue Jan 8 17:43:25 2002
+++ MW/wine/dlls/kernel/comm.c Tue Jan 8 17:47:41 2002
@@ -1515,11 +1515,12 @@
static void COMM_WaitCommEventService(async_private *ovp)
{
LPOVERLAPPED lpOverlapped = ovp->lpOverlapped;
+ async_fileio *fileio = (async_fileio*) ovp;
TRACE("overlapped %p\n",lpOverlapped);
/* FIXME: detect other events */
- *ovp->buffer = EV_RXCHAR;
+ *fileio->buffer = EV_RXCHAR;
lpOverlapped->Internal = STATUS_SUCCESS;
}
@@ -1536,7 +1537,7 @@
LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
{
int fd,ret;
- async_private *ovp;
+ async_fileio *ovp;
if(!lpOverlapped)
{
@@ -1556,26 +1557,27 @@
if(fd<0)
return FALSE;
- ovp = (async_private *) HeapAlloc(GetProcessHeap(), 0, sizeof (async_private));
+ ovp = (async_fileio *) HeapAlloc(GetProcessHeap(), 0, sizeof (async_fileio));
if(!ovp)
{
close(fd);
return FALSE;
}
- ovp->lpOverlapped = lpOverlapped;
- ovp->func = COMM_WaitCommEventService;
+ ovp->async.handle = hFile;
+ ovp->async.fd = fd;
+ ovp->async.type = ASYNC_TYPE_WAIT;
+ ovp->async.lpOverlapped = lpOverlapped;
+ ovp->async.func = COMM_WaitCommEventService;
+ ovp->async.call_completion = NULL;
ovp->buffer = (char *)lpdwEvents;
- ovp->fd = fd;
ovp->count = 0;
ovp->completion_func = 0;
- ovp->type = ASYNC_TYPE_WAIT;
- ovp->handle = hFile;
- ovp->next = NtCurrentTeb()->pending_list;
- ovp->prev = NULL;
- if(ovp->next)
- ovp->next->prev=ovp;
- NtCurrentTeb()->pending_list = ovp;
+ ovp->async.next = NtCurrentTeb()->pending_list;
+ ovp->async.prev = NULL;
+ if(ovp->async.next)
+ ovp->async.next->prev=&ovp->async;
+ NtCurrentTeb()->pending_list = &ovp->async;
/* start an ASYNCHRONOUS WaitCommEvent */
SERVER_START_REQ( register_async )
diff -ruX diffignore CVS/wine/files/file.c MW/wine/files/file.c
--- CVS/wine/files/file.c Tue Jan 8 17:43:51 2002
+++ MW/wine/files/file.c Tue Jan 8 17:47:41 2002
@@ -1298,6 +1298,21 @@
}
/***********************************************************************
+ * fileio_call_completion_func (INTERNAL)
+ */
+void CALLBACK fileio_call_completion_func (ULONG_PTR data)
+{
+ async_fileio *ovp = (async_fileio*) data;
+ TRACE ("data: %p\n", ovp);
+
+ ovp->completion_func(ovp->async.lpOverlapped->Internal,
+ ovp->async.lpOverlapped->InternalHigh,
+ ovp->async.lpOverlapped);
+ ovp->completion_func=NULL;
+ HeapFree(GetProcessHeap(), 0, ovp);
+}
+
+/***********************************************************************
* FILE_AsyncReadService (INTERNAL)
*
* This function is called while the client is waiting on the
@@ -1305,18 +1320,19 @@
*/
static void FILE_AsyncReadService(async_private *ovp)
{
+ async_fileio *fileio = (async_fileio*) ovp;
LPOVERLAPPED lpOverlapped = ovp->lpOverlapped;
int result, r;
int already = lpOverlapped->InternalHigh;
- TRACE("%p %p\n", lpOverlapped, ovp->buffer );
+ TRACE("%p %p\n", lpOverlapped, fileio->buffer );
/* check to see if the data is ready (non-blocking) */
- result = pread (ovp->fd, &ovp->buffer[already], ovp->count - already,
+ result = pread (ovp->fd, &fileio->buffer[already], fileio->count - already,
OVERLAPPED_OFFSET (lpOverlapped) + already);
if ((result < 0) && (errno == ESPIPE))
- result = read (ovp->fd, &ovp->buffer[already], ovp->count - already);
+ result = read (ovp->fd, &fileio->buffer[already], fileio->count - already);
if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR)))
{
@@ -1336,7 +1352,7 @@
lpOverlapped->InternalHigh += result;
TRACE("read %d more bytes %ld/%d so far\n",result,lpOverlapped->InternalHigh,ovp->count);
- if(lpOverlapped->InternalHigh < ovp->count)
+ if(lpOverlapped->InternalHigh < fileio->count)
r = STATUS_PENDING;
else
r = STATUS_SUCCESS;
@@ -1352,7 +1368,7 @@
LPOVERLAPPED overlapped,
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
- async_private *ovp;
+ async_fileio *ovp;
int fd;
TRACE("file %d to buf %p num %ld %p func %p\n",
@@ -1372,7 +1388,7 @@
return FALSE;
}
- ovp = (async_private *) HeapAlloc(GetProcessHeap(), 0, sizeof (async_private));
+ ovp = (async_fileio *) HeapAlloc(GetProcessHeap(), 0, sizeof (async_fileio));
if(!ovp)
{
TRACE("HeapAlloc Failed\n");
@@ -1380,21 +1396,23 @@
close(fd);
return FALSE;
}
- ovp->lpOverlapped = overlapped;
- ovp->count = bytesToRead;
+
+ ovp->async.handle = hFile;
+ ovp->async.fd = fd;
+ ovp->async.type = ASYNC_TYPE_READ;
+ ovp->async.lpOverlapped = overlapped;
+ ovp->async.func = FILE_AsyncReadService;
+ ovp->async.call_completion = (lpCompletionRoutine ? fileio_call_completion_func : NULL);
ovp->completion_func = lpCompletionRoutine;
- ovp->func = FILE_AsyncReadService;
ovp->buffer = buffer;
- ovp->fd = fd;
- ovp->type = ASYNC_TYPE_READ;
- ovp->handle = hFile;
+ ovp->count = bytesToRead;
/* hook this overlap into the pending async operation list */
- ovp->next = NtCurrentTeb()->pending_list;
- ovp->prev = NULL;
- if(ovp->next)
- ovp->next->prev = ovp;
- NtCurrentTeb()->pending_list = ovp;
+ ovp->async.next = NtCurrentTeb()->pending_list;
+ ovp->async.prev = NULL;
+ if(ovp->async.next)
+ ovp->async.next->prev = &ovp->async;
+ NtCurrentTeb()->pending_list = &ovp->async;
if ( !FILE_StartAsync(hFile, overlapped, ASYNC_TYPE_READ, bytesToRead, STATUS_PENDING) )
{
@@ -1550,18 +1568,19 @@
*/
static void FILE_AsyncWriteService(struct async_private *ovp)
{
+ async_fileio *fileio = (async_fileio *) ovp;
LPOVERLAPPED lpOverlapped = ovp->lpOverlapped;
int result, r;
int already = lpOverlapped->InternalHigh;
- TRACE("(%p %p)\n",lpOverlapped,ovp->buffer);
+ TRACE("(%p %p)\n",lpOverlapped,fileio->buffer);
/* write some data (non-blocking) */
- result = pwrite(ovp->fd, &ovp->buffer[already], ovp->count - already,
+ result = pwrite(ovp->fd, &fileio->buffer[already], fileio->count - already,
OVERLAPPED_OFFSET (lpOverlapped) + already);
if ((result < 0) && (errno == ESPIPE))
- result = write(ovp->fd, &ovp->buffer[already], ovp->count - already);
+ result = write(ovp->fd, &fileio->buffer[already], fileio->count - already);
if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR)))
{
@@ -1578,9 +1597,9 @@
lpOverlapped->InternalHigh += result;
- TRACE("wrote %d more bytes %ld/%d so far\n",result,lpOverlapped->InternalHigh,ovp->count);
+ TRACE("wrote %d more bytes %ld/%d so far\n",result,lpOverlapped->InternalHigh,fileio->count);
- if(lpOverlapped->InternalHigh < ovp->count)
+ if(lpOverlapped->InternalHigh < fileio->count)
r = STATUS_PENDING;
else
r = STATUS_SUCCESS;
@@ -1596,7 +1615,7 @@
LPOVERLAPPED overlapped,
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
- async_private *ovp;
+ async_fileio *ovp;
TRACE("file %d to buf %p num %ld %p func %p stub\n",
hFile, buffer, bytesToWrite, overlapped, lpCompletionRoutine);
@@ -1616,34 +1635,35 @@
return FALSE;
}
- ovp = (async_private*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_private));
+ ovp = (async_fileio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_fileio));
if(!ovp)
{
TRACE("HeapAlloc Failed\n");
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
- ovp->lpOverlapped = overlapped;
- ovp->func = FILE_AsyncWriteService;
+ ovp->async.handle = hFile;
+ ovp->async.fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
+ ovp->async.type = ASYNC_TYPE_WRITE;
+ ovp->async.lpOverlapped = overlapped;
+ ovp->async.func = FILE_AsyncWriteService;
+ ovp->async.call_completion = (lpCompletionRoutine ? fileio_call_completion_func : NULL);
ovp->buffer = (LPVOID) buffer;
ovp->count = bytesToWrite;
ovp->completion_func = lpCompletionRoutine;
- ovp->fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
- ovp->type = ASYNC_TYPE_WRITE;
- ovp->handle = hFile;
- if(ovp->fd <0)
+ if(ovp->async.fd <0)
{
HeapFree(GetProcessHeap(), 0, ovp);
return FALSE;
}
/* hook this overlap into the pending async operation list */
- ovp->next = NtCurrentTeb()->pending_list;
- ovp->prev = NULL;
- if(ovp->next)
- ovp->next->prev = ovp;
- NtCurrentTeb()->pending_list = ovp;
+ ovp->async.next = NtCurrentTeb()->pending_list;
+ ovp->async.prev = NULL;
+ if(ovp->async.next)
+ ovp->async.next->prev = &ovp->async;
+ NtCurrentTeb()->pending_list = &ovp->async;
return TRUE;
}
diff -ruX diffignore CVS/wine/include/file.h MW/wine/include/file.h
--- CVS/wine/include/file.h Tue Jan 8 17:43:45 2002
+++ MW/wine/include/file.h Tue Jan 8 17:47:41 2002
@@ -33,20 +33,31 @@
/* overlapped private structure */
struct async_private;
-typedef void (*async_handler)(struct async_private *ovp);
+
+typedef void (*async_handler) (struct async_private *ovp);
+typedef void CALLBACK (*async_call_completion_func) (ULONG_PTR data);
+
+extern void CALLBACK fileio_call_completion_func (ULONG_PTR data);
+
typedef struct async_private
{
- LPOVERLAPPED lpOverlapped;
- HANDLE handle;
- int fd;
- char *buffer;
- async_handler func;
- int count;
- int type;
- LPOVERLAPPED_COMPLETION_ROUTINE completion_func;
- struct async_private *next;
- struct async_private *prev;
+ HANDLE handle;
+ int fd;
+ int type;
+ LPOVERLAPPED lpOverlapped;
+ async_handler func;
+ async_call_completion_func call_completion;
+ struct async_private *next;
+ struct async_private *prev;
} async_private;
+
+typedef struct async_fileio
+{
+ async_private async;
+ LPOVERLAPPED_COMPLETION_ROUTINE completion_func;
+ char *buffer;
+ int count;
+} async_fileio;
extern void WINAPI check_async_list(LPOVERLAPPED ov, DWORD status);
extern void finish_async(struct async_private *ovp, DWORD status);
diff -ruX diffignore CVS/wine/scheduler/synchro.c MW/wine/scheduler/synchro.c
--- CVS/wine/scheduler/synchro.c Tue Jan 8 17:43:37 2002
+++ MW/wine/scheduler/synchro.c Tue Jan 8 17:47:41 2002
@@ -36,25 +36,14 @@
}
}
-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);
-}
-
void finish_async(async_private *ovp, DWORD status)
{
ovp->lpOverlapped->Internal=status;
- /* call ReadFileEx/WriteFileEx's overlapped completion function */
- if(ovp->completion_func)
+ /* call overlapped completion function */
+ if(ovp->call_completion)
{
- QueueUserAPC(call_completion_routine,GetCurrentThread(),(ULONG_PTR)ovp);
+ QueueUserAPC(ovp->call_completion,GetCurrentThread(),(ULONG_PTR)ovp);
}
/* remove it from the active list */
@@ -70,7 +59,7 @@
ovp->prev=NULL;
close(ovp->fd);
- if(!ovp->completion_func) HeapFree(GetProcessHeap(), 0, ovp);
+ if(!ovp->call_completion) HeapFree(GetProcessHeap(), 0, ovp);
}
/***********************************************************************
@@ -80,7 +69,7 @@
*/
void WINAPI check_async_list(LPOVERLAPPED overlapped, DWORD status)
{
- async_private *ovp;
+ async_private *ovp = NULL;
/* fprintf(stderr,"overlapped %p status %x\n",overlapped,status); */