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
ea1afcef
Commit
ea1afcef
authored
Aug 22, 2000
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added APC support in waitable timers.
parent
0baa4e0b
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
172 additions
and
82 deletions
+172
-82
server.h
include/server.h
+9
-6
winnt.h
include/winnt.h
+4
-0
synchro.c
scheduler/synchro.c
+29
-16
request.h
server/request.h
+2
-2
thread.c
server/thread.c
+83
-27
thread.h
server/thread.h
+7
-4
timer.c
server/timer.c
+25
-16
trace.c
server/trace.c
+13
-11
No files found.
include/server.h
View file @
ea1afcef
...
...
@@ -308,12 +308,15 @@ struct queue_apc_request
};
/* Get
list of
APC to call */
struct
get_apc
s
_request
/* Get
next
APC to call */
struct
get_apc_request
{
OUT
int
count
;
/* number of apcs */
OUT
void
*
apcs
[
1
];
/* async procedures to call */
OUT
void
*
func
;
/* function to call */
OUT
int
type
;
/* function type */
OUT
int
nb_args
;
/* number of arguments */
OUT
void
*
args
[
1
];
/* function arguments */
};
enum
apc_type
{
APC_NONE
,
APC_USER
,
APC_TIMER
};
/* Close a handle for the current process */
...
...
@@ -1212,7 +1215,7 @@ enum request
REQ_LOAD_DLL
,
REQ_UNLOAD_DLL
,
REQ_QUEUE_APC
,
REQ_GET_APC
S
,
REQ_GET_APC
,
REQ_CLOSE_HANDLE
,
REQ_GET_HANDLE_INFO
,
REQ_SET_HANDLE_INFO
,
...
...
@@ -1303,7 +1306,7 @@ enum request
REQ_NB_REQUESTS
};
#define SERVER_PROTOCOL_VERSION 1
6
#define SERVER_PROTOCOL_VERSION 1
7
/* ### make_requests end ### */
/* Everything above this line is generated automatically by tools/make_requests */
...
...
include/winnt.h
View file @
ea1afcef
...
...
@@ -2578,6 +2578,10 @@ typedef enum tagSID_NAME_USE {
#define MUTEX_MODIFY_STATE 0x0001
#define MUTEX_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x1)
#define TIMER_QUERY_STATE 0x0001
#define TIMER_MODIFY_STATE 0x0002
#define TIMER_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3)
#define PROCESS_TERMINATE 0x0001
#define PROCESS_CREATE_THREAD 0x0002
#define PROCESS_VM_OPERATION 0x0008
...
...
scheduler/synchro.c
View file @
ea1afcef
...
...
@@ -9,11 +9,13 @@
#include <sys/time.h>
#include <unistd.h>
#include "heap.h"
#include "file.h"
/* for DOSFS_UnixTimeToFileTime */
#include "thread.h"
#include "winerror.h"
#include "syslevel.h"
#include "server.h"
/***********************************************************************
* call_apcs
*
...
...
@@ -21,24 +23,35 @@
*/
static
void
call_apcs
(
void
)
{
#define MAX_APCS 16
int
i
;
void
*
buffer
[
MAX_APCS
*
2
];
int
count
;
struct
get_apcs_request
*
req
=
get_req_buffer
();
if
(
server_call
(
REQ_GET_APCS
)
||
!
req
->
count
)
return
;
assert
(
req
->
count
<=
MAX_APCS
);
/* make a copy of the request buffer... it may get trashed *
* when the apcs are called */
memcpy
(
buffer
,
req
->
apcs
,
req
->
count
*
2
*
sizeof
(
req
->
apcs
[
0
])
);
count
=
req
->
count
;
FARPROC
proc
;
struct
get_apc_request
*
req
=
get_req_buffer
();
for
(
i
=
0
;
i
<
count
*
2
;
i
+=
2
)
for
(
;;
)
{
PAPCFUNC
func
=
(
PAPCFUNC
)
buffer
[
i
];
if
(
func
)
func
(
(
ULONG_PTR
)
buffer
[
i
+
1
]
);
if
(
server_call
(
REQ_GET_APC
))
return
;
switch
(
req
->
type
)
{
case
APC_NONE
:
return
;
/* no more APCs */
case
APC_USER
:
if
((
proc
=
req
->
func
))
{
proc
(
req
->
args
[
0
]
);
}
break
;
case
APC_TIMER
:
if
((
proc
=
req
->
func
))
{
FILETIME
ft
;
/* convert sec/usec to NT time */
DOSFS_UnixTimeToFileTime
(
(
time_t
)
req
->
args
[
0
],
&
ft
,
(
DWORD
)
req
->
args
[
1
]
*
10
);
proc
(
req
->
args
[
2
],
ft
.
dwLowDateTime
,
ft
.
dwHighDateTime
);
}
break
;
default:
server_protocol_error
(
"get_apc_request: bad type %d
\n
"
,
req
->
type
);
break
;
}
}
}
...
...
server/request.h
View file @
ea1afcef
...
...
@@ -89,7 +89,7 @@ DECL_HANDLER(resume_thread);
DECL_HANDLER
(
load_dll
);
DECL_HANDLER
(
unload_dll
);
DECL_HANDLER
(
queue_apc
);
DECL_HANDLER
(
get_apc
s
);
DECL_HANDLER
(
get_apc
);
DECL_HANDLER
(
close_handle
);
DECL_HANDLER
(
get_handle_info
);
DECL_HANDLER
(
set_handle_info
);
...
...
@@ -202,7 +202,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(
req_handler
)
req_load_dll
,
(
req_handler
)
req_unload_dll
,
(
req_handler
)
req_queue_apc
,
(
req_handler
)
req_get_apc
s
,
(
req_handler
)
req_get_apc
,
(
req_handler
)
req_close_handle
,
(
req_handler
)
req_get_handle_info
,
(
req_handler
)
req_set_handle_info
,
...
...
server/thread.c
View file @
ea1afcef
...
...
@@ -9,6 +9,7 @@
#include <assert.h>
#include <fcntl.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
...
...
@@ -23,7 +24,6 @@
#include <unistd.h>
#include <stdarg.h>
#include "winbase.h"
#include "handle.h"
...
...
@@ -48,10 +48,14 @@ struct thread_wait
struct
thread_apc
{
void
*
func
;
/* function to call in client */
void
*
param
;
/* function param */
struct
thread_apc
*
next
;
/* queue linked list */
struct
thread_apc
*
prev
;
struct
object
*
owner
;
/* object that queued this apc */
void
*
func
;
/* function to call in client */
enum
apc_type
type
;
/* type of apc function */
int
nb_args
;
/* number of arguments */
void
*
args
[
1
];
/* function arguments */
};
#define MAX_THREAD_APC 16
/* Max outstanding APCs for a thread */
/* thread operations */
...
...
@@ -60,6 +64,7 @@ static void dump_thread( struct object *obj, int verbose );
static
int
thread_signaled
(
struct
object
*
obj
,
struct
thread
*
thread
);
extern
void
thread_poll_event
(
struct
object
*
obj
,
int
event
);
static
void
destroy_thread
(
struct
object
*
obj
);
static
struct
thread_apc
*
thread_dequeue_apc
(
struct
thread
*
thread
);
static
const
struct
object_ops
thread_ops
=
{
...
...
@@ -126,8 +131,8 @@ struct thread *create_thread( int fd, struct process *process )
thread
->
queue
=
NULL
;
thread
->
info
=
NULL
;
thread
->
wait
=
NULL
;
thread
->
apc
=
NULL
;
thread
->
apc_
count
=
0
;
thread
->
apc
_head
=
NULL
;
thread
->
apc_
tail
=
NULL
;
thread
->
error
=
0
;
thread
->
pass_fd
=
-
1
;
thread
->
state
=
RUNNING
;
...
...
@@ -179,6 +184,7 @@ void thread_poll_event( struct object *obj, int event )
/* destroy a thread when its refcount is 0 */
static
void
destroy_thread
(
struct
object
*
obj
)
{
struct
thread_apc
*
apc
;
struct
thread
*
thread
=
(
struct
thread
*
)
obj
;
assert
(
obj
->
ops
==
&
thread_ops
);
...
...
@@ -187,7 +193,7 @@ static void destroy_thread( struct object *obj )
if
(
thread
->
next
)
thread
->
next
->
prev
=
thread
->
prev
;
if
(
thread
->
prev
)
thread
->
prev
->
next
=
thread
->
next
;
else
first_thread
=
thread
->
next
;
if
(
thread
->
apc
)
free
(
thread
->
apc
);
while
((
apc
=
thread_dequeue_apc
(
thread
)))
free
(
apc
);
if
(
thread
->
info
)
release_object
(
thread
->
info
);
if
(
thread
->
queue
)
release_object
(
thread
->
queue
);
if
(
thread
->
buffer
!=
(
void
*
)
-
1
)
munmap
(
thread
->
buffer
,
MAX_REQUEST_LENGTH
);
...
...
@@ -399,7 +405,7 @@ static int check_wait( struct thread *thread, struct object **object )
}
other_checks:
if
((
wait
->
flags
&
SELECT_ALERTABLE
)
&&
thread
->
apc
)
return
STATUS_USER_APC
;
if
((
wait
->
flags
&
SELECT_ALERTABLE
)
&&
thread
->
apc
_head
)
return
STATUS_USER_APC
;
if
(
wait
->
flags
&
SELECT_TIMEOUT
)
{
struct
timeval
now
;
...
...
@@ -501,26 +507,67 @@ void wake_up( struct object *obj, int max )
}
/* queue an async procedure call */
static
int
thread_queue_apc
(
struct
thread
*
thread
,
void
*
func
,
void
*
param
)
int
thread_queue_apc
(
struct
thread
*
thread
,
struct
object
*
owner
,
void
*
func
,
enum
apc_type
type
,
int
nb_args
,
...
)
{
struct
thread_apc
*
apc
;
if
(
!
thread
->
apc
)
/* cancel a possible previous APC with the same owner */
if
(
owner
)
thread_cancel_apc
(
thread
,
owner
);
if
(
!
(
apc
=
mem_alloc
(
sizeof
(
*
apc
)
+
(
nb_args
-
1
)
*
sizeof
(
apc
->
args
[
0
])
)))
return
0
;
apc
->
prev
=
thread
->
apc_tail
;
apc
->
next
=
NULL
;
apc
->
owner
=
owner
;
apc
->
func
=
func
;
apc
->
type
=
type
;
apc
->
nb_args
=
nb_args
;
if
(
nb_args
)
{
if
(
!
(
thread
->
apc
=
mem_alloc
(
MAX_THREAD_APC
*
sizeof
(
*
apc
)
)))
return
0
;
thread
->
apc_count
=
0
;
int
i
;
va_list
args
;
va_start
(
args
,
nb_args
);
for
(
i
=
0
;
i
<
nb_args
;
i
++
)
apc
->
args
[
i
]
=
va_arg
(
args
,
void
*
);
va_end
(
args
);
}
else
if
(
thread
->
apc_count
>=
MAX_THREAD_APC
)
return
0
;
thread
->
apc
[
thread
->
apc_count
].
func
=
func
;
thread
->
apc
[
thread
->
apc_count
].
param
=
param
;
thread
->
apc_count
++
;
if
(
thread
->
wait
)
thread
->
apc_tail
=
apc
;
if
(
!
apc
->
prev
)
/* first one */
{
if
(
wake_thread
(
thread
))
send_reply
(
thread
);
thread
->
apc_head
=
apc
;
if
(
thread
->
wait
&&
wake_thread
(
thread
))
send_reply
(
thread
);
}
return
1
;
}
/* cancel the async procedure call owned by a specific object */
void
thread_cancel_apc
(
struct
thread
*
thread
,
struct
object
*
owner
)
{
struct
thread_apc
*
apc
;
for
(
apc
=
thread
->
apc_head
;
apc
;
apc
=
apc
->
next
)
{
if
(
apc
->
owner
!=
owner
)
continue
;
if
(
apc
->
next
)
apc
->
next
->
prev
=
apc
->
prev
;
else
thread
->
apc_tail
=
apc
->
prev
;
if
(
apc
->
prev
)
apc
->
prev
->
next
=
apc
->
next
;
else
thread
->
apc_head
=
apc
->
next
;
free
(
apc
);
return
;
}
}
/* remove the head apc from the queue; the returned pointer must be freed by the caller */
static
struct
thread_apc
*
thread_dequeue_apc
(
struct
thread
*
thread
)
{
struct
thread_apc
*
apc
=
thread
->
apc_head
;
if
(
apc
)
{
if
(
apc
->
next
)
apc
->
next
->
prev
=
NULL
;
else
thread
->
apc_tail
=
NULL
;
thread
->
apc_head
=
apc
->
next
;
}
return
apc
;
}
/* retrieve an LDT selector entry */
static
void
get_selector_entry
(
struct
thread
*
thread
,
int
entry
,
unsigned
int
*
base
,
unsigned
int
*
limit
,
...
...
@@ -749,20 +796,29 @@ DECL_HANDLER(queue_apc)
struct
thread
*
thread
;
if
((
thread
=
get_thread_from_handle
(
req
->
handle
,
THREAD_SET_CONTEXT
)))
{
thread_queue_apc
(
thread
,
req
->
func
,
req
->
param
);
thread_queue_apc
(
thread
,
NULL
,
req
->
func
,
APC_USER
,
1
,
req
->
param
);
release_object
(
thread
);
}
}
/* get
list of
APC to call */
DECL_HANDLER
(
get_apc
s
)
/* get
next
APC to call */
DECL_HANDLER
(
get_apc
)
{
if
((
req
->
count
=
current
->
apc_count
))
struct
thread_apc
*
apc
;
if
((
apc
=
thread_dequeue_apc
(
current
)))
{
req
->
func
=
apc
->
func
;
req
->
type
=
apc
->
type
;
req
->
nb_args
=
apc
->
nb_args
;
memcpy
(
req
->
args
,
apc
->
args
,
apc
->
nb_args
*
sizeof
(
req
->
args
[
0
])
);
free
(
apc
);
}
else
{
memcpy
(
req
->
apcs
,
current
->
apc
,
current
->
apc_count
*
sizeof
(
*
current
->
apc
)
);
free
(
current
->
apc
);
current
->
apc
=
NULL
;
current
->
apc_count
=
0
;
req
->
func
=
NULL
;
req
->
type
=
APC_NONE
;
req
->
nb_args
=
0
;
}
}
...
...
server/thread.h
View file @
ea1afcef
...
...
@@ -43,10 +43,10 @@ struct thread
struct
debug_ctx
*
debug_ctx
;
/* debugger context if this thread is a debugger */
struct
debug_event
*
debug_event
;
/* debug event being sent to debugger */
struct
msg_queue
*
queue
;
/* message queue */
struct
startup_info
*
info
;
/* startup info for child process */
struct
thread_wait
*
wait
;
/* current wait condition if sleeping */
struct
thread_apc
*
apc
;
/* list
of async procedure calls */
int
apc_count
;
/* number of outstanding APC
s */
struct
startup_info
*
info
;
/* startup info for child process */
struct
thread_wait
*
wait
;
/* current wait condition if sleeping */
struct
thread_apc
*
apc
_head
;
/* queue
of async procedure calls */
struct
thread_apc
*
apc_tail
;
/* queue of async procedure call
s */
int
error
;
/* current error code */
int
pass_fd
;
/* fd to pass to the client */
enum
run_state
state
;
/* running state */
...
...
@@ -90,6 +90,9 @@ extern void kill_thread( struct thread *thread, int violent_death );
extern
void
wake_up
(
struct
object
*
obj
,
int
max
);
extern
int
sleep_on
(
int
count
,
struct
object
*
objects
[],
int
flags
,
int
timeout
,
sleep_reply
func
);
extern
int
thread_queue_apc
(
struct
thread
*
thread
,
struct
object
*
owner
,
void
*
func
,
enum
apc_type
type
,
int
nb_args
,
...
);
extern
void
thread_cancel_apc
(
struct
thread
*
thread
,
struct
object
*
owner
);
extern
struct
thread_snapshot
*
thread_snap
(
int
*
count
);
/* ptrace functions */
...
...
server/timer.c
View file @
ea1afcef
...
...
@@ -10,14 +10,10 @@
#include <sys/time.h>
#include <sys/types.h>
#include "winnt.h"
#include "handle.h"
#include "request.h"
/* FIXME: check values and move to standard header */
#define TIMER_MODIFY_STATE 0x0001
#define TIMER_QUERY_STATE 0x0002
#define TIMER_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3)
struct
timer
{
struct
object
obj
;
/* object header */
...
...
@@ -26,6 +22,7 @@ struct timer
int
period
;
/* timer period in ms */
struct
timeval
when
;
/* next expiration */
struct
timeout_user
*
timeout
;
/* timeout user */
struct
thread
*
thread
;
/* thread that set the APC function */
void
*
callback
;
/* callback APC function */
void
*
arg
;
/* callback argument */
};
...
...
@@ -69,6 +66,7 @@ static struct timer *create_timer( const WCHAR *name, size_t len, int manual )
timer
->
when
.
tv_usec
=
0
;
timer
->
period
=
0
;
timer
->
timeout
=
NULL
;
timer
->
thread
=
NULL
;
}
}
return
timer
;
...
...
@@ -79,6 +77,11 @@ static void timer_callback( void *private )
{
struct
timer
*
timer
=
(
struct
timer
*
)
private
;
/* queue an APC */
if
(
timer
->
thread
)
thread_queue_apc
(
timer
->
thread
,
&
timer
->
obj
,
timer
->
callback
,
APC_TIMER
,
3
,
(
void
*
)
timer
->
when
.
tv_sec
,
(
void
*
)
timer
->
when
.
tv_usec
,
timer
->
arg
);
if
(
timer
->
period
)
/* schedule the next expiration */
{
add_timeout
(
&
timer
->
when
,
timer
->
period
);
...
...
@@ -91,16 +94,31 @@ static void timer_callback( void *private )
wake_up
(
&
timer
->
obj
,
0
);
}
/* cancel a running timer */
static
void
cancel_timer
(
struct
timer
*
timer
)
{
if
(
timer
->
timeout
)
{
remove_timeout_user
(
timer
->
timeout
);
timer
->
timeout
=
NULL
;
}
if
(
timer
->
thread
)
{
thread_cancel_apc
(
timer
->
thread
,
&
timer
->
obj
);
timer
->
thread
=
NULL
;
}
}
/* set the timer expiration and period */
static
void
set_timer
(
struct
timer
*
timer
,
int
sec
,
int
usec
,
int
period
,
void
*
callback
,
void
*
arg
)
{
cancel_timer
(
timer
);
if
(
timer
->
manual
)
{
period
=
0
;
/* period doesn't make any sense for a manual timer */
timer
->
signaled
=
0
;
}
if
(
timer
->
timeout
)
remove_timeout_user
(
timer
->
timeout
);
if
(
!
sec
&&
!
usec
)
{
/* special case: use now + period as first expiration */
...
...
@@ -115,19 +133,10 @@ static void set_timer( struct timer *timer, int sec, int usec, int period,
timer
->
period
=
period
;
timer
->
callback
=
callback
;
timer
->
arg
=
arg
;
if
(
callback
)
timer
->
thread
=
current
;
timer
->
timeout
=
add_timeout_user
(
&
timer
->
when
,
timer_callback
,
timer
);
}
/* cancel a running timer */
static
void
cancel_timer
(
struct
timer
*
timer
)
{
if
(
timer
->
timeout
)
{
remove_timeout_user
(
timer
->
timeout
);
timer
->
timeout
=
NULL
;
}
}
static
void
timer_dump
(
struct
object
*
obj
,
int
verbose
)
{
struct
timer
*
timer
=
(
struct
timer
*
)
obj
;
...
...
server/trace.c
View file @
ea1afcef
...
...
@@ -165,11 +165,11 @@ static void dump_varargs_select_request( const struct select_request *req )
dump_ints
(
req
->
handles
,
count
);
}
static
void
dump_varargs_get_apc
s_reply
(
const
struct
get_apcs
_request
*
req
)
static
void
dump_varargs_get_apc
_reply
(
const
struct
get_apc
_request
*
req
)
{
int
i
;
for
(
i
=
0
;
i
<
2
*
req
->
count
;
i
++
)
fprintf
(
stderr
,
"%c%p"
,
i
?
','
:
'{'
,
req
->
a
pc
s
[
i
]
);
for
(
i
=
0
;
i
<
req
->
nb_args
;
i
++
)
fprintf
(
stderr
,
"%c%p"
,
i
?
','
:
'{'
,
req
->
a
rg
s
[
i
]
);
fprintf
(
stderr
,
"}"
);
}
...
...
@@ -422,15 +422,17 @@ static void dump_queue_apc_request( const struct queue_apc_request *req )
fprintf
(
stderr
,
" param=%p"
,
req
->
param
);
}
static
void
dump_get_apc
s_request
(
const
struct
get_apcs
_request
*
req
)
static
void
dump_get_apc
_request
(
const
struct
get_apc
_request
*
req
)
{
}
static
void
dump_get_apc
s_reply
(
const
struct
get_apcs
_request
*
req
)
static
void
dump_get_apc
_reply
(
const
struct
get_apc
_request
*
req
)
{
fprintf
(
stderr
,
" count=%d,"
,
req
->
count
);
fprintf
(
stderr
,
" apcs="
);
dump_varargs_get_apcs_reply
(
req
);
fprintf
(
stderr
,
" func=%p,"
,
req
->
func
);
fprintf
(
stderr
,
" type=%d,"
,
req
->
type
);
fprintf
(
stderr
,
" nb_args=%d,"
,
req
->
nb_args
);
fprintf
(
stderr
,
" args="
);
dump_varargs_get_apc_reply
(
req
);
}
static
void
dump_close_handle_request
(
const
struct
close_handle_request
*
req
)
...
...
@@ -1394,7 +1396,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(
dump_func
)
dump_load_dll_request
,
(
dump_func
)
dump_unload_dll_request
,
(
dump_func
)
dump_queue_apc_request
,
(
dump_func
)
dump_get_apc
s
_request
,
(
dump_func
)
dump_get_apc_request
,
(
dump_func
)
dump_close_handle_request
,
(
dump_func
)
dump_get_handle_info_request
,
(
dump_func
)
dump_set_handle_info_request
,
...
...
@@ -1504,7 +1506,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(
dump_func
)
0
,
(
dump_func
)
0
,
(
dump_func
)
0
,
(
dump_func
)
dump_get_apc
s
_reply
,
(
dump_func
)
dump_get_apc_reply
,
(
dump_func
)
0
,
(
dump_func
)
dump_get_handle_info_reply
,
(
dump_func
)
0
,
...
...
@@ -1614,7 +1616,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"load_dll"
,
"unload_dll"
,
"queue_apc"
,
"get_apc
s
"
,
"get_apc"
,
"close_handle"
,
"get_handle_info"
,
"set_handle_info"
,
...
...
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