Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
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-winehq
Commits
1c32a46d
Commit
1c32a46d
authored
Mar 22, 2001
by
Michael McCormack
Committed by
Alexandre Julliard
Mar 22, 2001
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use poll() on the client-side during server waits to implement
overlapped I/O.
parent
a5a872ef
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
260 additions
and
424 deletions
+260
-424
comm.c
dlls/kernel/comm.c
+104
-68
file.c
files/file.c
+0
-0
file.h
include/file.h
+17
-0
server.h
include/server.h
+3
-18
thread.h
include/thread.h
+2
-1
synchro.c
scheduler/synchro.c
+123
-2
async.c
server/async.c
+2
-251
object.h
server/object.h
+1
-11
request.h
server/request.h
+0
-2
serial.c
server/serial.c
+7
-58
trace.c
server/trace.c
+1
-13
No files found.
dlls/kernel/comm.c
View file @
1c32a46d
...
...
@@ -50,6 +50,7 @@
#endif
#include <sys/ioctl.h>
#include <unistd.h>
#include <sys/poll.h>
#include "windef.h"
#ifdef HAVE_SYS_MODEM_H
...
...
@@ -2814,117 +2815,152 @@ BOOL WINAPI GetCommModemStatus(
#endif
}
VOID
COMM_WaitCommEventService
(
void
**
args
)
/***********************************************************************
* COMM_WaitCommEventService (INTERNAL)
*
* This function is called while the client is waiting on the
* server, so we can't make any server calls here.
*/
static
void
COMM_WaitCommEventService
(
async_private
*
ovp
,
int
events
)
{
LPOVERLAPPED
lpOverlapped
=
(
LPOVERLAPPED
)
args
[
0
];
LPDWORD
buffer
=
(
LPDWORD
)
args
[
1
];
DWORD
events
=
(
DWORD
)
args
[
2
];
LPOVERLAPPED
lpOverlapped
=
ovp
->
lpOverlapped
;
TRACE
(
"overlapped %p wait complete %p <- %lx
\n
"
,
lpOverlapped
,
buffer
,
events
);
if
(
buffer
)
*
buffer
=
events
;
TRACE
(
"overlapped %p wait complete %p <- %x
\n
"
,
lpOverlapped
,
ovp
->
buffer
,
events
);
if
(
events
&
POLLNVAL
)
{
lpOverlapped
->
Internal
=
STATUS_HANDLES_CLOSED
;
return
;
}
if
(
ovp
->
buffer
)
{
if
(
events
&
POLLIN
)
*
ovp
->
buffer
=
EV_RXCHAR
;
}
lpOverlapped
->
Internal
=
STATUS_SUCCESS
;
SetEvent
(
lpOverlapped
->
hEvent
);
CloseHandle
(
lpOverlapped
->
InternalHigh
);
}
/***********************************************************************
* 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
* COMM_WaitCommEvent (INTERNAL)
*
* BUGS:
* Only supports EV_RXCHAR and EV_TXEMPTY
* This function must have an lpOverlapped.
*/
BOOL
WINAPI
WaitCommEvent
(
static
BOOL
COMM_
WaitCommEvent
(
HANDLE
hFile
,
/* [in] handle of comm port to wait for */
LPDWORD
lpdwEvents
,
/* [out] event(s) that were detected */
LPOVERLAPPED
lpOverlapped
)
/* [in/out] for Asynchronous waiting */
{
OVERLAPPED
ov
;
LPOVERLAPPED
lpov
;
int
ret
;
int
fd
,
ret
;
async_private
*
ovp
;
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
)
)
{
ERR
(
"Couldn't create Event flag for Overlapped structure
\n
"
);
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
ResetEvent
(
lpov
->
hEvent
);
if
(
NtResetEvent
(
lpOverlapped
->
hEvent
,
NULL
))
return
FALSE
;
lp
ov
->
Internal
=
STATUS_PENDING
;
lp
ov
->
InternalHigh
=
0
;
lp
ov
->
Offset
=
0
;
lp
ov
->
OffsetHigh
=
0
;
lp
Overlapped
->
Internal
=
STATUS_PENDING
;
lp
Overlapped
->
InternalHigh
=
0
;
lp
Overlapped
->
Offset
=
0
;
lp
Overlapped
->
OffsetHigh
=
0
;
/* start an ASYNCHRONOUS WaitCommEvent */
SERVER_START_REQ
(
create_async
)
{
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_ERR
();
lpov
->
InternalHigh
=
req
->
ov_handle
;
}
SERVER_END_REQ
;
if
(
ret
)
if
(
ret
)
return
FALSE
;
fd
=
FILE_GetUnixHandle
(
hFile
,
GENERIC_WRITE
);
if
(
fd
<
0
)
return
FALSE
;
ovp
=
(
async_private
*
)
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
async_private
));
if
(
!
ovp
)
{
if
(
!
lpOverlapped
)
CloseHandle
(
lpov
->
hEvent
);
TRACE
(
"server call failed.
\n
"
);
close
(
fd
);
return
FALSE
;
}
ovp
->
lpOverlapped
=
lpOverlapped
;
ovp
->
timeout
=
0
;
ovp
->
tv
.
tv_sec
=
0
;
ovp
->
tv
.
tv_usec
=
0
;
ovp
->
event
=
POLLIN
;
ovp
->
func
=
COMM_WaitCommEventService
;
ovp
->
buffer
=
(
char
*
)
lpdwEvents
;
ovp
->
fd
=
fd
;
ovp
->
next
=
NtCurrentTeb
()
->
pending_list
;
ovp
->
prev
=
NULL
;
if
(
ovp
->
next
)
ovp
->
next
->
prev
=
ovp
;
NtCurrentTeb
()
->
pending_list
=
ovp
;
SetLastError
(
ERROR_IO_PENDING
);
return
FALSE
;
}
/* activate the overlapped operation */
lpov
->
Internal
=
STATUS_PENDING
;
/***********************************************************************
* 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
,
/* [in] handle of comm port to wait for */
LPDWORD
lpdwEvents
,
/* [out] event(s) that were detected */
LPOVERLAPPED
lpOverlapped
)
/* [in/out] for Asynchronous waiting */
{
OVERLAPPED
ov
;
int
ret
;
/* 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
TRACE
(
"(%x %p %p )
\n
"
,
hFile
,
lpdwEvents
,
lpOverlapped
);
if
(
lpOverlapped
)
return
COMM_WaitCommEvent
(
hFile
,
lpdwEvents
,
lpOverlapped
);
/* if there is no overlapped structure, create our own */
ov
.
hEvent
=
CreateEventA
(
NULL
,
FALSE
,
FALSE
,
NULL
);
COMM_WaitCommEvent
(
hFile
,
lpdwEvents
,
&
ov
);
if
(
GetLastError
()
!=
STATUS_PENDING
)
{
/* caller wants overlapped I/O using GetOverlapped result */
SetLastError
(
ERROR_IO_PENDING
);
CloseHandle
(
ov
.
hEvent
);
return
FALSE
;
}
return
TRUE
;
}
/* wait for the overlapped to complete */
ret
=
GetOverlappedResult
(
hFile
,
&
ov
,
NULL
,
TRUE
);
CloseHandle
(
ov
.
hEvent
);
return
ret
;
}
/***********************************************************************
* GetCommProperties (KERNEL32.286)
*
...
...
files/file.c
View file @
1c32a46d
This diff is collapsed.
Click to expand it.
include/file.h
View file @
1c32a46d
...
...
@@ -8,6 +8,7 @@
#define __WINE_FILE_H
#include <time.h>
/* time_t */
#include <sys/time.h>
#include "winbase.h"
#include "wine/windef16.h"
/* HFILE16 */
...
...
@@ -30,6 +31,22 @@ typedef struct
int
flags
;
}
DOS_DEVICE
;
/* overlapped private structure */
struct
async_private
;
typedef
void
(
*
async_handler
)(
struct
async_private
*
ovp
,
int
revents
);
typedef
struct
async_private
{
LPOVERLAPPED
lpOverlapped
;
int
fd
;
int
timeout
;
struct
timeval
tv
;
int
event
;
char
*
buffer
;
async_handler
func
;
struct
async_private
*
next
;
struct
async_private
*
prev
;
}
async_private
;
/* locale-independent case conversion */
inline
static
char
FILE_tolower
(
char
c
)
{
...
...
include/server.h
View file @
1c32a46d
...
...
@@ -1356,28 +1356,15 @@ struct set_serial_info_request
struct
create_async_request
{
REQUEST_HEADER
;
/* request header */
IN
handle_t
file_handle
;
/* handle to comm port */
IN
void
*
overlapped
;
IN
void
*
buffer
;
IN
handle_t
file_handle
;
/* handle to comm port, socket or file */
IN
int
count
;
IN
void
*
func
;
IN
int
type
;
OUT
handle_t
ov_handle
;
OUT
int
timeout
;
};
#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
handle_t
ov_handle
;
IN
int
result
;
/* NT status code */
};
/* Everything below this line is generated automatically by tools/make_requests */
/* ### make_requests begin ### */
...
...
@@ -1492,7 +1479,6 @@ enum request
REQ_get_serial_info
,
REQ_set_serial_info
,
REQ_create_async
,
REQ_async_result
,
REQ_NB_REQUESTS
};
...
...
@@ -1608,10 +1594,9 @@ union generic_request
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 4
3
#define SERVER_PROTOCOL_VERSION 4
4
/* ### make_requests end ### */
/* Everything above this line is generated automatically by tools/make_requests */
...
...
include/thread.h
View file @
1c32a46d
...
...
@@ -100,10 +100,11 @@ typedef struct _TEB
int
wait_fd
[
2
];
/* --3 214 fd for sleeping server requests */
void
*
debug_info
;
/* --3 21c Info for debugstr functions */
void
*
pthread_data
;
/* --3 220 Data for pthread emulation */
struct
async_private
*
pending_list
;
/* --3 224 list of pending async operations */
/* here is plenty space for wine specific fields (don't forget to change pad6!!) */
/* the following are nt specific fields */
DWORD
pad6
[
62
9
];
/* --n 224
*/
DWORD
pad6
[
62
8
];
/* --n 228
*/
UNICODE_STRING
StaticUnicodeString
;
/* -2- bf8 used by advapi32 */
USHORT
StaticUnicodeBuffer
[
261
];
/* -2- c00 used by advapi32 */
DWORD
pad7
;
/* --n e0c */
...
...
scheduler/synchro.c
View file @
1c32a46d
...
...
@@ -8,6 +8,7 @@
#include <errno.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/poll.h>
#include <unistd.h>
#include <string.h>
...
...
@@ -35,6 +36,125 @@ inline static void get_timeout( struct timeval *when, int timeout )
}
}
#define MAX_NUMBER_OF_FDS 20
static
inline
int
time_before
(
struct
timeval
*
t1
,
struct
timeval
*
t2
)
{
return
((
t1
->
tv_sec
<
t2
->
tv_sec
)
||
((
t1
->
tv_sec
==
t2
->
tv_sec
)
&&
(
t1
->
tv_usec
<
t2
->
tv_usec
)));
}
static
void
finish_async
(
async_private
*
ovp
)
{
/* remove it from the active list */
if
(
ovp
->
prev
)
ovp
->
prev
->
next
=
ovp
->
next
;
else
NtCurrentTeb
()
->
pending_list
=
ovp
->
next
;
if
(
ovp
->
next
)
ovp
->
next
->
prev
=
ovp
->
prev
;
ovp
->
next
=
NULL
;
ovp
->
prev
=
NULL
;
close
(
ovp
->
fd
);
NtSetEvent
(
ovp
->
lpOverlapped
->
hEvent
,
NULL
);
HeapFree
(
GetProcessHeap
(),
0
,
ovp
);
}
/***********************************************************************
* check_async_list
*
* Create a list of fds for poll to check while waiting on the server
* FIXME: this loop is too large, cut into smaller functions
* perhaps we could share/steal some of the code in server/select.c?
*/
static
void
check_async_list
(
void
)
{
/* FIXME: should really malloc these two arrays */
struct
pollfd
fds
[
MAX_NUMBER_OF_FDS
];
async_private
*
user
[
MAX_NUMBER_OF_FDS
],
*
tmp
;
int
i
,
n
,
r
,
timeout
;
async_private
*
ovp
,
*
timeout_user
;
struct
timeval
now
;
while
(
1
)
{
/* the first fd belongs to the server connection */
fds
[
0
].
events
=
POLLIN
;
fds
[
0
].
revents
=
0
;
fds
[
0
].
fd
=
NtCurrentTeb
()
->
wait_fd
[
0
];
ovp
=
NtCurrentTeb
()
->
pending_list
;
timeout
=
-
1
;
timeout_user
=
NULL
;
gettimeofday
(
&
now
,
NULL
);
for
(
n
=
1
;
ovp
&&
(
n
<
MAX_NUMBER_OF_FDS
);
ovp
=
tmp
)
{
tmp
=
ovp
->
next
;
if
(
ovp
->
lpOverlapped
->
Internal
!=
STATUS_PENDING
)
{
ovp
->
lpOverlapped
->
Internal
=
STATUS_UNSUCCESSFUL
;
finish_async
(
ovp
);
continue
;
}
if
(
ovp
->
timeout
&&
time_before
(
&
ovp
->
tv
,
&
now
))
{
ovp
->
lpOverlapped
->
Internal
=
STATUS_TIMEOUT
;
finish_async
(
ovp
);
continue
;
}
fds
[
n
].
fd
=
ovp
->
fd
;
fds
[
n
].
events
=
ovp
->
event
;
fds
[
n
].
revents
=
0
;
user
[
n
]
=
ovp
;
if
(
ovp
->
timeout
&&
(
(
!
timeout_user
)
||
time_before
(
&
ovp
->
tv
,
&
timeout_user
->
tv
)))
{
timeout
=
(
ovp
->
tv
.
tv_sec
-
now
.
tv_sec
)
*
1000
+
(
ovp
->
tv
.
tv_usec
-
now
.
tv_usec
)
/
1000
;
timeout_user
=
ovp
;
}
n
++
;
}
/* if there aren't any active asyncs return */
if
(
n
==
1
)
return
;
r
=
poll
(
fds
,
n
,
timeout
);
/* if there were any errors, return immediately */
if
(
(
r
<
0
)
||
(
fds
[
0
].
revents
==
POLLNVAL
)
)
return
;
if
(
r
==
0
)
{
timeout_user
->
lpOverlapped
->
Internal
=
STATUS_TIMEOUT
;
finish_async
(
timeout_user
);
continue
;
}
/* search for async operations that are ready */
for
(
i
=
1
;
i
<
n
;
i
++
)
{
if
(
fds
[
i
].
revents
)
user
[
i
]
->
func
(
user
[
i
],
fds
[
i
].
revents
);
if
(
user
[
i
]
->
lpOverlapped
->
Internal
!=
STATUS_PENDING
)
finish_async
(
user
[
i
]);
}
if
(
fds
[
0
].
revents
==
POLLIN
)
return
;
}
}
/***********************************************************************
* wait_reply
...
...
@@ -47,7 +167,9 @@ static int wait_reply( void *cookie )
struct
wake_up_reply
reply
;
for
(;;)
{
int
ret
=
read
(
NtCurrentTeb
()
->
wait_fd
[
0
],
&
reply
,
sizeof
(
reply
)
);
int
ret
;
if
(
NtCurrentTeb
()
->
pending_list
)
check_async_list
();
ret
=
read
(
NtCurrentTeb
()
->
wait_fd
[
0
],
&
reply
,
sizeof
(
reply
)
);
if
(
ret
==
sizeof
(
reply
))
{
if
(
!
reply
.
cookie
)
break
;
/* thread got killed */
...
...
@@ -105,7 +227,6 @@ static void call_apcs( BOOL alertable )
case
APC_NONE
:
return
;
/* no more APCs */
case
APC_ASYNC
:
proc
(
&
args
[
0
]
);
break
;
case
APC_USER
:
proc
(
args
[
0
]
);
...
...
server/async.c
View file @
1c32a46d
...
...
@@ -4,280 +4,31 @@
* 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
timeval
tv
;
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_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
void
overlapped_timeout
(
void
*
private
);
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_fd
,
/* get_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
,
handle_t
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_fd
(
struct
object
*
obj
)
{
struct
async
*
async
=
(
struct
async
*
)
obj
;
assert
(
obj
->
ops
==
&
async_ops
);
return
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
=
0
;
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
;
ov
->
tv
.
tv_sec
=
0
;
ov
->
tv
.
tv_usec
=
0
;
/* FIXME: check if this object is allowed to do overlapped I/O */
/* FIXME: this should be a function pointer */
serial_async_setup
(
obj
,
ov
);
if
(
ov
->
tv
.
tv_sec
||
ov
->
tv
.
tv_usec
)
{
ov
->
timeout
=
add_timeout_user
(
&
ov
->
tv
,
overlapped_timeout
,
ov
);
}
ov
->
obj
.
ops
->
add_queue
(
&
ov
->
obj
,
&
ov
->
wait
);
req
->
timeout
=
get_serial_async_timeout
(
obj
,
req
->
type
,
req
->
count
);
req
->
ov_handle
=
alloc_handle
(
current
->
process
,
ov
,
GENERIC_READ
|
GENERIC_WRITE
,
0
);
release_object
(
ov
);
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
);
if
(
ov
->
timeout
)
{
remove_timeout_user
(
ov
->
timeout
);
ov
->
timeout
=
NULL
;
}
/* FIXME: this should be a function pointer */
event
=
serial_async_poll_event
(
obj
,
event
);
thread_queue_apc
(
ov
->
thread
,
NULL
,
ov
->
func
,
APC_ASYNC
,
1
,
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
);
ov
->
timeout
=
NULL
;
thread_queue_apc
(
ov
->
thread
,
NULL
,
ov
->
func
,
APC_ASYNC
,
1
,
3
,
ov
->
client_overlapped
,
ov
->
buffer
,
0
);
}
void
async_add_timeout
(
struct
async
*
ov
,
int
timeout
)
{
if
(
timeout
)
{
gettimeofday
(
&
ov
->
tv
,
0
);
add_timeout
(
&
ov
->
tv
,
timeout
);
}
}
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
);
if
(
(
ov
->
tv
.
tv_sec
||
ov
->
tv
.
tv_usec
)
&&
!
ov
->
timeout
)
{
ov
->
timeout
=
add_timeout_user
(
&
ov
->
tv
,
overlapped_timeout
,
ov
);
}
}
release_object
(
ov
);
}
}
server/object.h
View file @
1c32a46d
...
...
@@ -153,19 +153,9 @@ 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
);
int
get_serial_async_timeout
(
struct
object
*
obj
,
int
type
,
int
count
);
/* console functions */
...
...
server/request.h
View file @
1c32a46d
...
...
@@ -176,7 +176,6 @@ 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
...
...
@@ -291,7 +290,6 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(
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 @
1c32a46d
...
...
@@ -173,76 +173,25 @@ 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
)
/* these function calculates the timeout for an async operation
on a serial port */
int
get_serial_async_timeout
(
struct
object
*
obj
,
int
type
,
int
count
)
{
struct
serial
*
serial
=
(
struct
serial
*
)
obj
;
int
timeout
;
if
(
obj
->
ops
!=
&
serial_ops
)
return
0
;
switch
(
async_type
(
ov
)
)
switch
(
type
)
{
case
ASYNC_TYPE_READ
:
timeout
=
serial
->
readconst
+
serial
->
readmult
*
async_count
(
ov
);
async_add_timeout
(
ov
,
timeout
);
async_set_eventmask
(
ov
,
EV_RXCHAR
);
break
;
return
serial
->
readconst
+
serial
->
readmult
*
count
;
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
serial
->
writeconst
+
serial
->
writemult
*
count
;
}
return
1
;
return
0
;
}
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 @
1c32a46d
...
...
@@ -1477,22 +1477,13 @@ static void dump_set_serial_info_request( const struct set_serial_info_request *
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
);
fprintf
(
stderr
,
" timeout=%d"
,
req
->
timeout
);
}
static
const
dump_func
req_dumpers
[
REQ_NB_REQUESTS
]
=
{
...
...
@@ -1604,7 +1595,6 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(
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
]
=
{
...
...
@@ -1716,7 +1706,6 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(
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
]
=
{
...
...
@@ -1828,7 +1817,6 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"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