ntdll: Move server call functions to the Unix library.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Alexandre Julliard 2020-05-29 15:53:42 +02:00
parent 1a743c9af3
commit 01150d7f8d
7 changed files with 118 additions and 103 deletions

View File

@ -119,7 +119,6 @@ extern void server_init_process_done(void) DECLSPEC_HIDDEN;
extern void DECLSPEC_NORETURN abort_thread( int status ) DECLSPEC_HIDDEN;
extern void DECLSPEC_NORETURN exit_thread( int status ) DECLSPEC_HIDDEN;
extern sigset_t server_block_set DECLSPEC_HIDDEN;
extern unsigned int server_call_unlocked( void *req_ptr ) DECLSPEC_HIDDEN;
extern void server_enter_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ) DECLSPEC_HIDDEN;
extern void server_leave_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ) DECLSPEC_HIDDEN;
extern unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT flags,

View File

@ -142,98 +142,6 @@ static DECLSPEC_NORETURN void server_protocol_perror( const char *err )
}
/***********************************************************************
* send_request
*
* Send a request to the server.
*/
static unsigned int send_request( const struct __server_request_info *req )
{
unsigned int i;
int ret;
if (!req->u.req.request_header.request_size)
{
if ((ret = write( ntdll_get_thread_data()->request_fd, &req->u.req,
sizeof(req->u.req) )) == sizeof(req->u.req)) return STATUS_SUCCESS;
}
else
{
struct iovec vec[__SERVER_MAX_DATA+1];
vec[0].iov_base = (void *)&req->u.req;
vec[0].iov_len = sizeof(req->u.req);
for (i = 0; i < req->data_count; i++)
{
vec[i+1].iov_base = (void *)req->data[i].ptr;
vec[i+1].iov_len = req->data[i].size;
}
if ((ret = writev( ntdll_get_thread_data()->request_fd, vec, i+1 )) ==
req->u.req.request_header.request_size + sizeof(req->u.req)) return STATUS_SUCCESS;
}
if (ret >= 0) server_protocol_error( "partial write %d\n", ret );
if (errno == EPIPE) abort_thread(0);
if (errno == EFAULT) return STATUS_ACCESS_VIOLATION;
server_protocol_perror( "write" );
}
/***********************************************************************
* read_reply_data
*
* Read data from the reply buffer; helper for wait_reply.
*/
static void read_reply_data( void *buffer, size_t size )
{
int ret;
for (;;)
{
if ((ret = read( ntdll_get_thread_data()->reply_fd, buffer, size )) > 0)
{
if (!(size -= ret)) return;
buffer = (char *)buffer + ret;
continue;
}
if (!ret) break;
if (errno == EINTR) continue;
if (errno == EPIPE) break;
server_protocol_perror("read");
}
/* the server closed the connection; time to die... */
abort_thread(0);
}
/***********************************************************************
* wait_reply
*
* Wait for a reply from the server.
*/
static inline unsigned int wait_reply( struct __server_request_info *req )
{
read_reply_data( &req->u.reply, sizeof(req->u.reply) );
if (req->u.reply.reply_header.reply_size)
read_reply_data( req->reply_data, req->u.reply.reply_header.reply_size );
return req->u.reply.reply_header.error;
}
/***********************************************************************
* server_call_unlocked
*/
unsigned int server_call_unlocked( void *req_ptr )
{
struct __server_request_info * const req = req_ptr;
unsigned int ret;
if ((ret = send_request( req ))) return ret;
return wait_reply( req );
}
/***********************************************************************
* wine_server_call (NTDLL.@)
*
@ -258,13 +166,7 @@ unsigned int server_call_unlocked( void *req_ptr )
*/
unsigned int CDECL wine_server_call( void *req_ptr )
{
sigset_t old_set;
unsigned int ret;
pthread_sigmask( SIG_BLOCK, &server_block_set, &old_set );
ret = server_call_unlocked( req_ptr );
pthread_sigmask( SIG_SETMASK, &old_set, NULL );
return ret;
return unix_funcs->server_call( req_ptr );
}
@ -582,7 +484,7 @@ unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT
suspend_context = FALSE; /* server owns the context now */
}
if (context) wine_server_set_reply( req, &server_context, sizeof(server_context) );
ret = server_call_unlocked( req );
ret = unix_funcs->server_call_unlocked( req );
apc_handle = reply->apc_handle;
call = reply->call;
if (wine_server_reply_size( reply ))

View File

@ -996,6 +996,8 @@ static struct unix_funcs unix_funcs =
mmap_remove_reserved_area,
mmap_is_in_reserved_area,
mmap_enum_reserved_areas,
server_call_unlocked,
wine_server_call,
server_send_fd,
server_remove_fd_from_cache,
server_get_unix_fd,

View File

@ -205,6 +205,115 @@ static DECLSPEC_NORETURN void server_protocol_perror( const char *err )
}
/***********************************************************************
* send_request
*
* Send a request to the server.
*/
static unsigned int send_request( const struct __server_request_info *req )
{
unsigned int i;
int ret;
if (!req->u.req.request_header.request_size)
{
if ((ret = write( ntdll_get_thread_data()->request_fd, &req->u.req,
sizeof(req->u.req) )) == sizeof(req->u.req)) return STATUS_SUCCESS;
}
else
{
struct iovec vec[__SERVER_MAX_DATA+1];
vec[0].iov_base = (void *)&req->u.req;
vec[0].iov_len = sizeof(req->u.req);
for (i = 0; i < req->data_count; i++)
{
vec[i+1].iov_base = (void *)req->data[i].ptr;
vec[i+1].iov_len = req->data[i].size;
}
if ((ret = writev( ntdll_get_thread_data()->request_fd, vec, i+1 )) ==
req->u.req.request_header.request_size + sizeof(req->u.req)) return STATUS_SUCCESS;
}
if (ret >= 0) server_protocol_error( "partial write %d\n", ret );
if (errno == EPIPE) NtTerminateThread( GetCurrentThread(), 0 );
if (errno == EFAULT) return STATUS_ACCESS_VIOLATION;
server_protocol_perror( "write" );
}
/***********************************************************************
* read_reply_data
*
* Read data from the reply buffer; helper for wait_reply.
*/
static void read_reply_data( void *buffer, size_t size )
{
int ret;
for (;;)
{
if ((ret = read( ntdll_get_thread_data()->reply_fd, buffer, size )) > 0)
{
if (!(size -= ret)) return;
buffer = (char *)buffer + ret;
continue;
}
if (!ret) break;
if (errno == EINTR) continue;
if (errno == EPIPE) break;
server_protocol_perror("read");
}
/* the server closed the connection; time to die... */
for (;;) NtTerminateThread( GetCurrentThread(), 0 );
}
/***********************************************************************
* wait_reply
*
* Wait for a reply from the server.
*/
static inline unsigned int wait_reply( struct __server_request_info *req )
{
read_reply_data( &req->u.reply, sizeof(req->u.reply) );
if (req->u.reply.reply_header.reply_size)
read_reply_data( req->reply_data, req->u.reply.reply_header.reply_size );
return req->u.reply.reply_header.error;
}
/***********************************************************************
* server_call_unlocked
*/
unsigned int CDECL server_call_unlocked( void *req_ptr )
{
struct __server_request_info * const req = req_ptr;
unsigned int ret;
if ((ret = send_request( req ))) return ret;
return wait_reply( req );
}
/***********************************************************************
* wine_server_call
*
* Perform a server call.
*/
unsigned int CDECL wine_server_call( void *req_ptr )
{
sigset_t old_set;
unsigned int ret;
pthread_sigmask( SIG_BLOCK, &server_block_set, &old_set );
ret = server_call_unlocked( req_ptr );
pthread_sigmask( SIG_SETMASK, &old_set, NULL );
return ret;
}
/***********************************************************************
* server_enter_uninterrupted_section
*/

View File

@ -60,6 +60,7 @@ extern void virtual_init(void) DECLSPEC_HIDDEN;
extern void CDECL dbg_init(void) DECLSPEC_HIDDEN;
extern unsigned int CDECL server_call_unlocked( void *req_ptr ) DECLSPEC_HIDDEN;
extern void CDECL server_send_fd( int fd ) DECLSPEC_HIDDEN;
extern int CDECL server_remove_fd_from_cache( HANDLE handle ) DECLSPEC_HIDDEN;
extern int CDECL server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,

View File

@ -25,7 +25,7 @@
#include "wine/debug.h"
/* increment this when you change the function table */
#define NTDLL_UNIXLIB_VERSION 9
#define NTDLL_UNIXLIB_VERSION 10
struct unix_funcs
{
@ -51,6 +51,8 @@ struct unix_funcs
void *arg, int top_down );
/* server functions */
unsigned int (CDECL *server_call_unlocked)( void *req_ptr );
unsigned int (CDECL *server_call)( void *req_ptr );
void (CDECL *server_send_fd)( int fd );
int (CDECL *server_remove_fd_from_cache)( HANDLE handle );
int (CDECL *server_get_unix_fd)( HANDLE handle, unsigned int wanted_access, int *unix_fd,

View File

@ -2390,7 +2390,7 @@ unsigned int virtual_locked_server_call( void *req_ptr )
server_enter_uninterrupted_section( &csVirtual, &sigset );
if (!(ret = check_write_access( addr, size, &has_write_watch )))
{
ret = server_call_unlocked( req );
ret = unix_funcs->server_call_unlocked( req );
if (has_write_watch) update_write_watches( addr, size, wine_server_reply_size( req ));
}
server_leave_uninterrupted_section( &csVirtual, &sigset );