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
5016e921
Commit
5016e921
authored
Jan 07, 2002
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added support for cleaning up the TEB from inside the exiting thread.
parent
c77c4df3
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
170 additions
and
94 deletions
+170
-94
thread.h
include/thread.h
+7
-2
exception.h
include/wine/exception.h
+0
-1
selector.c
memory/selector.c
+20
-4
virtual.c
memory/virtual.c
+7
-1
client.c
scheduler/client.c
+6
-6
process.c
scheduler/process.c
+0
-3
synchro.c
scheduler/synchro.c
+1
-1
sysdeps.c
scheduler/sysdeps.c
+129
-76
No files found.
include/thread.h
View file @
5016e921
...
...
@@ -89,8 +89,7 @@ typedef struct _TEB
DWORD
unknown6
[
5
];
/* --n 1e8 Unknown */
/* The following are Wine-specific fields (NT: GDI stuff) */
DWORD
cleanup
;
/* --3 1fc Cleanup service handle */
DWORD
unused
[
3
];
/* --3 200 Was server buffer */
DWORD
unused
[
4
];
/* --3 1fc Was server buffer */
int
request_fd
;
/* --3 20c fd for sending server requests */
int
reply_fd
;
/* --3 210 fd for receiving server replies */
int
wait_fd
[
2
];
/* --3 214 fd for sleeping server requests */
...
...
@@ -132,5 +131,11 @@ extern TEB *THREAD_IdToTEB( DWORD id );
extern
int
SYSDEPS_SpawnThread
(
TEB
*
teb
);
extern
void
SYSDEPS_SetCurThread
(
TEB
*
teb
);
extern
void
SYSDEPS_ExitThread
(
int
status
)
WINE_NORETURN
;
extern
void
SYSDEPS_AbortThread
(
int
status
)
WINE_NORETURN
;
extern
void
SYSDEPS_SwitchToThreadStack
(
void
(
*
func
)(
void
)
)
WINE_NORETURN
;
/* signal handling */
extern
BOOL
SIGNAL_Init
(
void
);
extern
void
SIGNAL_Reset
(
void
);
#endif
/* __WINE_THREAD_H */
include/wine/exception.h
View file @
5016e921
...
...
@@ -179,7 +179,6 @@ extern void __wine_enter_vm86( CONTEXT *context );
#ifdef __WINE__
extern
void
WINAPI
EXC_RtlRaiseException
(
PEXCEPTION_RECORD
,
PCONTEXT
);
extern
BOOL
SIGNAL_Init
(
void
);
#endif
#endif
/* __WINE_WINE_EXCEPTION_H */
memory/selector.c
View file @
5016e921
...
...
@@ -27,6 +27,8 @@ inline static WORD get_sel_count( WORD sel )
return
(
wine_ldt_copy
.
limit
[
sel
>>
__AHSHIFT
]
>>
16
)
+
1
;
}
static
const
LDT_ENTRY
null_entry
;
/* all-zeros, used to clear LDT entries */
/***********************************************************************
* SELECTOR_AllocArray
*
...
...
@@ -98,8 +100,6 @@ WORD WINAPI AllocSelector16( WORD sel )
*/
WORD
WINAPI
FreeSelector16
(
WORD
sel
)
{
LDT_ENTRY
entry
;
if
(
IS_SELECTOR_FREE
(
sel
))
return
sel
;
/* error */
#ifdef __i386__
...
...
@@ -112,14 +112,30 @@ WORD WINAPI FreeSelector16( WORD sel )
if
(
!
((
__get_gs
()
^
sel
)
&
~
7
))
__set_gs
(
0
);
#endif
/* __i386__ */
memset
(
&
entry
,
0
,
sizeof
(
entry
)
);
/* clear the LDT entries */
wine_ldt_set_entry
(
sel
,
&
entry
);
wine_ldt_set_entry
(
sel
,
&
null_entry
);
wine_ldt_copy
.
flags
[
sel
>>
__AHSHIFT
]
&=
~
WINE_LDT_FLAGS_ALLOCATED
;
return
0
;
}
/***********************************************************************
* SELECTOR_FreeFs
*
* Free the current %fs selector.
*/
void
SELECTOR_FreeFs
(
void
)
{
WORD
fs
=
__get_fs
();
if
(
fs
)
{
wine_ldt_copy
.
flags
[
fs
>>
__AHSHIFT
]
&=
~
WINE_LDT_FLAGS_ALLOCATED
;
__set_fs
(
0
);
wine_ldt_set_entry
(
fs
,
&
null_entry
);
}
}
/***********************************************************************
* SELECTOR_SetEntries
*
* Set the LDT entries for an array of selectors.
...
...
memory/virtual.c
View file @
5016e921
...
...
@@ -958,7 +958,13 @@ BOOL WINAPI VirtualFree(
return
FALSE
;
}
/* Compute the protection flags */
/* Check the type */
if
(
type
&
MEM_SYSTEM
)
{
view
->
flags
|=
VFLAG_SYSTEM
;
type
&=
~
MEM_SYSTEM
;
}
if
((
type
!=
MEM_DECOMMIT
)
&&
(
type
!=
MEM_RELEASE
))
{
...
...
scheduler/client.c
View file @
5016e921
...
...
@@ -98,7 +98,7 @@ void server_protocol_error( const char *err, ... )
fprintf
(
stderr
,
"wine client error:%p: "
,
NtCurrentTeb
()
->
tid
);
vfprintf
(
stderr
,
err
,
args
);
va_end
(
args
);
SYSDEPS_
Exi
tThread
(
1
);
SYSDEPS_
Abor
tThread
(
1
);
}
...
...
@@ -109,7 +109,7 @@ void server_protocol_perror( const char *err )
{
fprintf
(
stderr
,
"wine client error:%p: "
,
NtCurrentTeb
()
->
tid
);
perror
(
err
);
SYSDEPS_
Exi
tThread
(
1
);
SYSDEPS_
Abor
tThread
(
1
);
}
...
...
@@ -144,7 +144,7 @@ static void send_request( const struct __server_request_info *req )
}
if
(
ret
>=
0
)
server_protocol_error
(
"partial write %d
\n
"
,
ret
);
if
(
errno
==
EPIPE
)
SYSDEPS_
Exi
tThread
(
0
);
if
(
errno
==
EPIPE
)
SYSDEPS_
Abor
tThread
(
0
);
server_protocol_perror
(
"sendmsg"
);
}
...
...
@@ -172,7 +172,7 @@ static void read_reply_data( void *buffer, size_t size )
server_protocol_perror
(
"read"
);
}
/* the server closed the connection; time to die... */
SYSDEPS_
Exi
tThread
(
0
);
SYSDEPS_
Abor
tThread
(
0
);
}
...
...
@@ -252,7 +252,7 @@ void wine_server_send_fd( int fd )
if
((
ret
=
sendmsg
(
fd_socket
,
&
msghdr
,
0
))
==
sizeof
(
data
))
return
;
if
(
ret
>=
0
)
server_protocol_error
(
"partial write %d
\n
"
,
ret
);
if
(
errno
==
EINTR
)
continue
;
if
(
errno
==
EPIPE
)
SYSDEPS_
Exi
tThread
(
0
);
if
(
errno
==
EPIPE
)
SYSDEPS_
Abor
tThread
(
0
);
server_protocol_perror
(
"sendmsg"
);
}
}
...
...
@@ -311,7 +311,7 @@ static int receive_fd( handle_t *handle )
server_protocol_perror
(
"recvmsg"
);
}
/* the server closed the connection; time to die... */
SYSDEPS_
Exi
tThread
(
0
);
SYSDEPS_
Abor
tThread
(
0
);
}
...
...
scheduler/process.c
View file @
5016e921
...
...
@@ -109,9 +109,6 @@ extern STARTUPINFOA current_startupinfo;
/* scheduler/pthread.c */
extern
void
PTHREAD_init_done
(
void
);
/* scheduler/sysdeps.c */
extern
void
SYSDEPS_SwitchToThreadStack
(
void
(
*
func
)(
void
)
)
WINE_NORETURN
;
extern
BOOL
MAIN_MainInit
(
void
);
typedef
WORD
WINAPI
(
*
pUserSignalProc
)(
UINT
,
DWORD
,
DWORD
,
HMODULE16
);
...
...
scheduler/synchro.c
View file @
5016e921
...
...
@@ -140,7 +140,7 @@ static int wait_reply( void *cookie )
server_protocol_perror
(
"wakeup read"
);
}
/* the server closed the connection; time to die... */
SYSDEPS_
Exi
tThread
(
0
);
SYSDEPS_
Abor
tThread
(
0
);
}
...
...
scheduler/sysdeps.c
View file @
5016e921
...
...
@@ -21,9 +21,13 @@
#ifdef HAVE_UCONTEXT_H
# include <ucontext.h>
#endif
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#include "thread.h"
#include "wine/server.h"
#include "winbase.h"
#include "wine/winbase16.h"
#include "wine/exception.h"
#include "debugtools.h"
...
...
@@ -42,6 +46,21 @@ DEFAULT_DEBUG_CHANNEL(thread);
# endif
/* CLONE_VM */
#endif
/* linux || HAVE_CLONE */
extern
void
SELECTOR_FreeFs
(
void
);
struct
thread_cleanup_info
{
void
*
stack_base
;
int
stack_size
;
int
status
;
};
/* temporary stacks used on thread exit */
#define TEMP_STACK_SIZE 1024
#define NB_TEMP_STACKS 8
static
char
temp_stacks
[
NB_TEMP_STACKS
][
TEMP_STACK_SIZE
];
static
LONG
next_temp_stack
;
/* next temp stack to use */
/***********************************************************************
* SYSDEPS_SetCurThread
*
...
...
@@ -58,6 +77,58 @@ void SYSDEPS_SetCurThread( TEB *teb )
#endif
}
/***********************************************************************
* call_on_thread_stack
*
* Call a function once we switched to the thread stack.
*/
static
void
call_on_thread_stack
(
void
*
func
)
{
__TRY
{
void
(
*
funcptr
)(
void
)
=
func
;
funcptr
();
}
__EXCEPT
(
UnhandledExceptionFilter
)
{
TerminateThread
(
GetCurrentThread
(),
GetExceptionCode
()
);
}
__ENDTRY
SYSDEPS_ExitThread
(
0
);
/* should never get here */
}
/***********************************************************************
* get_temp_stack
*
* Get a temporary stack address to run the thread exit code on.
*/
inline
static
char
*
get_temp_stack
(
void
)
{
unsigned
int
next
=
InterlockedExchangeAdd
(
&
next_temp_stack
,
1
);
return
temp_stacks
[
next
%
NB_TEMP_STACKS
];
}
/***********************************************************************
* cleanup_thread
*
* Cleanup the remains of a thread. Runs on a temporary stack.
*/
static
void
cleanup_thread
(
void
*
ptr
)
{
/* copy the info structure since it is on the stack we will free */
struct
thread_cleanup_info
info
=
*
(
struct
thread_cleanup_info
*
)
ptr
;
munmap
(
info
.
stack_base
,
info
.
stack_size
);
SELECTOR_FreeFs
();
#ifdef HAVE__LWP_CREATE
_lwp_exit
();
#endif
_exit
(
info
.
status
);
}
/***********************************************************************
* SYSDEPS_StartThread
*
...
...
@@ -138,105 +209,87 @@ int SYSDEPS_SpawnThread( TEB *teb )
}
/***********************************************************************
* SYSDEPS_ExitThread
*
* Exit a running thread; must not return.
*/
void
SYSDEPS_ExitThread
(
int
status
)
{
int
fd
=
NtCurrentTeb
()
->
request_fd
;
NtCurrentTeb
()
->
request_fd
=
-
1
;
close
(
fd
);
#ifdef HAVE__LWP_CREATE
_lwp_exit
();
#endif
_exit
(
status
);
/*
* It is of course impossible to come here,
* but it eliminates a compiler warning.
*/
exit
(
status
);
}
/***********************************************************************
* SYSDEPS_CallOnStack
*/
int
SYSDEPS_DoCallOnStack
(
int
(
*
func
)(
LPVOID
),
LPVOID
arg
)
{
int
retv
=
0
;
__TRY
{
retv
=
func
(
arg
);
}
__EXCEPT
(
UnhandledExceptionFilter
)
{
TerminateThread
(
GetCurrentThread
(),
GetExceptionCode
()
);
return
0
;
}
__ENDTRY
return
retv
;
}
void
SYSDEPS_CallOnStack
(
void
(
*
func
)(
LPVOID
),
LPVOID
arg
)
WINE_NORETURN
;
#ifdef __i386__
int
SYSDEPS_CallOnStack
(
LPVOID
stackTop
,
LPVOID
stackLow
,
int
(
*
func
)(
LPVOID
),
LPVOID
arg
);
__ASM_GLOBAL_FUNC
(
SYSDEPS_CallOnStack
,
"pushl %ebp
\n\t
"
"movl %esp, %ebp
\n\t
"
".byte 0x64; pushl 0x04
\n\t
"
".byte 0x64; pushl 0x08
\n\t
"
"movl 8(%ebp), %esp
\n\t
"
"movl 12(%ebp), %eax
\n\t
"
".byte 0x64; movl %esp, 0x04
\n\t
"
".byte 0x64; movl %eax, 0x08
\n\t
"
"pushl 20(%ebp)
\n\t
"
"pushl 16(%ebp)
\n\t
"
"call "
__ASM_NAME
(
"SYSDEPS_DoCallOnStack"
)
"
\n\t
"
"leal -8(%ebp), %esp
\n\t
"
".byte 0x64; popl 0x08
\n\t
"
".byte 0x64; popl 0x04
\n\t
"
"popl %ebp
\n\t
"
"ret"
);
"movl 4(%esp),%ecx
\n\t
"
/* func */
"movl 8(%esp),%edx
\n\t
"
/* arg */
".byte 0x64
\n\t
movl 0x04,%esp
\n\t
"
/* teb->stack_top */
"pushl %edx
\n\t
"
"xorl %ebp,%ebp
\n\t
"
"call *%ecx
\n\t
"
"int $3"
/* we never return here */
);
#else
int
SYSDEPS_CallOnStack
(
LPVOID
stackTop
,
LPVOID
stackLow
,
int
(
*
func
)(
LPVOID
),
LPVOID
arg
)
void
SYSDEPS_CallOnStack
(
void
(
*
func
)(
LPVOID
),
LPVOID
arg
)
{
return
SYSDEPS_DoCallOnStack
(
func
,
arg
);
func
(
arg
);
while
(
1
);
/* avoid warning */
}
#endif
/***********************************************************************
* SYSDEPS_SwitchToThreadStack
*/
void
SYSDEPS_SwitchToThreadStack
(
void
(
*
func
)(
void
)
)
{
DWORD
page_size
=
getpagesize
();
void
*
cur_stack
=
(
void
*
)(((
ULONG_PTR
)
&
func
+
(
page_size
-
1
))
&
~
(
page_size
-
1
));
SYSDEPS_CallOnStack
(
call_on_thread_stack
,
func
);
}
/***********************************************************************
* SYSDEPS_ExitThread
*
* Exit a running thread; must not return.
*/
void
SYSDEPS_ExitThread
(
int
status
)
{
TEB
*
teb
=
NtCurrentTeb
();
LPVOID
stackTop
=
teb
->
stack_top
;
LPVOID
stackLow
=
teb
->
stack_low
;
struct
thread_cleanup_info
info
;
MEMORY_BASIC_INFORMATION
meminfo
;
struct
rlimit
rl
;
FreeSelector16
(
teb
->
stack_sel
);
VirtualQuery
(
teb
->
stack_top
,
&
meminfo
,
sizeof
(
meminfo
)
);
info
.
stack_base
=
meminfo
.
AllocationBase
;
info
.
stack_size
=
meminfo
.
RegionSize
+
((
char
*
)
teb
->
stack_top
-
(
char
*
)
meminfo
.
AllocationBase
);
info
.
status
=
status
;
if
(
getrlimit
(
RLIMIT_STACK
,
&
rl
)
<
0
)
{
WARN
(
"Can't get rlimit
\n
"
);
rl
.
rlim_cur
=
8
*
1024
*
1024
;
}
SIGNAL_Reset
();
VirtualFree
(
teb
->
stack_base
,
0
,
MEM_RELEASE
|
MEM_SYSTEM
);
close
(
teb
->
wait_fd
[
0
]
);
close
(
teb
->
wait_fd
[
1
]
);
close
(
teb
->
reply_fd
);
close
(
teb
->
request_fd
);
teb
->
stack_low
=
get_temp_stack
();
teb
->
stack_top
=
teb
->
stack_low
+
TEMP_STACK_SIZE
;
SYSDEPS_CallOnStack
(
cleanup_thread
,
&
info
);
}
teb
->
stack_top
=
cur_stack
;
teb
->
stack_low
=
(
char
*
)
cur_stack
-
rl
.
rlim_cur
;
SYSDEPS_CallOnStack
(
stackTop
,
stackLow
,
(
int
(
*
)(
void
*
))
func
,
NULL
);
/***********************************************************************
* SYSDEPS_AbortThread
*
* Same as SYSDEPS_ExitThread, but must not do anything that requires a server call.
*/
void
SYSDEPS_AbortThread
(
int
status
)
{
SIGNAL_Reset
();
close
(
NtCurrentTeb
()
->
wait_fd
[
0
]
);
close
(
NtCurrentTeb
()
->
wait_fd
[
1
]
);
close
(
NtCurrentTeb
()
->
reply_fd
);
close
(
NtCurrentTeb
()
->
request_fd
);
#ifdef HAVE__LWP_CREATE
_lwp_exit
();
#endif
for
(;;)
/* avoid warning */
_exit
(
status
);
}
/**********************************************************************
* NtCurrentTeb (NTDLL.@)
*
...
...
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