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
e5dedb19
Commit
e5dedb19
authored
Mar 08, 2001
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added support for nested server waits (to allow waiting in signal
handlers).
parent
5142150f
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
113 additions
and
62 deletions
+113
-62
server.h
include/server.h
+9
-1
thread.h
include/thread.h
+4
-4
client.c
scheduler/client.c
+6
-7
synchro.c
scheduler/synchro.c
+25
-9
thread.c
scheduler/thread.c
+4
-2
request.c
server/request.c
+0
-14
request.h
server/request.h
+7
-3
thread.c
server/thread.c
+57
-22
trace.c
server/trace.c
+1
-0
No files found.
include/server.h
View file @
e5dedb19
...
...
@@ -125,6 +125,13 @@ struct send_fd
int
fd
;
/* file descriptor on client-side */
};
/* structure sent by the server on the wait fifo */
struct
wake_up_reply
{
void
*
cookie
;
/* magic cookie that was passed in select_request */
int
signaled
;
/* wait result */
};
/* Create a new process from the context of the parent */
struct
new_process_request
{
...
...
@@ -425,6 +432,7 @@ struct select_request
{
REQUEST_HEADER
;
/* request header */
IN
int
flags
;
/* wait flags (see below) */
IN
void
*
cookie
;
/* magic cookie to return to client */
IN
int
sec
;
/* absolute timeout */
IN
int
usec
;
/* absolute timeout */
IN
VARARG
(
handles
,
handles
);
/* handles to select on */
...
...
@@ -1603,7 +1611,7 @@ union generic_request
struct
async_result_request
async_result
;
};
#define SERVER_PROTOCOL_VERSION 4
1
#define SERVER_PROTOCOL_VERSION 4
2
/* ### make_requests end ### */
/* Everything above this line is generated automatically by tools/make_requests */
...
...
include/thread.h
View file @
e5dedb19
...
...
@@ -97,13 +97,13 @@ typedef struct _TEB
unsigned
int
buffer_size
;
/* --3 208 Buffer size */
int
request_fd
;
/* --3 20c fd for sending server requests */
int
reply_fd
;
/* --3 210 fd for receiving server replies */
int
wait_fd
;
/* --3 214 fd for sleeping server requests */
void
*
debug_info
;
/* --3 21
8
Info for debugstr functions */
void
*
pthread_data
;
/* --3 2
1c
Data for pthread emulation */
int
wait_fd
[
2
];
/* --3 214 fd for sleeping server requests */
void
*
debug_info
;
/* --3 21
c
Info for debugstr functions */
void
*
pthread_data
;
/* --3 2
20
Data for pthread emulation */
/* here is plenty space for wine specific fields (don't forget to change pad6!!) */
/* the following are nt specific fields */
DWORD
pad6
[
6
30
];
/* --n 220
*/
DWORD
pad6
[
6
29
];
/* --n 224
*/
UNICODE_STRING
StaticUnicodeString
;
/* -2- bf8 used by advapi32 */
USHORT
StaticUnicodeBuffer
[
261
];
/* -2- c00 used by advapi32 */
DWORD
pad7
;
/* --n e0c */
...
...
scheduler/client.c
View file @
e5dedb19
...
...
@@ -638,22 +638,22 @@ void CLIENT_InitThread(void)
{
TEB
*
teb
=
NtCurrentTeb
();
int
version
,
ret
;
int
reply_pipe
[
2
]
,
wait_pipe
[
2
]
;
int
reply_pipe
[
2
];
/* ignore SIGPIPE so that we get a EPIPE error instead */
signal
(
SIGPIPE
,
SIG_IGN
);
/* create the server->client communication pipes */
if
(
pipe
(
reply_pipe
)
==
-
1
)
server_protocol_perror
(
"pipe"
);
if
(
pipe
(
wait_pipe
)
==
-
1
)
server_protocol_perror
(
"pipe"
);
if
(
pipe
(
teb
->
wait_fd
)
==
-
1
)
server_protocol_perror
(
"pipe"
);
wine_server_send_fd
(
reply_pipe
[
1
]
);
wine_server_send_fd
(
wait_pipe
[
1
]
);
wine_server_send_fd
(
teb
->
wait_fd
[
1
]
);
teb
->
reply_fd
=
reply_pipe
[
0
];
teb
->
wait_fd
=
wait_pipe
[
0
];
/* set close on exec flag */
fcntl
(
teb
->
reply_fd
,
F_SETFD
,
1
);
fcntl
(
teb
->
wait_fd
,
F_SETFD
,
1
);
fcntl
(
teb
->
wait_fd
[
0
],
F_SETFD
,
1
);
fcntl
(
teb
->
wait_fd
[
1
],
F_SETFD
,
1
);
SERVER_START_REQ
(
init_thread
)
{
...
...
@@ -661,7 +661,7 @@ void CLIENT_InitThread(void)
req
->
teb
=
teb
;
req
->
entry
=
teb
->
entry_point
;
req
->
reply_fd
=
reply_pipe
[
1
];
req
->
wait_fd
=
wait_pipe
[
1
];
req
->
wait_fd
=
teb
->
wait_fd
[
1
];
ret
=
SERVER_CALL
();
teb
->
pid
=
req
->
pid
;
teb
->
tid
=
req
->
tid
;
...
...
@@ -669,7 +669,6 @@ void CLIENT_InitThread(void)
if
(
req
->
boot
)
boot_thread_id
=
teb
->
tid
;
else
if
(
boot_thread_id
==
teb
->
tid
)
boot_thread_id
=
0
;
close
(
reply_pipe
[
1
]
);
close
(
wait_pipe
[
1
]
);
}
SERVER_END_REQ
;
...
...
scheduler/synchro.c
View file @
e5dedb19
...
...
@@ -40,18 +40,33 @@ inline static void get_timeout( struct timeval *when, int timeout )
*
* Wait for a reply on the waiting pipe of the current thread.
*/
static
int
wait_reply
(
void
)
static
int
wait_reply
(
void
*
cookie
)
{
int
signaled
;
struct
wake_up_reply
reply
;
for
(;;)
{
int
ret
=
read
(
NtCurrentTeb
()
->
wait_fd
,
&
signaled
,
sizeof
(
signaled
)
);
if
(
ret
==
sizeof
(
signaled
))
return
signaled
;
if
(
!
ret
)
break
;
if
(
ret
>
0
)
server_protocol_error
(
"partial wakeup read %d
\n
"
,
ret
);
int
ret
=
read
(
NtCurrentTeb
()
->
wait_fd
[
0
],
&
reply
,
sizeof
(
reply
)
);
if
(
ret
==
sizeof
(
reply
))
{
if
(
!
reply
.
cookie
)
break
;
/* thread got killed */
if
(
reply
.
cookie
==
cookie
)
return
reply
.
signaled
;
/* we stole another reply, wait for the real one */
signaled
=
wait_reply
(
cookie
);
/* and now put the wrong one back in the pipe */
for
(;;)
{
ret
=
write
(
NtCurrentTeb
()
->
wait_fd
[
1
],
&
reply
,
sizeof
(
reply
)
);
if
(
ret
==
sizeof
(
reply
))
break
;
if
(
ret
>=
0
)
server_protocol_error
(
"partial wakeup write %d
\n
"
,
ret
);
if
(
errno
==
EINTR
)
continue
;
server_protocol_perror
(
"wakeup write"
);
}
return
signaled
;
}
if
(
ret
>=
0
)
server_protocol_error
(
"partial wakeup read %d
\n
"
,
ret
);
if
(
errno
==
EINTR
)
continue
;
if
(
errno
==
EPIPE
)
break
;
server_protocol_perror
(
"read"
);
server_protocol_perror
(
"wakeup read"
);
}
/* the server closed the connection; time to die... */
SYSDEPS_ExitThread
(
0
);
...
...
@@ -161,7 +176,7 @@ DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
BOOL
wait_all
,
DWORD
timeout
,
BOOL
alertable
)
{
int
i
,
ret
;
int
i
,
ret
,
cookie
;
struct
timeval
tv
;
if
(
count
>
MAXIMUM_WAIT_OBJECTS
)
...
...
@@ -180,6 +195,7 @@ DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
int
*
data
=
server_data_ptr
(
req
);
req
->
flags
=
SELECT_INTERRUPTIBLE
;
req
->
cookie
=
&
cookie
;
req
->
sec
=
tv
.
tv_sec
;
req
->
usec
=
tv
.
tv_usec
;
for
(
i
=
0
;
i
<
count
;
i
++
)
data
[
i
]
=
handles
[
i
];
...
...
@@ -191,7 +207,7 @@ DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
ret
=
SERVER_CALL
();
}
SERVER_END_VAR_REQ
;
if
(
ret
==
STATUS_PENDING
)
ret
=
wait_reply
();
if
(
ret
==
STATUS_PENDING
)
ret
=
wait_reply
(
&
cookie
);
if
(
ret
!=
STATUS_USER_APC
)
break
;
call_apcs
(
alertable
);
if
(
alertable
)
break
;
...
...
scheduler/thread.c
View file @
e5dedb19
...
...
@@ -91,7 +91,8 @@ static BOOL THREAD_InitTEB( TEB *teb )
teb
->
exit_code
=
STILL_ACTIVE
;
teb
->
request_fd
=
-
1
;
teb
->
reply_fd
=
-
1
;
teb
->
wait_fd
=
-
1
;
teb
->
wait_fd
[
0
]
=
-
1
;
teb
->
wait_fd
[
1
]
=
-
1
;
teb
->
stack_top
=
(
void
*
)
~
0UL
;
teb
->
StaticUnicodeString
.
MaximumLength
=
sizeof
(
teb
->
StaticUnicodeBuffer
);
teb
->
StaticUnicodeString
.
Buffer
=
(
PWSTR
)
teb
->
StaticUnicodeBuffer
;
...
...
@@ -115,7 +116,8 @@ static void CALLBACK THREAD_FreeTEB( TEB *teb )
close
(
teb
->
request_fd
);
close
(
teb
->
reply_fd
);
close
(
teb
->
wait_fd
);
close
(
teb
->
wait_fd
[
0
]
);
close
(
teb
->
wait_fd
[
1
]
);
if
(
teb
->
stack_sel
)
FreeSelector16
(
teb
->
stack_sel
);
FreeSelector16
(
teb
->
teb_sel
);
if
(
teb
->
buffer
)
munmap
(
(
void
*
)
teb
->
buffer
,
teb
->
buffer_size
);
...
...
server/request.c
View file @
e5dedb19
...
...
@@ -277,20 +277,6 @@ int receive_fd( struct process *process )
return
-
1
;
}
/* send the wakeup signal to a thread */
int
send_thread_wakeup
(
struct
thread
*
thread
,
int
signaled
)
{
int
ret
=
write
(
thread
->
wait_fd
,
&
signaled
,
sizeof
(
signaled
)
);
if
(
ret
==
sizeof
(
signaled
))
return
0
;
if
(
ret
>=
0
)
fatal_protocol_error
(
thread
,
"partial wakeup write %d
\n
"
,
ret
);
else
if
(
errno
==
EPIPE
)
kill_thread
(
thread
,
0
);
/* normal death */
else
fatal_protocol_perror
(
thread
,
"write"
);
return
-
1
;
}
/* send an fd to a client */
int
send_client_fd
(
struct
process
*
process
,
int
fd
,
handle_t
handle
)
{
...
...
server/request.h
View file @
e5dedb19
...
...
@@ -24,15 +24,19 @@
#ifdef __GNUC__
extern
void
fatal_protocol_error
(
struct
thread
*
thread
,
const
char
*
err
,
...
)
__attribute__
((
format
(
printf
,
2
,
3
)));
extern
void
fatal_protocol_perror
(
struct
thread
*
thread
,
const
char
*
err
,
...
)
__attribute__
((
format
(
printf
,
2
,
3
)));
extern
void
fatal_error
(
const
char
*
err
,
...
)
__attribute__
((
noreturn
,
format
(
printf
,
1
,
2
)));
extern
void
fatal_perror
(
const
char
*
err
,
...
)
__attribute__
((
noreturn
,
format
(
printf
,
1
,
2
)));
#else
extern
void
fatal_protocol_error
(
struct
thread
*
thread
,
const
char
*
err
,
...
);
extern
void
fatal_protocol_perror
(
struct
thread
*
thread
,
const
char
*
err
,
...
);
extern
void
fatal_error
(
const
char
*
err
,
...
);
extern
void
fatal_perror
(
const
char
*
err
,
...
);
#endif
extern
void
fatal_error
(
const
char
*
err
,
...
)
WINE_NORETURN
;
extern
void
fatal_perror
(
const
char
*
err
,
...
)
WINE_NORETURN
;
extern
const
char
*
get_config_dir
(
void
);
extern
int
receive_fd
(
struct
process
*
process
);
extern
int
send_thread_wakeup
(
struct
thread
*
thread
,
int
signaled
);
extern
int
send_client_fd
(
struct
process
*
process
,
int
fd
,
handle_t
handle
);
extern
void
read_request
(
struct
thread
*
thread
);
extern
void
send_reply
(
struct
thread
*
thread
,
union
generic_request
*
request
);
...
...
server/thread.c
View file @
e5dedb19
...
...
@@ -7,6 +7,7 @@
#include "config.h"
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdarg.h>
...
...
@@ -32,8 +33,11 @@
struct
thread_wait
{
struct
thread_wait
*
next
;
/* next wait structure for this thread */
struct
thread
*
thread
;
/* owner thread */
int
count
;
/* count of objects */
int
flags
;
void
*
cookie
;
/* magic cookie to return to client */
struct
timeval
timeout
;
struct
timeout_user
*
user
;
struct
wait_queue_entry
queues
[
1
];
...
...
@@ -325,8 +329,8 @@ static void end_wait( struct thread *thread )
for
(
i
=
0
,
entry
=
wait
->
queues
;
i
<
wait
->
count
;
i
++
,
entry
++
)
entry
->
obj
->
ops
->
remove_queue
(
entry
->
obj
,
entry
);
if
(
wait
->
user
)
remove_timeout_user
(
wait
->
user
);
thread
->
wait
=
wait
->
next
;
free
(
wait
);
thread
->
wait
=
NULL
;
}
/* build the thread wait structure */
...
...
@@ -337,10 +341,12 @@ static int wait_on( int count, struct object *objects[], int flags, int sec, int
int
i
;
if
(
!
(
wait
=
mem_alloc
(
sizeof
(
*
wait
)
+
(
count
-
1
)
*
sizeof
(
*
entry
)
)))
return
0
;
current
->
wait
=
wait
;
wait
->
next
=
current
->
wait
;
wait
->
thread
=
current
;
wait
->
count
=
count
;
wait
->
flags
=
flags
;
wait
->
user
=
NULL
;
current
->
wait
=
wait
;
if
(
flags
&
SELECT_TIMEOUT
)
{
wait
->
timeout
.
tv_sec
=
sec
;
...
...
@@ -409,41 +415,68 @@ static int check_wait( struct thread *thread )
return
-
1
;
}
/* send the wakeup signal to a thread */
static
int
send_thread_wakeup
(
struct
thread
*
thread
,
void
*
cookie
,
int
signaled
)
{
struct
wake_up_reply
reply
;
int
ret
;
reply
.
cookie
=
cookie
;
reply
.
signaled
=
signaled
;
if
((
ret
=
write
(
thread
->
wait_fd
,
&
reply
,
sizeof
(
reply
)
))
==
sizeof
(
reply
))
return
0
;
if
(
ret
>=
0
)
fatal_protocol_error
(
thread
,
"partial wakeup write %d
\n
"
,
ret
);
else
if
(
errno
==
EPIPE
)
kill_thread
(
thread
,
0
);
/* normal death */
else
fatal_protocol_perror
(
thread
,
"write"
);
return
-
1
;
}
/* attempt to wake up a thread */
/* return
1
if OK, 0 if the wait condition is still not satisfied */
/* return
>0
if OK, 0 if the wait condition is still not satisfied */
static
int
wake_thread
(
struct
thread
*
thread
)
{
int
signaled
;
if
((
signaled
=
check_wait
(
thread
))
==
-
1
)
return
0
;
int
signaled
,
count
;
void
*
cookie
;
if
(
debug_level
)
fprintf
(
stderr
,
"%08x: *wakeup* object=%d
\n
"
,
(
unsigned
int
)
thread
,
signaled
);
end_wait
(
thread
);
send_thread_wakeup
(
thread
,
signaled
);
return
1
;
for
(
count
=
0
;
thread
->
wait
;
count
++
)
{
if
((
signaled
=
check_wait
(
thread
))
==
-
1
)
break
;
cookie
=
thread
->
wait
->
cookie
;
if
(
debug_level
)
fprintf
(
stderr
,
"%08x: *wakeup* signaled=%d cookie=%p
\n
"
,
(
unsigned
int
)
thread
,
signaled
,
cookie
);
end_wait
(
thread
);
send_thread_wakeup
(
thread
,
cookie
,
signaled
);
}
return
count
;
}
/* thread wait timeout */
static
void
thread_timeout
(
void
*
ptr
)
{
struct
thread
*
thread
=
ptr
;
struct
thread_wait
*
wait
=
ptr
;
struct
thread
*
thread
=
wait
->
thread
;
void
*
cookie
=
wait
->
cookie
;
if
(
debug_level
)
fprintf
(
stderr
,
"%08x: *timeout*
\n
"
,
(
unsigned
int
)
thread
);
wait
->
user
=
NULL
;
if
(
thread
->
wait
!=
wait
)
return
;
/* not the top-level wait, ignore it */
assert
(
thread
->
wait
);
thread
->
wait
->
user
=
NULL
;
if
(
debug_level
)
fprintf
(
stderr
,
"%08x: *wakeup* signaled=%d cookie=%p
\n
"
,
(
unsigned
int
)
thread
,
STATUS_TIMEOUT
,
cookie
)
;
end_wait
(
thread
);
send_thread_wakeup
(
thread
,
STATUS_TIMEOUT
);
send_thread_wakeup
(
thread
,
cookie
,
STATUS_TIMEOUT
);
/* check if other objects have become signaled in the meantime */
wake_thread
(
thread
);
}
/* select on a list of handles */
static
void
select_on
(
int
count
,
handle_t
*
handles
,
int
flags
,
int
sec
,
int
usec
)
static
void
select_on
(
int
count
,
void
*
cookie
,
handle_t
*
handles
,
int
flags
,
int
sec
,
int
usec
)
{
int
ret
,
i
;
struct
object
*
objects
[
MAXIMUM_WAIT_OBJECTS
];
assert
(
!
current
->
wait
);
if
((
count
<
0
)
||
(
count
>
MAXIMUM_WAIT_OBJECTS
))
{
set_error
(
STATUS_INVALID_PARAMETER
);
...
...
@@ -470,12 +503,13 @@ static void select_on( int count, handle_t *handles, int flags, int sec, int use
if
(
flags
&
SELECT_TIMEOUT
)
{
if
(
!
(
current
->
wait
->
user
=
add_timeout_user
(
&
current
->
wait
->
timeout
,
thread_timeout
,
current
)))
thread_timeout
,
current
->
wait
)))
{
end_wait
(
current
);
goto
done
;
}
}
current
->
wait
->
cookie
=
cookie
;
set_error
(
STATUS_PENDING
);
done:
...
...
@@ -527,7 +561,7 @@ int thread_queue_apc( struct thread *thread, struct object *owner, void *func,
if
(
!
apc
->
prev
)
/* first one */
{
queue
->
head
=
apc
;
if
(
thread
->
wait
)
wake_thread
(
thread
);
wake_thread
(
thread
);
}
return
1
;
}
...
...
@@ -661,7 +695,8 @@ void kill_thread( struct thread *thread, int violent_death )
(
unsigned
int
)
thread
,
thread
->
exit_code
);
if
(
thread
->
wait
)
{
end_wait
(
thread
);
while
(
thread
->
wait
)
end_wait
(
thread
);
send_thread_wakeup
(
thread
,
NULL
,
STATUS_PENDING
);
/* if it is waiting on the socket, we don't need to send a SIGTERM */
violent_death
=
0
;
}
...
...
@@ -886,7 +921,7 @@ DECL_HANDLER(resume_thread)
DECL_HANDLER
(
select
)
{
int
count
=
get_req_data_size
(
req
)
/
sizeof
(
int
);
select_on
(
count
,
get_req_data
(
req
),
req
->
flags
,
req
->
sec
,
req
->
usec
);
select_on
(
count
,
req
->
cookie
,
get_req_data
(
req
),
req
->
flags
,
req
->
sec
,
req
->
usec
);
}
/* queue an APC for a thread */
...
...
server/trace.c
View file @
e5dedb19
...
...
@@ -554,6 +554,7 @@ static void dump_open_process_reply( const struct open_process_request *req )
static
void
dump_select_request
(
const
struct
select_request
*
req
)
{
fprintf
(
stderr
,
" flags=%d,"
,
req
->
flags
);
fprintf
(
stderr
,
" cookie=%p,"
,
req
->
cookie
);
fprintf
(
stderr
,
" sec=%d,"
,
req
->
sec
);
fprintf
(
stderr
,
" usec=%d,"
,
req
->
usec
);
fprintf
(
stderr
,
" handles="
);
...
...
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