Hi Martin,
i don't know much about Winsock, but i can tell you how overlapped I/O is supposed to work in Wine.
The bulk of the implementation is in files/file.c and scheduler/synchro.c. When ReadFile is called on a handle, the following happens:
1. check that the handle is valid and was opened with FILE_FLAG_OVERLAPPED. 2. attempt to read any data that is available immediately, and perhaps return if we read enough already. 3. queue the operation onto CurrentTeb()->pending_list
When the thread waits upon any server object, all (unix) fds with pending overlapped operations are polled on. This is a minor problem in the design; if the thread never waits upon an object the overlapped can never complete, however the thread must wait upon the overlapped's hEvent to check whether it has completed...
The only part of the serial comms overlapped implementation the lives in the wineserver is the calculation of overlapped timeouts.
So to get winsock to do overlapped, you may have to modify the winsock code to work like that... but the winsock code uses the service thread to wait upon sockets. The task is definitely not impossible, but it might take a bit of work :-)
Maybe Ove K. can give you some advice?
Mike
In particular, it uses the Winsock 2 feature of "Overlapped IO" on sockets, with user-supplied callbacks that are called when data is received on a socket etc.
Browsing through the Wine Winsock code, I saw that this part of Winsock2 is obviously unimplemented.
------------------------------------------ mailto:Mike_McCormack@start.com.au ph +82 16 430 0425
__________________________________________________________________ Get your free Australian email account at http://www.Looksmart.com.au
On Tue, 6 Nov 2001, Mike McCormack wrote:
i don't know much about Winsock, but i can tell you how overlapped I/O is supposed to work in Wine.
Hm, by the way, when are you going to implemented overlapped ConnectNamedPipe? That might make my rpcrt4 wait-for-connection code a bit cleaner, so I don't have to spawn a separate thread per named pipe, and worse, use TerminateThread to cancel the wait...
So to get winsock to do overlapped, you may have to modify the winsock code to work like that... but the winsock code uses the service thread to wait upon sockets.
Not really, the wineserver does the grunt work. The service thread is only used to implement WSAAsyncSelect, to post messages when the wineserver says that it should. Winsock2 code is unlikely to use WSAAsyncSelect, they'd rather do either WSAEventSelect (which doesn't use the service thread, but is 100% wineserver-based), *or* overlapped I/O.
The challenges for winsock2 should be pretty much the same as those for implementing something like ReadFileEx (which you've probably already done) and the above-mentioned overlapped ConnectNamedPipe.
Hi Mike,
The bulk of the implementation is in files/file.c and scheduler/synchro.c. When ReadFile is called on a handle, the following happens:
- check that the handle is valid > FILE_FLAG_OVERLAPPED.
- attempt to read any data that is available immediately, and perhaps
return if we read enough already. 3. queue the operation onto CurrentTeb()->pending_list
I have taken a closer look at this code. I believe a very similar approach is possible for Winsock. However, there are a few problems:
The asynchronous functions for Winsock take different arguments than the file I/O functions. Thus, the async_handler structure as defined in file.h must be changed such that Winsock can define a compatible wsa_async_handler structure. In a first attempt, I changed the sequence of fields in async_handler such that common elements between file and winsock routines come first, others at the end. Moreover, the "finish_async" function will be different for File and Winsock I/O. Thus, I've come up with a new declaration of async_private that looks like this:
struct async_private; typedef void (*async_handler) (struct async_private*, int); typedef void (*async_finish) (struct async_private*, int); typedef struct async_private { struct async_private *next; struct async_private *prev; int fd; async_handler func; async_finish finish; LPOVERLAPPED lpOverlapped; LPOVERLAPPED_COMPLETION_ROUTINE completion_func; int event; int timeout; /* "common" elements end here */ struct timeval tv; char *buffer; int count; } async_private;
What do you think about this?
It would be cleaner to define a "general" async structure containing either a type-specific union or a pointer to type-specific data, and using void* for pointers. However, that would require even more changes in the async file I/O code, which I'd like to avoid at the moment.
Another difference is that the overlapped Winsock routines cause asynchronous success notification (i.e. calling the completion routine or signalling the lpOverlapped->hEvent) even if they are immediately successful, which seems not to be the case for asynchronous file I/O.
That would require a minor change in the check_async_list() routine.
Please tell me your opinion!
Regards, Martin
-- Martin Wilck Phone: +49 5251 8 15113 Fujitsu Siemens Computers Fax: +49 5251 8 20409 Heinz-Nixdorf-Ring 1 mailto:Martin.Wilck@Fujitsu-Siemens.com D-33106 Paderborn http://www.fujitsu-siemens.com/primergy