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
5c8421d3
Commit
5c8421d3
authored
Jan 04, 2007
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
server: Add a generic apc_call structure to make it easier to extend, and more type-safe.
parent
49b49c30
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
190 additions
and
95 deletions
+190
-95
sync.c
dlls/ntdll/sync.c
+12
-16
thread.c
dlls/ntdll/thread.c
+9
-5
server_protocol.h
include/wine/server_protocol.h
+31
-12
fd.c
server/fd.c
+9
-2
named_pipe.c
server/named_pipe.c
+9
-2
protocol.def
server/protocol.def
+30
-11
thread.c
server/thread.c
+38
-31
thread.h
server/thread.h
+2
-3
timer.c
server/timer.c
+15
-3
trace.c
server/trace.c
+34
-10
make_requests
tools/make_requests
+1
-0
No files found.
dlls/ntdll/sync.c
View file @
5c8421d3
...
...
@@ -660,14 +660,11 @@ static int wait_reply( void *cookie )
static
void
call_apcs
(
BOOL
alertable
)
{
NTSTATUS
ret
;
apc_call_t
call
;
HANDLE
handle
=
0
;
FARPROC
proc
;
LARGE_INTEGER
time
;
void
*
arg1
,
*
arg2
,
*
arg3
;
for
(;;)
{
int
type
=
APC_NONE
;
SERVER_START_REQ
(
get_apc
)
{
req
->
alertable
=
alertable
;
...
...
@@ -675,34 +672,33 @@ static void call_apcs( BOOL alertable )
if
(
!
(
ret
=
wine_server_call
(
req
)))
{
handle
=
reply
->
handle
;
type
=
reply
->
type
;
proc
=
reply
->
func
;
arg1
=
reply
->
arg1
;
arg2
=
reply
->
arg2
;
arg3
=
reply
->
arg3
;
call
=
reply
->
call
;
}
}
SERVER_END_REQ
;
if
(
ret
)
return
;
/* no more APCs */
switch
(
type
)
switch
(
call
.
type
)
{
case
APC_USER
:
proc
(
arg1
,
arg2
,
arg3
);
call
.
user
.
func
(
call
.
user
.
args
[
0
],
call
.
user
.
args
[
1
],
call
.
user
.
args
[
2
]
);
break
;
case
APC_TIMER
:
{
LARGE_INTEGER
time
;
/* convert sec/usec to NT time */
RtlSecondsSince1970ToTime
(
(
time_t
)
arg1
,
&
time
);
time
.
QuadPart
+=
(
DWORD
)
arg2
*
10
;
proc
(
arg3
,
time
.
u
.
LowPart
,
time
.
u
.
HighPart
);
RtlSecondsSince1970ToTime
(
call
.
timer
.
time
.
sec
,
&
time
);
time
.
QuadPart
+=
call
.
timer
.
time
.
usec
*
10
;
call
.
timer
.
func
(
call
.
timer
.
arg
,
time
.
u
.
LowPart
,
time
.
u
.
HighPart
);
break
;
}
case
APC_ASYNC_IO
:
NtCurrentTeb
()
->
num_async_io
--
;
proc
(
arg1
,
(
IO_STATUS_BLOCK
*
)
arg2
,
(
ULONG
)
arg3
);
call
.
async_io
.
func
(
call
.
async_io
.
user
,
call
.
async_io
.
sb
,
call
.
async_io
.
status
);
break
;
default:
server_protocol_error
(
"get_apc_request: bad type %d
\n
"
,
type
);
server_protocol_error
(
"get_apc_request: bad type %d
\n
"
,
call
.
type
);
break
;
}
}
...
...
dlls/ntdll/thread.c
View file @
5c8421d3
...
...
@@ -638,11 +638,15 @@ NTSTATUS WINAPI NtQueueApcThread( HANDLE handle, PNTAPCFUNC func, ULONG_PTR arg1
SERVER_START_REQ
(
queue_apc
)
{
req
->
handle
=
handle
;
req
->
user
=
1
;
req
->
func
=
func
;
req
->
arg1
=
(
void
*
)
arg1
;
req
->
arg2
=
(
void
*
)
arg2
;
req
->
arg3
=
(
void
*
)
arg3
;
if
(
func
)
{
req
->
call
.
type
=
APC_USER
;
req
->
call
.
user
.
func
=
func
;
req
->
call
.
user
.
args
[
0
]
=
arg1
;
req
->
call
.
user
.
args
[
1
]
=
arg2
;
req
->
call
.
user
.
args
[
2
]
=
arg3
;
}
else
req
->
call
.
type
=
APC_NONE
;
/* wake up only */
ret
=
wine_server_call
(
req
);
}
SERVER_END_REQ
;
...
...
include/wine/server_protocol.h
View file @
5c8421d3
...
...
@@ -209,6 +209,34 @@ struct token_groups
};
enum
apc_type
{
APC_NONE
,
APC_USER
,
APC_TIMER
,
APC_ASYNC_IO
};
typedef
union
{
enum
apc_type
type
;
struct
{
enum
apc_type
type
;
void
(
__stdcall
*
func
)(
unsigned
long
,
unsigned
long
,
unsigned
long
);
unsigned
long
args
[
3
];
}
user
;
struct
{
enum
apc_type
type
;
void
(
__stdcall
*
func
)(
void
*
,
unsigned
int
,
unsigned
int
);
abs_time_t
time
;
void
*
arg
;
}
timer
;
struct
{
enum
apc_type
type
;
void
(
__stdcall
*
func
)(
void
*
,
void
*
,
unsigned
int
);
void
*
user
;
void
*
sb
;
unsigned
int
status
;
}
async_io
;
}
apc_call_t
;
...
...
@@ -512,11 +540,7 @@ struct queue_apc_request
{
struct
request_header
__header
;
obj_handle_t
handle
;
int
user
;
void
*
func
;
void
*
arg1
;
void
*
arg2
;
void
*
arg3
;
apc_call_t
call
;
};
struct
queue_apc_reply
{
...
...
@@ -535,13 +559,8 @@ struct get_apc_reply
{
struct
reply_header
__header
;
obj_handle_t
handle
;
void
*
func
;
int
type
;
void
*
arg1
;
void
*
arg2
;
void
*
arg3
;
apc_call_t
call
;
};
enum
apc_type
{
APC_NONE
,
APC_USER
,
APC_TIMER
,
APC_ASYNC_IO
};
...
...
@@ -4417,6 +4436,6 @@ union generic_reply
struct
query_symlink_reply
query_symlink_reply
;
};
#define SERVER_PROTOCOL_VERSION 26
2
#define SERVER_PROTOCOL_VERSION 26
3
#endif
/* __WINE_WINE_SERVER_PROTOCOL_H */
server/fd.c
View file @
5c8421d3
...
...
@@ -1283,8 +1283,15 @@ struct async
/* destroys the server side of it */
static
void
async_terminate
(
struct
async
*
async
,
int
status
)
{
thread_queue_apc
(
async
->
thread
,
NULL
,
async
->
apc
,
APC_ASYNC_IO
,
1
,
async
->
user
,
async
->
sb
,
(
void
*
)
status
);
apc_call_t
data
;
memset
(
&
data
,
0
,
sizeof
(
data
)
);
data
.
type
=
APC_ASYNC_IO
;
data
.
async_io
.
func
=
async
->
apc
;
data
.
async_io
.
user
=
async
->
user
;
data
.
async_io
.
sb
=
async
->
sb
;
data
.
async_io
.
status
=
status
;
thread_queue_apc
(
async
->
thread
,
NULL
,
&
data
);
if
(
async
->
timeout
)
remove_timeout_user
(
async
->
timeout
);
async
->
timeout
=
NULL
;
...
...
server/named_pipe.c
View file @
5c8421d3
...
...
@@ -857,9 +857,16 @@ DECL_HANDLER(wait_named_pipe)
server
=
find_server
(
pipe
,
ps_wait_open
);
if
(
server
)
{
apc_call_t
data
;
/* there's already a server waiting for a client to connect */
thread_queue_apc
(
current
,
NULL
,
req
->
func
,
APC_ASYNC_IO
,
1
,
req
->
event
,
NULL
,
(
void
*
)
STATUS_SUCCESS
);
memset
(
&
data
,
0
,
sizeof
(
data
)
);
data
.
type
=
APC_ASYNC_IO
;
data
.
async_io
.
func
=
req
->
func
;
data
.
async_io
.
user
=
req
->
event
;
data
.
async_io
.
sb
=
NULL
;
data
.
async_io
.
status
=
STATUS_SUCCESS
;
thread_queue_apc
(
current
,
NULL
,
&
data
);
release_object
(
server
);
}
else
...
...
server/protocol.def
View file @
5c8421d3
...
...
@@ -225,6 +225,34 @@ struct token_groups
/* VARARGS(sids,SID); */
};
enum apc_type { APC_NONE, APC_USER, APC_TIMER, APC_ASYNC_IO };
typedef union
{
enum apc_type type;
struct
{
enum apc_type type; /* APC_USER */
void (__stdcall *func)(unsigned long,unsigned long,unsigned long);
unsigned long args[3]; /* arguments for user function */
} user;
struct
{
enum apc_type type; /* APC_TIMER */
void (__stdcall *func)(void*, unsigned int, unsigned int);
abs_time_t time; /* absolute time of expiration */
void *arg; /* user argument */
} timer;
struct
{
enum apc_type type; /* APC_ASYNC_IO */
void (__stdcall *func)(void*, void*, unsigned int);
void *user; /* user pointer */
void *sb; /* status block */
unsigned int status; /* I/O status */
} async_io;
} apc_call_t;
/****************************************************************/
/* Request declarations */
...
...
@@ -436,11 +464,7 @@ struct token_groups
/* Queue an APC for a thread */
@REQ(queue_apc)
obj_handle_t handle; /* thread handle */
int user; /* user or system apc? */
void* func; /* function to call */
void* arg1; /* params for function to call */
void* arg2;
void* arg3;
apc_call_t call; /* call arguments */
@END
...
...
@@ -450,13 +474,8 @@ struct token_groups
obj_handle_t prev; /* handle to previous APC */
@REPLY
obj_handle_t handle; /* handle to APC */
void* func; /* function to call */
int type; /* function type */
void* arg1; /* function arguments */
void* arg2;
void* arg3;
apc_call_t call; /* call arguments */
@END
enum apc_type { APC_NONE, APC_USER, APC_TIMER, APC_ASYNC_IO };
/* Close a handle for the current process */
...
...
server/thread.c
View file @
5c8421d3
...
...
@@ -72,11 +72,7 @@ struct thread_apc
struct
list
entry
;
/* queue linked list */
struct
object
*
owner
;
/* object that queued this apc */
int
executed
;
/* has it been executed by the client? */
void
*
func
;
/* function to call in client */
enum
apc_type
type
;
/* type of apc function */
void
*
arg1
;
/* function arguments */
void
*
arg2
;
void
*
arg3
;
apc_call_t
call
;
};
static
void
dump_thread_apc
(
struct
object
*
obj
,
int
verbose
);
...
...
@@ -306,7 +302,7 @@ static void dump_thread_apc( struct object *obj, int verbose )
struct
thread_apc
*
apc
=
(
struct
thread_apc
*
)
obj
;
assert
(
obj
->
ops
==
&
thread_apc_ops
);
fprintf
(
stderr
,
"APC owner=%p type=%u
\n
"
,
apc
->
owner
,
apc
->
type
);
fprintf
(
stderr
,
"APC owner=%p type=%u
\n
"
,
apc
->
owner
,
apc
->
call
.
type
);
}
static
int
thread_apc_signaled
(
struct
object
*
obj
,
struct
thread
*
thread
)
...
...
@@ -663,24 +659,33 @@ void wake_up( struct object *obj, int max )
}
}
/* return the apc queue to use for a given apc type */
static
inline
struct
list
*
get_apc_queue
(
struct
thread
*
thread
,
enum
apc_type
type
)
{
switch
(
type
)
{
case
APC_NONE
:
case
APC_USER
:
case
APC_TIMER
:
return
&
thread
->
user_apc
;
default:
return
&
thread
->
system_apc
;
}
}
/* queue an async procedure call */
int
thread_queue_apc
(
struct
thread
*
thread
,
struct
object
*
owner
,
void
*
func
,
enum
apc_type
type
,
int
system
,
void
*
arg1
,
void
*
arg2
,
void
*
arg3
)
int
thread_queue_apc
(
struct
thread
*
thread
,
struct
object
*
owner
,
const
apc_call_t
*
call_data
)
{
struct
thread_apc
*
apc
;
struct
list
*
queue
=
system
?
&
thread
->
system_apc
:
&
thread
->
user_apc
;
struct
list
*
queue
=
get_apc_queue
(
thread
,
call_data
->
type
)
;
/* cancel a possible previous APC with the same owner */
if
(
owner
)
thread_cancel_apc
(
thread
,
owner
,
system
);
if
(
owner
)
thread_cancel_apc
(
thread
,
owner
,
call_data
->
type
);
if
(
thread
->
state
==
TERMINATED
)
return
0
;
if
(
!
(
apc
=
alloc_object
(
&
thread_apc_ops
)))
return
0
;
apc
->
owner
=
owner
;
apc
->
func
=
func
;
apc
->
type
=
type
;
apc
->
arg1
=
arg1
;
apc
->
arg2
=
arg2
;
apc
->
arg3
=
arg3
;
apc
->
call
=
*
call_data
;
apc
->
owner
=
owner
;
apc
->
executed
=
0
;
list_add_tail
(
queue
,
&
apc
->
entry
);
if
(
!
list_prev
(
queue
,
&
apc
->
entry
))
/* first one */
...
...
@@ -690,10 +695,11 @@ int thread_queue_apc( struct thread *thread, struct object *owner, void *func,
}
/* cancel the async procedure call owned by a specific object */
void
thread_cancel_apc
(
struct
thread
*
thread
,
struct
object
*
owner
,
int
system
)
void
thread_cancel_apc
(
struct
thread
*
thread
,
struct
object
*
owner
,
enum
apc_type
type
)
{
struct
thread_apc
*
apc
;
struct
list
*
queue
=
system
?
&
thread
->
system_apc
:
&
thread
->
user_apc
;
struct
list
*
queue
=
get_apc_queue
(
thread
,
type
);
LIST_FOR_EACH_ENTRY
(
apc
,
queue
,
struct
thread_apc
,
entry
)
{
if
(
apc
->
owner
!=
owner
)
continue
;
...
...
@@ -1053,8 +1059,16 @@ DECL_HANDLER(queue_apc)
struct
thread
*
thread
;
if
((
thread
=
get_thread_from_handle
(
req
->
handle
,
THREAD_SET_CONTEXT
)))
{
thread_queue_apc
(
thread
,
NULL
,
req
->
func
,
APC_USER
,
!
req
->
user
,
req
->
arg1
,
req
->
arg2
,
req
->
arg3
);
switch
(
req
->
call
.
type
)
{
case
APC_NONE
:
case
APC_USER
:
thread_queue_apc
(
thread
,
NULL
,
&
req
->
call
);
break
;
default
:
set_error
(
STATUS_INVALID_PARAMETER
);
break
;
}
release_object
(
thread
);
}
}
...
...
@@ -1082,22 +1096,15 @@ DECL_HANDLER(get_apc)
set_error
(
STATUS_PENDING
);
return
;
}
/* 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.
/* Optimization: ignore APC_NONE calls, they are only used to
* wake up a thread, but since we got here the thread woke up already.
*/
if
(
apc
->
func
||
apc
->
type
==
APC_ASYNC_IO
)
break
;
if
(
apc
->
call
.
type
!=
APC_NONE
)
break
;
release_object
(
apc
);
}
if
((
reply
->
handle
=
alloc_handle
(
current
->
process
,
apc
,
SYNCHRONIZE
,
0
)))
{
reply
->
func
=
apc
->
func
;
reply
->
type
=
apc
->
type
;
reply
->
arg1
=
apc
->
arg1
;
reply
->
arg2
=
apc
->
arg2
;
reply
->
arg3
=
apc
->
arg3
;
}
reply
->
call
=
apc
->
call
;
release_object
(
apc
);
}
...
...
server/thread.h
View file @
5c8421d3
...
...
@@ -112,9 +112,8 @@ extern void remove_queue( struct object *obj, struct wait_queue_entry *entry );
extern
void
kill_thread
(
struct
thread
*
thread
,
int
violent_death
);
extern
void
break_thread
(
struct
thread
*
thread
);
extern
void
wake_up
(
struct
object
*
obj
,
int
max
);
extern
int
thread_queue_apc
(
struct
thread
*
thread
,
struct
object
*
owner
,
void
*
func
,
enum
apc_type
type
,
int
system
,
void
*
arg1
,
void
*
arg2
,
void
*
arg3
);
extern
void
thread_cancel_apc
(
struct
thread
*
thread
,
struct
object
*
owner
,
int
system
);
extern
int
thread_queue_apc
(
struct
thread
*
thread
,
struct
object
*
owner
,
const
apc_call_t
*
call_data
);
extern
void
thread_cancel_apc
(
struct
thread
*
thread
,
struct
object
*
owner
,
enum
apc_type
type
);
extern
int
thread_add_inflight_fd
(
struct
thread
*
thread
,
int
client
,
int
server
);
extern
int
thread_get_inflight_fd
(
struct
thread
*
thread
,
int
client
);
extern
struct
thread_snapshot
*
thread_snap
(
int
*
count
);
...
...
server/timer.c
View file @
5c8421d3
...
...
@@ -104,8 +104,20 @@ static void timer_callback( void *private )
/* queue an APC */
if
(
timer
->
thread
)
{
if
(
!
thread_queue_apc
(
timer
->
thread
,
&
timer
->
obj
,
timer
->
callback
,
APC_TIMER
,
0
,
(
void
*
)
timer
->
when
.
tv_sec
,
(
void
*
)
timer
->
when
.
tv_usec
,
timer
->
arg
))
apc_call_t
data
;
memset
(
&
data
,
0
,
sizeof
(
data
)
);
if
(
timer
->
callback
)
{
data
.
type
=
APC_TIMER
;
data
.
timer
.
func
=
timer
->
callback
;
data
.
timer
.
time
.
sec
=
timer
->
when
.
tv_sec
;
data
.
timer
.
time
.
usec
=
timer
->
when
.
tv_usec
;
data
.
timer
.
arg
=
timer
->
arg
;
}
else
data
.
type
=
APC_NONE
;
/* wake up only */
if
(
!
thread_queue_apc
(
timer
->
thread
,
&
timer
->
obj
,
&
data
))
{
release_object
(
timer
->
thread
);
timer
->
thread
=
NULL
;
...
...
@@ -136,7 +148,7 @@ static int cancel_timer( struct timer *timer )
}
if
(
timer
->
thread
)
{
thread_cancel_apc
(
timer
->
thread
,
&
timer
->
obj
,
0
);
thread_cancel_apc
(
timer
->
thread
,
&
timer
->
obj
,
APC_TIMER
);
release_object
(
timer
->
thread
);
timer
->
thread
=
NULL
;
}
...
...
server/trace.c
View file @
5c8421d3
...
...
@@ -43,6 +43,8 @@
static
const
void
*
cur_data
;
static
data_size_t
cur_size
;
static
const
char
*
get_status_name
(
unsigned
int
status
);
/* utility functions */
inline
static
void
remove_data
(
data_size_t
size
)
...
...
@@ -96,6 +98,34 @@ static void dump_char_info( const char_info_t *info )
fprintf
(
stderr
,
"',%04x}"
,
info
->
attr
);
}
static
void
dump_apc_call
(
const
apc_call_t
*
call
)
{
fputc
(
'{'
,
stderr
);
switch
(
call
->
type
)
{
case
APC_NONE
:
fprintf
(
stderr
,
"APC_NONE"
);
break
;
case
APC_USER
:
fprintf
(
stderr
,
"APC_USER,args={%lx,%lx,%lx}"
,
call
->
user
.
args
[
0
],
call
->
user
.
args
[
1
],
call
->
user
.
args
[
2
]
);
break
;
case
APC_TIMER
:
fprintf
(
stderr
,
"APC_TIMER,time="
);
dump_abs_time
(
&
call
->
timer
.
time
);
fprintf
(
stderr
,
",arg=%p"
,
call
->
timer
.
arg
);
break
;
case
APC_ASYNC_IO
:
fprintf
(
stderr
,
"APC_ASYNC_IO,user=%p,sb=%p,status=%s"
,
call
->
async_io
.
user
,
call
->
async_io
.
sb
,
get_status_name
(
call
->
async_io
.
status
)
);
break
;
default:
fprintf
(
stderr
,
"type=%u"
,
call
->
type
);
break
;
}
fputc
(
'}'
,
stderr
);
}
static
void
dump_context
(
const
CONTEXT
*
context
)
{
#ifdef __i386__
...
...
@@ -845,11 +875,8 @@ static void dump_unload_dll_request( const struct unload_dll_request *req )
static
void
dump_queue_apc_request
(
const
struct
queue_apc_request
*
req
)
{
fprintf
(
stderr
,
" handle=%p,"
,
req
->
handle
);
fprintf
(
stderr
,
" user=%d,"
,
req
->
user
);
fprintf
(
stderr
,
" func=%p,"
,
req
->
func
);
fprintf
(
stderr
,
" arg1=%p,"
,
req
->
arg1
);
fprintf
(
stderr
,
" arg2=%p,"
,
req
->
arg2
);
fprintf
(
stderr
,
" arg3=%p"
,
req
->
arg3
);
fprintf
(
stderr
,
" call="
);
dump_apc_call
(
&
req
->
call
);
}
static
void
dump_get_apc_request
(
const
struct
get_apc_request
*
req
)
...
...
@@ -861,11 +888,8 @@ static void dump_get_apc_request( const struct get_apc_request *req )
static
void
dump_get_apc_reply
(
const
struct
get_apc_reply
*
req
)
{
fprintf
(
stderr
,
" handle=%p,"
,
req
->
handle
);
fprintf
(
stderr
,
" func=%p,"
,
req
->
func
);
fprintf
(
stderr
,
" type=%d,"
,
req
->
type
);
fprintf
(
stderr
,
" arg1=%p,"
,
req
->
arg1
);
fprintf
(
stderr
,
" arg2=%p,"
,
req
->
arg2
);
fprintf
(
stderr
,
" arg3=%p"
,
req
->
arg3
);
fprintf
(
stderr
,
" call="
);
dump_apc_call
(
&
req
->
call
);
}
static
void
dump_close_handle_request
(
const
struct
close_handle_request
*
req
)
...
...
tools/make_requests
View file @
5c8421d3
...
...
@@ -42,6 +42,7 @@ my %formats =
"abs_time_t"
=>
"&dump_abs_time"
,
"rectangle_t"
=>
"&dump_rectangle"
,
"char_info_t"
=>
"&dump_char_info"
,
"apc_call_t"
=>
"&dump_apc_call"
,
);
my
@requests
=
();
...
...
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