ntdll: Simplify the async read/write code now that most of the work is done in the server.

This commit is contained in:
Alexandre Julliard 2007-04-10 17:19:24 +02:00
parent 72bff2e445
commit 6dcb280bc5
1 changed files with 63 additions and 58 deletions

View File

@ -236,57 +236,24 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIB
/*********************************************************************** /***********************************************************************
* Asynchronous file I/O * * Asynchronous file I/O *
*/ */
static NTSTATUS FILE_AsyncReadService(void*, PIO_STATUS_BLOCK, NTSTATUS);
static NTSTATUS FILE_AsyncWriteService(void*, PIO_STATUS_BLOCK, NTSTATUS);
typedef struct async_fileio typedef struct
{ {
HANDLE handle; HANDLE handle;
PIO_APC_ROUTINE apc;
void* apc_user;
char* buffer; char* buffer;
unsigned int already; unsigned int already;
unsigned int count; unsigned int count;
BOOL avail_mode; BOOL avail_mode;
HANDLE event; } async_fileio_read;
} async_fileio;
static void fileio_terminate(async_fileio *fileio, IO_STATUS_BLOCK* iosb, NTSTATUS status) typedef struct
{ {
TRACE("data: %p\n", fileio); HANDLE handle;
const char *buffer;
unsigned int already;
unsigned int count;
} async_fileio_write;
iosb->u.Status = status;
iosb->Information = fileio->already;
RtlFreeHeap( GetProcessHeap(), 0, fileio );
}
static ULONG fileio_queue_async(async_fileio* fileio, IO_STATUS_BLOCK* iosb,
BOOL do_read)
{
NTSTATUS status;
SERVER_START_REQ( register_async )
{
req->handle = fileio->handle;
req->async.callback = do_read ? FILE_AsyncReadService : FILE_AsyncWriteService;
req->async.iosb = iosb;
req->async.arg = fileio;
req->async.apc = fileio->apc;
req->async.apc_arg = fileio->apc_user;
req->async.event = fileio->event;
req->type = do_read ? ASYNC_TYPE_READ : ASYNC_TYPE_WRITE;
req->count = (fileio->count < fileio->already) ? 0 : fileio->count - fileio->already;
status = wine_server_call( req );
}
SERVER_END_REQ;
if (status != STATUS_PENDING)
fileio_terminate( fileio, iosb, status );
else
NtCurrentTeb()->num_async_io++;
return status;
}
/*********************************************************************** /***********************************************************************
* FILE_GetNtStatus(void) * FILE_GetNtStatus(void)
@ -339,7 +306,7 @@ NTSTATUS FILE_GetNtStatus(void)
*/ */
static NTSTATUS FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, NTSTATUS status) static NTSTATUS FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, NTSTATUS status)
{ {
async_fileio *fileio = (async_fileio*)user; async_fileio_read *fileio = user;
int fd, needs_close, result; int fd, needs_close, result;
TRACE("%p %p 0x%x\n", iosb, fileio->buffer, status); TRACE("%p %p 0x%x\n", iosb, fileio->buffer, status);
@ -394,7 +361,12 @@ static NTSTATUS FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, NTSTATU
if (fileio->already) status = STATUS_SUCCESS; if (fileio->already) status = STATUS_SUCCESS;
break; break;
} }
if (status != STATUS_PENDING) fileio_terminate(fileio, iosb, status); if (status != STATUS_PENDING)
{
iosb->u.Status = status;
iosb->Information = fileio->already;
RtlFreeHeap( GetProcessHeap(), 0, fileio );
}
return status; return status;
} }
@ -580,7 +552,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
if (flags & FD_FLAG_OVERLAPPED) if (flags & FD_FLAG_OVERLAPPED)
{ {
async_fileio *fileio; async_fileio_read *fileio;
if (total && (flags & FD_FLAG_AVAILABLE)) if (total && (flags & FD_FLAG_AVAILABLE))
{ {
@ -588,7 +560,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
goto done; goto done;
} }
if (!(fileio = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio)))) if (!(fileio = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*fileio))))
{ {
status = STATUS_NO_MEMORY; status = STATUS_NO_MEMORY;
goto done; goto done;
@ -596,12 +568,26 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
fileio->handle = hFile; fileio->handle = hFile;
fileio->already = total; fileio->already = total;
fileio->count = length; fileio->count = length;
fileio->apc = apc;
fileio->apc_user = apc_user;
fileio->buffer = buffer; fileio->buffer = buffer;
fileio->avail_mode = (flags & FD_FLAG_AVAILABLE); fileio->avail_mode = (flags & FD_FLAG_AVAILABLE);
fileio->event = hEvent;
status = fileio_queue_async(fileio, io_status, TRUE); SERVER_START_REQ( register_async )
{
req->handle = hFile;
req->type = ASYNC_TYPE_READ;
req->count = length;
req->async.callback = FILE_AsyncReadService;
req->async.iosb = io_status;
req->async.arg = fileio;
req->async.apc = apc;
req->async.apc_arg = apc_user;
req->async.event = hEvent;
status = wine_server_call( req );
}
SERVER_END_REQ;
if (status != STATUS_PENDING) RtlFreeHeap( GetProcessHeap(), 0, fileio );
else NtCurrentTeb()->num_async_io++;
goto done; goto done;
} }
else /* synchronous read, wait for the fd to become ready */ else /* synchronous read, wait for the fd to become ready */
@ -662,7 +648,7 @@ done:
*/ */
static NTSTATUS FILE_AsyncWriteService(void *user, IO_STATUS_BLOCK *iosb, NTSTATUS status) static NTSTATUS FILE_AsyncWriteService(void *user, IO_STATUS_BLOCK *iosb, NTSTATUS status)
{ {
async_fileio *fileio = user; async_fileio_write *fileio = user;
int result, fd, needs_close; int result, fd, needs_close;
enum server_fd_type type; enum server_fd_type type;
@ -701,7 +687,12 @@ static NTSTATUS FILE_AsyncWriteService(void *user, IO_STATUS_BLOCK *iosb, NTSTAT
if (fileio->already) status = STATUS_SUCCESS; if (fileio->already) status = STATUS_SUCCESS;
break; break;
} }
if (status != STATUS_PENDING) fileio_terminate(fileio, iosb, status); if (status != STATUS_PENDING)
{
iosb->u.Status = status;
iosb->Information = fileio->already;
RtlFreeHeap( GetProcessHeap(), 0, fileio );
}
return status; return status;
} }
@ -799,9 +790,9 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
if (flags & FD_FLAG_OVERLAPPED) if (flags & FD_FLAG_OVERLAPPED)
{ {
async_fileio *fileio; async_fileio_write *fileio;
if (!(fileio = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio)))) if (!(fileio = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*fileio))))
{ {
status = STATUS_NO_MEMORY; status = STATUS_NO_MEMORY;
goto done; goto done;
@ -809,11 +800,25 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
fileio->handle = hFile; fileio->handle = hFile;
fileio->already = total; fileio->already = total;
fileio->count = length; fileio->count = length;
fileio->apc = apc; fileio->buffer = buffer;
fileio->apc_user = apc_user;
fileio->buffer = (void*)buffer; SERVER_START_REQ( register_async )
fileio->event = hEvent; {
status = fileio_queue_async(fileio, io_status, FALSE); req->handle = hFile;
req->type = ASYNC_TYPE_WRITE;
req->count = length;
req->async.callback = FILE_AsyncWriteService;
req->async.iosb = io_status;
req->async.arg = fileio;
req->async.apc = apc;
req->async.apc_arg = apc_user;
req->async.event = hEvent;
status = wine_server_call( req );
}
SERVER_END_REQ;
if (status != STATUS_PENDING) RtlFreeHeap( GetProcessHeap(), 0, fileio );
else NtCurrentTeb()->num_async_io++;
goto done; goto done;
} }
else /* synchronous write, wait for the fd to become ready */ else /* synchronous write, wait for the fd to become ready */