PATCH: async-func.diff
This is an improvement over my previous patch (async-struct.diff) in that it does not need the static function check_async_lists in several source files anymore and still achieves DLL separation.
The idea is that all async I/O requests use check_async_list as callback function anyway, so that there is no need to pass a function pointer. I discussed the idea with Mike, and he seemed to like it.
Patch against: Wine CVS 2002/04/04, with my async-struct patch applied. Test status: Compiles warnings. Tested regular file async IO (ok). Serial port async IO: a test would be desirable.
Modified files: include : async.h (remove check_async_list) server : protocol.def (add APC_ASYNC_IO APC type, remove func field for create_async) async.h (remove func field in async struct) async.c (remove references to func field) thread.c (allow NULL function pointer for APC_ASYNC_IO) scheduler : synchro.c (add check_async_list; call from call_apcs for APC_ASYNC_IO)
-- Martin
diff -ruNX ignore MW/wine/include/async.h TMP/wine/include/async.h --- MW/wine/include/async.h Thu Apr 4 18:07:36 2002 +++ TMP/wine/include/async.h Thu Apr 4 18:08:56 2002 @@ -56,8 +56,6 @@
/* All functions declared static for Dll separation purposes */
-static void WINAPI check_async_list(async_private *asp, DWORD status); - inline static void finish_async( async_private *ovp ) { if(ovp->prev) @@ -87,7 +85,6 @@ req->overlapped = ovp; req->type = ovp->type; req->count = ovp->ops->get_count( ovp ); - req->func = check_async_list; req->status = status; ret = wine_server_call( req ); } @@ -115,29 +112,6 @@ NtCurrentTeb()->pending_list = ovp;
return __register_async( ovp, status ); -} - -static void WINAPI check_async_list(async_private *asp, DWORD status) -{ - async_private *ovp; - DWORD ovp_status; - - for( ovp = NtCurrentTeb()->pending_list; ovp && ovp != asp; ovp = ovp->next ); - - if(!ovp) - return; - - if( status != STATUS_ALERTED ) - { - ovp_status = status; - ovp->ops->set_status (ovp, status); - } - else ovp_status = ovp->ops->get_status (ovp); - - if( ovp_status == STATUS_PENDING ) ovp->func( ovp ); /* ovp->func may change status */ - - /* This will destroy all but PENDING requests */ - register_old_async( ovp ); }
#endif /* __WINE_ASYNC_H */ diff -ruNX ignore MW/wine/include/wine/server_protocol.h TMP/wine/include/wine/server_protocol.h --- MW/wine/include/wine/server_protocol.h Thu Apr 4 18:07:36 2002 +++ TMP/wine/include/wine/server_protocol.h Thu Apr 4 17:49:50 2002 @@ -502,7 +502,7 @@ int type; /* VARARG(args,ptrs); */ }; -enum apc_type { APC_NONE, APC_USER, APC_TIMER, APC_ASYNC }; +enum apc_type { APC_NONE, APC_USER, APC_TIMER, APC_ASYNC, APC_ASYNC_IO };
@@ -2278,7 +2278,6 @@ { struct request_header __header; handle_t handle; - void* func; int type; void* overlapped; int count; @@ -3200,6 +3199,6 @@ struct get_window_properties_reply get_window_properties_reply; };
-#define SERVER_PROTOCOL_VERSION 78 +#define SERVER_PROTOCOL_VERSION 81
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff -ruNX ignore MW/wine/scheduler/synchro.c TMP/wine/scheduler/synchro.c --- MW/wine/scheduler/synchro.c Thu Apr 4 18:07:36 2002 +++ TMP/wine/scheduler/synchro.c Thu Apr 4 17:54:20 2002 @@ -30,7 +30,7 @@ #include "thread.h" #include "winerror.h" #include "wine/server.h" - +#include "async.h"
/*********************************************************************** * get_timeout @@ -90,6 +90,34 @@
/*********************************************************************** + * check_async_list + * + * Handle async I/O requests. + */ +static void WINAPI check_async_list(async_private *asp, DWORD status) +{ + async_private *ovp; + DWORD ovp_status; + + for( ovp = NtCurrentTeb()->pending_list; ovp && ovp != asp; ovp = ovp->next ); + + if(!ovp) + return; + + if( status != STATUS_ALERTED ) + { + ovp_status = status; + ovp->ops->set_status (ovp, status); + } + else ovp_status = ovp->ops->get_status (ovp); + + if( ovp_status == STATUS_PENDING ) ovp->func( ovp ); + + /* This will destroy all but PENDING requests */ + register_old_async( ovp ); +} + +/*********************************************************************** * call_apcs * * Call outstanding APCs. @@ -129,6 +157,9 @@ /* convert sec/usec to NT time */ DOSFS_UnixTimeToFileTime( (time_t)args[0], &ft, (DWORD)args[1] * 10 ); proc( args[2], ft.dwLowDateTime, ft.dwHighDateTime ); + break; + case APC_ASYNC_IO: + check_async_list ( args[0], (DWORD) args[1]); break; default: server_protocol_error( "get_apc_request: bad type %d\n", type ); diff -ruNX ignore MW/wine/server/async.c TMP/wine/server/async.c --- MW/wine/server/async.c Thu Apr 4 18:07:36 2002 +++ TMP/wine/server/async.c Thu Apr 4 17:50:45 2002 @@ -64,7 +64,7 @@ { /* fprintf(stderr,"notifying %p!\n",async->overlapped); */ async->status = status; - thread_queue_apc(async->thread, NULL, async->func, APC_ASYNC, 1, 2, async->overlapped, status); + thread_queue_apc(async->thread, NULL, NULL, APC_ASYNC_IO, 1, 2, async->overlapped, status); }
void destroy_async_queue( struct async_queue *q ) @@ -116,7 +116,7 @@ destroy_async(async); }
-struct async *create_async(struct object *obj, struct thread *thread, void *func, +struct async *create_async(struct object *obj, struct thread *thread, void *overlapped) { struct async *async = (struct async *) malloc(sizeof(struct async)); @@ -128,7 +128,6 @@
async->obj = obj; async->thread = thread; - async->func = func; async->overlapped = overlapped; async->next = NULL; async->prev = NULL; @@ -165,7 +164,7 @@ if(req->status==STATUS_PENDING) { if(!async) - async = create_async(obj, current, req->func, req->overlapped); + async = create_async(obj, current, req->overlapped);
if(async) { diff -ruNX ignore MW/wine/server/async.h TMP/wine/server/async.h --- MW/wine/server/async.h Tue Apr 2 16:51:50 2002 +++ TMP/wine/server/async.h Thu Apr 4 17:50:57 2002 @@ -30,7 +30,6 @@ { struct object *obj; struct thread *thread; - void *func; void *overlapped; unsigned int status; struct timeval when; @@ -51,7 +50,7 @@ struct async *find_async(struct async_queue *q, struct thread *thread, void *overlapped); void async_insert(struct async_queue *q, struct async *async); struct async *create_async(struct object *obj, struct thread *thread, - void *func, void *overlapped); + void *overlapped); void async_add_timeout(struct async *async, int timeout); static inline void init_async_queue(struct async_queue *q) { diff -ruNX ignore MW/wine/server/protocol.def TMP/wine/server/protocol.def --- MW/wine/server/protocol.def Thu Apr 4 18:07:36 2002 +++ TMP/wine/server/protocol.def Thu Apr 4 17:49:45 2002 @@ -412,7 +412,7 @@ int type; /* function type */ VARARG(args,ptrs); /* function arguments */ @END -enum apc_type { APC_NONE, APC_USER, APC_TIMER, APC_ASYNC }; +enum apc_type { APC_NONE, APC_USER, APC_TIMER, APC_ASYNC, APC_ASYNC_IO };
/* Close a handle for the current process */ @@ -1618,7 +1618,6 @@ /* Create / reschedule an async I/O */ @REQ(register_async) handle_t handle; /* handle to comm port, socket or file */ - void* func; int type; void* overlapped; int count; diff -ruNX ignore MW/wine/server/thread.c TMP/wine/server/thread.c --- MW/wine/server/thread.c Tue Apr 2 16:51:51 2002 +++ TMP/wine/server/thread.c Thu Apr 4 17:37:22 2002 @@ -959,8 +959,9 @@ } /* Optimization: ignore APCs that have a NULL func; they are only used * to wake up a thread, but since we got here the thread woke up already. + * Exception: for APC_ASYNC_IO, func == NULL is legal. */ - if (apc->func) break; + if (apc->func || apc->type == APC_ASYNC_IO) break; free( apc ); } size = apc->nb_args * sizeof(apc->args[0]); diff -ruNX ignore MW/wine/server/trace.c TMP/wine/server/trace.c --- MW/wine/server/trace.c Thu Apr 4 18:07:36 2002 +++ TMP/wine/server/trace.c Thu Apr 4 17:49:50 2002 @@ -1846,7 +1846,6 @@ static void dump_register_async_request( const struct register_async_request *req ) { fprintf( stderr, " handle=%d,", req->handle ); - fprintf( stderr, " func=%p,", req->func ); fprintf( stderr, " type=%d,", req->type ); fprintf( stderr, " overlapped=%p,", req->overlapped ); fprintf( stderr, " count=%d,", req->count );