Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
1eac1911
Commit
1eac1911
authored
Nov 13, 2000
by
Mike McCormack
Committed by
Alexandre Julliard
Nov 13, 2000
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
- created server object for handling async i/o
- implemented WaitCommEvent with the EV_RXCHAR flag - implemented GetOverlappedResult
parent
745ec84c
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
524 additions
and
5 deletions
+524
-5
comm.c
dlls/kernel/comm.c
+101
-3
server.h
include/server.h
+32
-2
synchro.c
scheduler/synchro.c
+3
-0
Makefile.in
server/Makefile.in
+1
-0
async.c
server/async.c
+270
-0
object.h
server/object.h
+15
-0
request.h
server/request.h
+4
-0
serial.c
server/serial.c
+71
-0
trace.c
server/trace.c
+27
-0
No files found.
dlls/kernel/comm.c
View file @
1eac1911
...
...
@@ -2580,13 +2580,111 @@ BOOL WINAPI GetCommModemStatus(HANDLE hFile,LPDWORD lpModemStat )
return
FALSE
;
#endif
}
VOID
COMM_WaitCommEventService
(
void
**
args
)
{
LPOVERLAPPED
lpOverlapped
=
(
LPOVERLAPPED
)
args
[
0
];
LPDWORD
buffer
=
(
LPDWORD
)
args
[
1
];
DWORD
events
=
(
DWORD
)
args
[
2
];
TRACE
(
"overlapped %p wait complete %p <- %lx
\n
"
,
lpOverlapped
,
buffer
,
events
);
if
(
buffer
)
*
buffer
=
events
;
SetEvent
(
lpOverlapped
->
hEvent
);
}
/***********************************************************************
* WaitCommEvent (KERNEL32.719)
*
* Wait until something interesting happens on a COMM port.
* Interesting things (events) are set by calling SetCommMask before
* this function is called.
*
* RETURNS:
* TRUE if successful
* FALSE if failure
*
* The set of detected events will be written to *lpdwEventMask
* ERROR_IO_PENDING will be returned the overlapped structure was passed
*
* BUGS:
* Only supports EV_RXCHAR and EV_TXEMPTY
*/
BOOL
WINAPI
WaitCommEvent
(
HANDLE
hFile
,
LPDWORD
eventmask
,
LPOVERLAPPED
overlapped
)
BOOL
WINAPI
WaitCommEvent
(
HANDLE
hFile
,
/* [I] handle of comm port to wait for */
LPDWORD
lpdwEvents
,
/* [O] event(s) that were detected */
LPOVERLAPPED
lpOverlapped
/* [I/O] for Asynchronous waiting */
)
{
OVERLAPPED
ov
;
LPOVERLAPPED
lpov
;
int
ret
;
TRACE
(
"(%x %p %p )
\n
"
,
hFile
,
lpdwEvents
,
lpOverlapped
);
/* if there is no overlapped structure, create our own */
if
(
!
lpOverlapped
)
{
ov
.
hEvent
=
CreateEventA
(
NULL
,
FALSE
,
FALSE
,
NULL
);
lpov
=
&
ov
;
}
else
lpov
=
lpOverlapped
;
/* check that the overlapped structure has a valid event flag */
if
(
(
lpov
->
hEvent
==
0
)
||
(
lpov
->
hEvent
==
INVALID_HANDLE_VALUE
)
)
{
FIXME
(
"(%d %p %p )
\n
"
,
hFile
,
eventmask
,
overlapped
);
return
TRUE
;
ERR
(
"Couldn't create Event flag for Overlapped structure
\n
"
);
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
lpov
->
Internal
=
0
;
lpov
->
InternalHigh
=
hFile
;
lpov
->
Offset
=
0
;
lpov
->
OffsetHigh
=
0
;
/* start an ASYNCHRONOUS WaitCommEvent */
SERVER_START_REQ
{
struct
create_async_request
*
req
=
server_alloc_req
(
sizeof
(
*
req
),
0
);
req
->
file_handle
=
hFile
;
req
->
overlapped
=
lpov
;
req
->
buffer
=
lpdwEvents
;
req
->
count
=
0
;
req
->
func
=
COMM_WaitCommEventService
;
req
->
type
=
ASYNC_TYPE_WAIT
;
ret
=
server_call
(
REQ_CREATE_ASYNC
);
lpov
->
Internal
=
req
->
ov_handle
;
}
SERVER_END_REQ
;
if
(
ret
)
{
if
(
!
lpOverlapped
)
CloseHandle
(
lpov
->
hEvent
);
TRACE
(
"server call failed.
\n
"
);
return
FALSE
;
}
/* wait ourselves if the caller didn't give us an overlapped struct */
if
(
!
lpOverlapped
)
{
GetOverlappedResult
(
hFile
,
lpov
,
NULL
,
TRUE
);
CloseHandle
(
lpov
->
hEvent
);
lpov
->
hEvent
=
0
;
}
else
{
/* caller wants overlapped I/O using GetOverlapped result */
SetLastError
(
ERROR_IO_PENDING
);
return
FALSE
;
}
return
TRUE
;
}
/***********************************************************************
...
...
include/server.h
View file @
1eac1911
...
...
@@ -356,7 +356,7 @@ struct get_apc_request
OUT
int
type
;
/* function type */
OUT
VARARG
(
args
,
ptrs
);
/* function arguments */
};
enum
apc_type
{
APC_NONE
,
APC_USER
,
APC_TIMER
};
enum
apc_type
{
APC_NONE
,
APC_USER
,
APC_TIMER
,
APC_ASYNC
};
/* Close a handle for the current process */
...
...
@@ -1332,6 +1332,32 @@ struct set_serial_info_request
#define SERIALINFO_SET_MASK 0x02
#define SERIALINFO_SET_ERROR 0x04
struct
create_async_request
{
REQUEST_HEADER
;
/* request header */
IN
int
file_handle
;
/* handle to comm port */
IN
void
*
overlapped
;
IN
void
*
buffer
;
IN
int
count
;
IN
void
*
func
;
IN
int
type
;
OUT
int
ov_handle
;
};
#define ASYNC_TYPE_READ 0x01
#define ASYNC_TYPE_WRITE 0x02
#define ASYNC_TYPE_WAIT 0x03
/*
* Used by service thread to tell the server that the current
* operation has completed
*/
struct
async_result_request
{
REQUEST_HEADER
;
/* request header */
IN
int
ov_handle
;
IN
int
result
;
/* NT status code */
};
/* Everything below this line is generated automatically by tools/make_requests */
/* ### make_requests begin ### */
...
...
@@ -1445,6 +1471,8 @@ enum request
REQ_CREATE_SERIAL
,
REQ_GET_SERIAL_INFO
,
REQ_SET_SERIAL_INFO
,
REQ_CREATE_ASYNC
,
REQ_ASYNC_RESULT
,
REQ_NB_REQUESTS
};
...
...
@@ -1560,9 +1588,11 @@ union generic_request
struct
create_serial_request
create_serial
;
struct
get_serial_info_request
get_serial_info
;
struct
set_serial_info_request
set_serial_info
;
struct
create_async_request
create_async
;
struct
async_result_request
async_result
;
};
#define SERVER_PROTOCOL_VERSION 2
6
#define SERVER_PROTOCOL_VERSION 2
7
/* ### make_requests end ### */
/* Everything above this line is generated automatically by tools/make_requests */
...
...
scheduler/synchro.c
View file @
1eac1911
...
...
@@ -46,6 +46,9 @@ static void call_apcs(void)
{
case
APC_NONE
:
return
;
/* no more APCs */
case
APC_ASYNC
:
proc
(
&
args
[
0
]
);
break
;
case
APC_USER
:
proc
(
args
[
0
]
);
break
;
...
...
server/Makefile.in
View file @
1eac1911
...
...
@@ -6,6 +6,7 @@ VPATH = @srcdir@
MODULE
=
none
C_SRCS
=
\
async.c
\
atom.c
\
change.c
\
console.c
\
...
...
server/async.c
0 → 100644
View file @
1eac1911
/*
* Server-side support for async i/o operations
*
* Copyright (C) 1998 Alexandre Julliard
* Copyright (C) 2000 Mike McCormack
*
* TODO:
* Fix up WaitCommEvent operations. Currently only EV_RXCHAR is supported.
* This may require modifications to the linux kernel to enable select
* to wait on Modem Status Register deltas. (delta DCD, CTS, DSR or RING)
*
*/
#include "config.h"
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#ifdef HAVE_SYS_ERRNO_H
#include <sys/errno.h>
#endif
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <utime.h>
#include <termios.h>
#include <sys/ioctl.h>
#include "winerror.h"
#include "winbase.h"
#include "handle.h"
#include "thread.h"
#include "request.h"
struct
async
{
struct
object
obj
;
void
*
client_overlapped
;
int
type
;
int
result
;
int
count
;
int
eventmask
;
struct
async
*
next
;
struct
timeout_user
*
timeout
;
struct
wait_queue_entry
wait
;
void
*
buffer
;
void
*
func
;
struct
thread
*
thread
;
struct
object
*
file
;
};
static
void
async_dump
(
struct
object
*
obj
,
int
verbose
);
static
void
async_destroy
(
struct
object
*
obj
);
static
int
async_get_poll_events
(
struct
object
*
obj
);
static
int
async_get_read_fd
(
struct
object
*
obj
);
static
int
async_get_write_fd
(
struct
object
*
obj
);
static
int
async_get_info
(
struct
object
*
obj
,
struct
get_file_info_request
*
req
);
static
void
async_poll_event
(
struct
object
*
obj
,
int
event
);
static
const
struct
object_ops
async_ops
=
{
sizeof
(
struct
async
),
/* size */
async_dump
,
/* dump */
default_poll_add_queue
,
/* add_queue */
default_poll_remove_queue
,
/* remove_queue */
default_poll_signaled
,
/* signaled */
no_satisfied
,
/* satisfied */
async_get_poll_events
,
/* get_poll_events */
async_poll_event
,
/* poll_event */
async_get_read_fd
,
/* get_read_fd */
async_get_write_fd
,
/* get_write_fd */
no_flush
,
/* flush */
async_get_info
,
/* get_file_info */
async_destroy
/* destroy */
};
static
void
async_dump
(
struct
object
*
obj
,
int
verbose
)
{
struct
async
*
ov
=
(
struct
async
*
)
obj
;
assert
(
obj
->
ops
==
&
async_ops
);
fprintf
(
stderr
,
"async: overlapped %p %s
\n
"
,
ov
->
client_overlapped
,
ov
->
timeout
?
"with timeout"
:
""
);
}
/* same as file_destroy, but don't delete comm ports */
static
void
async_destroy
(
struct
object
*
obj
)
{
struct
async
*
ov
=
(
struct
async
*
)
obj
;
assert
(
obj
->
ops
==
&
async_ops
);
if
(
ov
->
timeout
)
remove_timeout_user
(
ov
->
timeout
);
ov
->
timeout
=
NULL
;
}
struct
async
*
get_async_obj
(
struct
process
*
process
,
int
handle
,
unsigned
int
access
)
{
return
(
struct
async
*
)
get_handle_obj
(
process
,
handle
,
access
,
&
async_ops
);
}
static
int
async_get_poll_events
(
struct
object
*
obj
)
{
struct
async
*
ov
=
(
struct
async
*
)
obj
;
assert
(
obj
->
ops
==
&
async_ops
);
/* FIXME: this should be a function pointer */
return
serial_async_get_poll_events
(
ov
);
}
static
int
async_get_read_fd
(
struct
object
*
obj
)
{
struct
async
*
async
=
(
struct
async
*
)
obj
;
assert
(
obj
->
ops
==
&
async_ops
);
return
dup
(
async
->
obj
.
fd
);
}
static
int
async_get_write_fd
(
struct
object
*
obj
)
{
struct
async
*
async
=
(
struct
async
*
)
obj
;
assert
(
obj
->
ops
==
&
async_ops
);
return
dup
(
async
->
obj
.
fd
);
}
static
int
async_get_info
(
struct
object
*
obj
,
struct
get_file_info_request
*
req
)
{
assert
(
obj
->
ops
==
&
async_ops
);
req
->
type
=
FILE_TYPE_CHAR
;
req
->
attr
=
0
;
req
->
access_time
=
0
;
req
->
write_time
=
0
;
req
->
size_high
=
0
;
req
->
size_low
=
0
;
req
->
links
=
0
;
req
->
index_high
=
0
;
req
->
index_low
=
0
;
req
->
serial
=
0
;
return
1
;
}
/* data access functions */
int
async_type
(
struct
async
*
ov
)
{
return
ov
->
type
;
}
int
async_count
(
struct
async
*
ov
)
{
return
ov
->
count
;
}
int
async_get_eventmask
(
struct
async
*
ov
)
{
return
ov
->
eventmask
;
}
int
async_set_eventmask
(
struct
async
*
ov
,
int
eventmask
)
{
return
ov
->
eventmask
=
eventmask
;
}
DECL_HANDLER
(
create_async
)
{
struct
object
*
obj
;
struct
async
*
ov
=
NULL
;
int
fd
;
req
->
ov_handle
=
-
1
;
if
(
!
(
obj
=
get_handle_obj
(
current
->
process
,
req
->
file_handle
,
0
,
NULL
))
)
return
;
fd
=
dup
(
obj
->
fd
);
if
(
fd
<
0
)
{
release_object
(
obj
);
set_error
(
STATUS_UNSUCCESSFUL
);
return
;
}
if
(
0
>
fcntl
(
fd
,
F_SETFL
,
O_NONBLOCK
))
{
release_object
(
obj
);
set_error
(
STATUS_UNSUCCESSFUL
);
return
;
}
ov
=
alloc_object
(
&
async_ops
,
fd
);
if
(
!
ov
)
{
release_object
(
obj
);
set_error
(
STATUS_UNSUCCESSFUL
);
return
;
}
ov
->
client_overlapped
=
req
->
overlapped
;
ov
->
next
=
NULL
;
ov
->
timeout
=
NULL
;
ov
->
type
=
req
->
type
;
ov
->
thread
=
current
;
ov
->
func
=
req
->
func
;
ov
->
file
=
obj
;
ov
->
buffer
=
req
->
buffer
;
ov
->
count
=
req
->
count
;
/* FIXME: this should be a function pointer */
serial_async_setup
(
obj
,
ov
);
ov
->
obj
.
ops
->
add_queue
(
&
ov
->
obj
,
&
ov
->
wait
);
req
->
ov_handle
=
alloc_handle
(
current
->
process
,
ov
,
GENERIC_READ
|
GENERIC_WRITE
,
0
);
release_object
(
obj
);
}
/* handler for async poll() events */
static
void
async_poll_event
(
struct
object
*
obj
,
int
event
)
{
struct
async
*
ov
=
(
struct
async
*
)
obj
;
/* queue an APC in the client thread to do our dirty work */
ov
->
obj
.
ops
->
remove_queue
(
&
ov
->
obj
,
&
ov
->
wait
);
/* FIXME: this should be a function pointer */
event
=
serial_async_poll_event
(
obj
,
event
);
thread_queue_apc
(
ov
->
thread
,
NULL
,
ov
->
func
,
APC_ASYNC
,
3
,
ov
->
client_overlapped
,
ov
->
buffer
,
event
);
}
/* handler for async i/o timeouts */
static
void
overlapped_timeout
(
void
*
private
)
{
struct
async
*
ov
=
(
struct
async
*
)
private
;
ov
->
obj
.
ops
->
remove_queue
(
&
ov
->
obj
,
&
ov
->
wait
);
thread_queue_apc
(
ov
->
thread
,
NULL
,
ov
->
func
,
APC_ASYNC
,
3
,
ov
->
client_overlapped
,
ov
->
buffer
,
0
);
}
void
async_add_timeout
(
struct
async
*
ov
,
int
timeout
)
{
struct
timeval
tv
;
gettimeofday
(
&
tv
,
0
);
add_timeout
(
&
tv
,
timeout
);
ov
->
timeout
=
add_timeout_user
(
&
tv
,
overlapped_timeout
,
ov
);
}
DECL_HANDLER
(
async_result
)
{
struct
async
*
ov
;
if
((
ov
=
get_async_obj
(
current
->
process
,
req
->
ov_handle
,
0
)))
{
ov
->
result
=
req
->
result
;
if
(
ov
->
result
==
STATUS_PENDING
)
{
ov
->
obj
.
ops
->
add_queue
(
&
ov
->
obj
,
&
ov
->
wait
);
}
release_object
(
ov
);
}
}
server/object.h
View file @
1eac1911
...
...
@@ -25,6 +25,7 @@ struct thread;
struct
process
;
struct
file
;
struct
wait_queue_entry
;
struct
async
;
/* operations valid on all objects */
struct
object_ops
...
...
@@ -156,6 +157,20 @@ extern int create_anonymous_file(void);
extern
struct
file
*
create_temp_file
(
int
access
);
extern
void
file_set_error
(
void
);
/* async functions */
void
async_add_timeout
(
struct
async
*
ov
,
int
timeout
);
int
async_count
(
struct
async
*
ov
);
int
async_type
(
struct
async
*
ov
);
int
async_get_eventmask
(
struct
async
*
ov
);
int
async_set_eventmask
(
struct
async
*
ov
,
int
eventmask
);
/* serial functions */
int
serial_async_setup
(
struct
object
*
obj
,
struct
async
*
ov
);
int
serial_async_get_poll_events
(
struct
async
*
ov
);
int
serial_async_poll_event
(
struct
object
*
obj
,
int
event
);
/* console functions */
extern
int
alloc_console
(
struct
process
*
process
);
...
...
server/request.h
View file @
1eac1911
...
...
@@ -202,6 +202,8 @@ DECL_HANDLER(wait_input_idle);
DECL_HANDLER
(
create_serial
);
DECL_HANDLER
(
get_serial_info
);
DECL_HANDLER
(
set_serial_info
);
DECL_HANDLER
(
create_async
);
DECL_HANDLER
(
async_result
);
#ifdef WANT_REQUEST_HANDLERS
...
...
@@ -316,6 +318,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(
req_handler
)
req_create_serial
,
(
req_handler
)
req_get_serial_info
,
(
req_handler
)
req_set_serial_info
,
(
req_handler
)
req_create_async
,
(
req_handler
)
req_async_result
,
};
#endif
/* WANT_REQUEST_HANDLERS */
...
...
server/serial.c
View file @
1eac1911
...
...
@@ -182,6 +182,77 @@ static int serial_get_info( struct object *obj, struct get_file_info_request *re
return
1
;
}
/* these functions are for interaction with asynchronous i/o objects */
int
serial_async_setup
(
struct
object
*
obj
,
struct
async
*
ov
)
{
struct
serial
*
serial
=
(
struct
serial
*
)
obj
;
int
timeout
;
if
(
obj
->
ops
!=
&
serial_ops
)
return
0
;
switch
(
async_type
(
ov
))
{
case
ASYNC_TYPE_READ
:
timeout
=
serial
->
readconst
+
serial
->
readmult
*
async_count
(
ov
);
async_add_timeout
(
ov
,
timeout
);
async_set_eventmask
(
ov
,
EV_RXCHAR
);
break
;
case
ASYNC_TYPE_WRITE
:
timeout
=
serial
->
writeconst
+
serial
->
writemult
*
async_count
(
ov
);
async_add_timeout
(
ov
,
timeout
);
async_set_eventmask
(
ov
,
EV_TXEMPTY
);
break
;
case
ASYNC_TYPE_WAIT
:
async_set_eventmask
(
ov
,
serial
->
eventmask
);
break
;
}
return
1
;
}
int
serial_async_get_poll_events
(
struct
async
*
ov
)
{
int
events
=
0
,
mask
;
switch
(
async_type
(
ov
))
{
case
ASYNC_TYPE_READ
:
events
|=
POLLIN
;
break
;
case
ASYNC_TYPE_WRITE
:
events
|=
POLLOUT
;
break
;
case
ASYNC_TYPE_WAIT
:
/*
* FIXME: here is the spot to implement other WaitCommEvent flags
*/
mask
=
async_get_eventmask
(
ov
);
if
(
mask
&
EV_RXCHAR
)
events
|=
POLLIN
;
if
(
mask
&
EV_TXEMPTY
)
events
|=
POLLOUT
;
break
;
}
return
events
;
}
/* receive a select event, and output a windows event */
int
serial_async_poll_event
(
struct
object
*
obj
,
int
event
)
{
int
r
=
0
;
/*
* FIXME: here is the spot to implement other WaitCommEvent flags
*/
if
(
event
&
POLLIN
)
r
|=
EV_RXCHAR
;
if
(
event
&
POLLOUT
)
r
|=
EV_TXEMPTY
;
return
r
;
}
/* create a serial */
DECL_HANDLER
(
create_serial
)
{
...
...
server/trace.c
View file @
1eac1911
...
...
@@ -1455,6 +1455,27 @@ static void dump_set_serial_info_request( const struct set_serial_info_request *
fprintf
(
stderr
,
" commerror=%08x"
,
req
->
commerror
);
}
static
void
dump_create_async_request
(
const
struct
create_async_request
*
req
)
{
fprintf
(
stderr
,
" file_handle=%d,"
,
req
->
file_handle
);
fprintf
(
stderr
,
" overlapped=%p,"
,
req
->
overlapped
);
fprintf
(
stderr
,
" buffer=%p,"
,
req
->
buffer
);
fprintf
(
stderr
,
" count=%d,"
,
req
->
count
);
fprintf
(
stderr
,
" func=%p,"
,
req
->
func
);
fprintf
(
stderr
,
" type=%d"
,
req
->
type
);
}
static
void
dump_create_async_reply
(
const
struct
create_async_request
*
req
)
{
fprintf
(
stderr
,
" ov_handle=%d"
,
req
->
ov_handle
);
}
static
void
dump_async_result_request
(
const
struct
async_result_request
*
req
)
{
fprintf
(
stderr
,
" ov_handle=%d,"
,
req
->
ov_handle
);
fprintf
(
stderr
,
" result=%d"
,
req
->
result
);
}
static
const
dump_func
req_dumpers
[
REQ_NB_REQUESTS
]
=
{
(
dump_func
)
dump_new_process_request
,
(
dump_func
)
dump_wait_process_request
,
...
...
@@ -1564,6 +1585,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(
dump_func
)
dump_create_serial_request
,
(
dump_func
)
dump_get_serial_info_request
,
(
dump_func
)
dump_set_serial_info_request
,
(
dump_func
)
dump_create_async_request
,
(
dump_func
)
dump_async_result_request
,
};
static
const
dump_func
reply_dumpers
[
REQ_NB_REQUESTS
]
=
{
...
...
@@ -1675,6 +1698,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(
dump_func
)
dump_create_serial_reply
,
(
dump_func
)
dump_get_serial_info_reply
,
(
dump_func
)
0
,
(
dump_func
)
dump_create_async_reply
,
(
dump_func
)
0
,
};
static
const
char
*
const
req_names
[
REQ_NB_REQUESTS
]
=
{
...
...
@@ -1786,6 +1811,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"create_serial"
,
"get_serial_info"
,
"set_serial_info"
,
"create_async"
,
"async_result"
,
};
/* ### make_requests end ### */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment