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
ca3bfd83
Commit
ca3bfd83
authored
Aug 29, 2003
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Export SYSDEPS_SwitchToThreadStack() functionality from libwine as
wine_switch_to_stack().
parent
d4c1ebab
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
228 additions
and
211 deletions
+228
-211
sysdeps.c
dlls/ntdll/sysdeps.c
+2
-72
thread.h
include/thread.h
+0
-1
library.h
include/wine/library.h
+1
-4
Makefile.in
libs/wine/Makefile.in
+2
-1
loader.c
libs/wine/loader.c
+0
-131
port.c
libs/wine/port.c
+220
-0
fiber.c
scheduler/fiber.c
+2
-1
process.c
scheduler/process.c
+1
-1
No files found.
dlls/ntdll/sysdeps.c
View file @
ca3bfd83
...
...
@@ -115,7 +115,7 @@ void SYSDEPS_SetCurThread( TEB *teb )
inline
static
char
*
get_temp_stack
(
void
)
{
unsigned
int
next
=
interlocked_xchg_add
(
&
next_temp_stack
,
1
);
return
temp_stacks
[
next
%
NB_TEMP_STACKS
];
return
temp_stacks
[
next
%
NB_TEMP_STACKS
]
+
TEMP_STACK_SIZE
;
}
...
...
@@ -193,73 +193,6 @@ int SYSDEPS_SpawnThread( void (*func)(TEB *), TEB *teb )
/***********************************************************************
* SYSDEPS_SwitchToThreadStack
*
* Switch to the stack specified in the current thread TEB
* and call the specified function.
*/
void
DECLSPEC_NORETURN
SYSDEPS_SwitchToThreadStack
(
void
(
*
func
)(
void
*
),
void
*
arg
);
#ifdef __i386__
# ifdef __GNUC__
__ASM_GLOBAL_FUNC
(
SYSDEPS_SwitchToThreadStack
,
"movl 4(%esp),%ecx
\n\t
"
/* func */
"movl 8(%esp),%edx
\n\t
"
/* arg */
".byte 0x64
\n\t
movl 0x04,%esp
\n\t
"
/* teb->Tib.StackBase */
"pushl %edx
\n\t
"
"xorl %ebp,%ebp
\n\t
"
"call *%ecx
\n\t
"
"int $3"
/* we never return here */
);
# elif defined(_MSC_VER)
__declspec
(
naked
)
void
SYSDEPS_SwitchToThreadStack
(
void
(
*
func
)(
void
*
),
void
*
arg
)
{
__asm
mov
ecx
,
4
[
esp
];
__asm
mov
edx
,
8
[
esp
];
__asm
mov
fs
:
[
0x04
],
esp
;
__asm
push
edx
;
__asm
xor
ebp
,
ebp
;
__asm
call
[
ecx
];
__asm
int
3
;
}
# endif
/* defined(__GNUC__) || defined(_MSC_VER) */
#elif defined(__sparc__) && defined(__GNUC__)
__ASM_GLOBAL_FUNC
(
SYSDEPS_SwitchToThreadStack
,
"mov %o0, %l0
\n\t
"
/* store first argument */
"call "
__ASM_NAME
(
"NtCurrentTeb"
)
", 0
\n\t
"
"mov %o1, %l1
\n\t
"
/* delay slot: store second argument */
"ld [%o0+4], %sp
\n\t
"
/* teb->Tib.StackBase */
"call %l0, 0
\n\t
"
/* call func */
"mov %l1, %o0
\n\t
"
/* delay slot: arg for func */
"ta 0x01
\n\t
"
);
/* breakpoint - we never get here */
#elif defined(__powerpc__) && defined(__APPLE__)
/* Darwin SYSDEPS_SwitchToThreadStack
Function Pointer to call is on r3, Args to pass on r4 and stack on r1 */
__ASM_GLOBAL_FUNC
(
SYSDEPS_SwitchToThreadStack
,
"stw r1, 0x4(r13)
\n\t
"
/* teb->Tib.StackBase */
"mr r12,r3
\n\t
"
"mtctr r12
\n\t
"
/* func->ctr */
"mr r3,r4
\n\t
"
/* args->function param 1 (r3) */
"bctr
\n\t
"
/* call ctr */
"b _SYSDEPS_SwitchToThreadStack+24
\n\t
"
);
/* loop */
#elif defined(__powerpc__) && defined(__GNUC__)
/* Linux SYSDEPS_SwitchToThreadStack
Function Pointer to call is on r3, Args to pass on r4 and stack on r1 */
__ASM_GLOBAL_FUNC
(
SYSDEPS_SwitchToThreadStack
,
"stw 1, 0x4(13)
\n\t
"
/* teb->Tib.StackBase */
"mr 12,3
\n\t
"
"mtctr 12
\n\t
"
/* func->ctr */
"mr 3,4
\n\t
"
/* args->function param 1 (r3) */
"bctr
\n\t
"
/* call ctr */
"b _SYSDEPS_SwitchToThreadStack+24
\n\t
"
);
/* loop */
#else
/* !powerpc, !sparc, !i386 */
void
SYSDEPS_SwitchToThreadStack
(
void
(
*
func
)(
void
*
),
void
*
arg
)
{
func
(
arg
);
while
(
1
);
/* avoid warning */
}
#endif
/* !defined(__i386__) && !defined(__sparc__) */
/***********************************************************************
* SYSDEPS_ExitThread
*
* Exit a running thread; must not return.
...
...
@@ -285,7 +218,6 @@ void SYSDEPS_ExitThread( int status )
ptr
=
free_teb
->
DeallocationStack
;
NtFreeVirtualMemory
(
GetCurrentProcess
(),
&
ptr
,
&
size
,
MEM_RELEASE
);
}
SIGNAL_Block
();
SYSDEPS_AbortThread
(
status
);
#else
struct
thread_cleanup_info
info
;
...
...
@@ -305,9 +237,7 @@ void SYSDEPS_ExitThread( int status )
close
(
teb
->
reply_fd
);
close
(
teb
->
request_fd
);
SIGNAL_Reset
();
teb
->
Tib
.
StackLimit
=
get_temp_stack
();
teb
->
Tib
.
StackBase
=
(
char
*
)
teb
->
Tib
.
StackLimit
+
TEMP_STACK_SIZE
;
SYSDEPS_SwitchToThreadStack
(
cleanup_thread
,
&
info
);
wine_switch_to_stack
(
cleanup_thread
,
&
info
,
get_temp_stack
()
);
#endif
}
...
...
include/thread.h
View file @
ca3bfd83
...
...
@@ -149,7 +149,6 @@ extern void SYSDEPS_SetCurThread( TEB *teb );
extern
int
SYSDEPS_GetUnixTid
(
void
);
extern
void
DECLSPEC_NORETURN
SYSDEPS_ExitThread
(
int
status
);
extern
void
DECLSPEC_NORETURN
SYSDEPS_AbortThread
(
int
status
);
extern
void
DECLSPEC_NORETURN
SYSDEPS_SwitchToThreadStack
(
void
(
*
func
)(
void
*
),
void
*
arg
);
/* signal handling */
extern
BOOL
SIGNAL_Init
(
void
);
...
...
include/wine/library.h
View file @
ca3bfd83
...
...
@@ -61,12 +61,9 @@ extern int wine_dbg_parse_options( const char *str );
/* portability */
extern
void
DECLSPEC_NORETURN
wine_switch_to_stack
(
void
(
*
func
)(
void
*
),
void
*
arg
,
void
*
stack
);
extern
void
*
wine_anon_mmap
(
void
*
start
,
size_t
size
,
int
prot
,
int
flags
);
/* errno support */
extern
int
*
(
*
wine_errno_location
)(
void
);
extern
int
*
(
*
wine_h_errno_location
)(
void
);
/* LDT management */
extern
void
wine_ldt_init_locking
(
void
(
*
lock_func
)(
void
),
void
(
*
unlock_func
)(
void
)
);
...
...
libs/wine/Makefile.in
View file @
ca3bfd83
...
...
@@ -11,7 +11,8 @@ C_SRCS = \
config.c
\
debug.c
\
ldt.c
\
loader.c
loader.c
\
port.c
@MAKE_LIB_RULES@
...
...
libs/wine/loader.c
View file @
ca3bfd83
...
...
@@ -33,9 +33,6 @@
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
...
...
@@ -428,134 +425,6 @@ void wine_init( int argc, char *argv[], char *error, int error_size )
}
#if (defined(__svr4__) || defined(__NetBSD__)) && !defined(MAP_TRYFIXED)
/***********************************************************************
* try_mmap_fixed
*
* The purpose of this routine is to emulate the behaviour of
* the Linux mmap() routine if a non-NULL address is passed,
* but the MAP_FIXED flag is not set. Linux in this case tries
* to place the mapping at the specified address, *unless* the
* range is already in use. Solaris, however, completely ignores
* the address argument in this case.
*
* As Wine code occasionally relies on the Linux behaviour, e.g. to
* be able to map non-relocateable PE executables to their proper
* start addresses, or to map the DOS memory to 0, this routine
* emulates the Linux behaviour by checking whether the desired
* address range is still available, and placing the mapping there
* using MAP_FIXED if so.
*/
static
int
try_mmap_fixed
(
void
*
addr
,
size_t
len
,
int
prot
,
int
flags
,
int
fildes
,
off_t
off
)
{
char
*
volatile
result
=
NULL
;
int
pagesize
=
getpagesize
();
pid_t
pid
;
/* We only try to map to a fixed address if
addr is non-NULL and properly aligned,
and MAP_FIXED isn't already specified. */
if
(
!
addr
)
return
0
;
if
(
(
uintptr_t
)
addr
&
(
pagesize
-
1
)
)
return
0
;
if
(
flags
&
MAP_FIXED
)
return
0
;
/* We use vfork() to freeze all threads of the
current process. This allows us to check without
race condition whether the desired memory range is
already in use. Note that because vfork() shares
the address spaces between parent and child, we
can actually perform the mapping in the child. */
if
(
(
pid
=
vfork
())
==
-
1
)
{
perror
(
"try_mmap_fixed: vfork"
);
exit
(
1
);
}
if
(
pid
==
0
)
{
int
i
;
char
vec
;
/* We call mincore() for every page in the desired range.
If any of these calls succeeds, the page is already
mapped and we must fail. */
for
(
i
=
0
;
i
<
len
;
i
+=
pagesize
)
if
(
mincore
(
(
caddr_t
)
addr
+
i
,
pagesize
,
&
vec
)
!=
-
1
)
_exit
(
1
);
/* Perform the mapping with MAP_FIXED set. This is safe
now, as none of the pages is currently in use. */
result
=
mmap
(
addr
,
len
,
prot
,
flags
|
MAP_FIXED
,
fildes
,
off
);
if
(
result
==
addr
)
_exit
(
0
);
if
(
result
!=
(
void
*
)
-
1
)
/* This should never happen ... */
munmap
(
result
,
len
);
_exit
(
1
);
}
/* vfork() lets the parent continue only after the child
has exited. Furthermore, Wine sets SIGCHLD to SIG_IGN,
so we don't need to wait for the child. */
return
result
==
addr
;
}
#endif
/* (__svr4__ || __NetBSD__) && !MAP_TRYFIXED */
/***********************************************************************
* wine_anon_mmap
*
* Portable wrapper for anonymous mmaps
*/
void
*
wine_anon_mmap
(
void
*
start
,
size_t
size
,
int
prot
,
int
flags
)
{
#ifdef HAVE_MMAP
static
int
fdzero
=
-
1
;
#ifdef MAP_ANON
flags
|=
MAP_ANON
;
#else
if
(
fdzero
==
-
1
)
{
if
((
fdzero
=
open
(
"/dev/zero"
,
O_RDONLY
))
==
-
1
)
{
perror
(
"/dev/zero: open"
);
exit
(
1
);
}
}
#endif
/* MAP_ANON */
#ifdef MAP_SHARED
flags
&=
~
MAP_SHARED
;
#endif
/* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
#ifdef MAP_PRIVATE
flags
|=
MAP_PRIVATE
;
#endif
#ifdef MAP_TRYFIXED
/* If available, this will attempt a fixed mapping in-kernel */
flags
|=
MAP_TRYFIXED
;
#elif defined(__svr4__) || defined(__NetBSD__)
if
(
try_mmap_fixed
(
start
,
size
,
prot
,
flags
,
fdzero
,
0
)
)
return
start
;
#endif
return
mmap
(
start
,
size
,
prot
,
flags
,
fdzero
,
0
);
#else
return
(
void
*
)
-
1
;
#endif
}
/*
* These functions provide wrappers around dlopen() and associated
* functions. They work around a bug in glibc 2.1.x where calling
...
...
libs/wine/port.c
0 → 100644
View file @
ca3bfd83
/*
* Wine portability routines
*
* Copyright 2000 Alexandre Julliard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "wine/port.h"
#include <assert.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include "wine/library.h"
/***********************************************************************
* wine_switch_to_stack
*
* Switch to the specified stack and call the function.
*/
void
DECLSPEC_NORETURN
wine_switch_to_stack
(
void
(
*
func
)(
void
*
),
void
*
arg
,
void
*
stack
);
#if defined(__i386__) && defined(__GNUC__)
__ASM_GLOBAL_FUNC
(
wine_switch_to_stack
,
"movl 4(%esp),%ecx
\n\t
"
/* func */
"movl 8(%esp),%edx
\n\t
"
/* arg */
"movl 12(%esp),%esp
\n\t
"
/* stack */
"pushl %edx
\n\t
"
"xorl %ebp,%ebp
\n\t
"
"call *%ecx
\n\t
"
"int $3"
/* we never return here */
);
#elif defined(__i386__) && defined(_MSC_VER)
__declspec
(
naked
)
void
wine_switch_to_stack
(
void
(
*
func
)(
void
*
),
void
*
arg
,
void
*
stack
)
{
__asm
mov
ecx
,
4
[
esp
];
__asm
mov
edx
,
8
[
esp
];
__asm
mov
esp
,
12
[
esp
];
__asm
push
edx
;
__asm
xor
ebp
,
ebp
;
__asm
call
[
ecx
];
__asm
int
3
;
}
#elif defined(__sparc__) && defined(__GNUC__)
__ASM_GLOBAL_FUNC
(
wine_switch_to_stack
,
"mov %o0, %l0
\n\t
"
/* store first argument */
"mov %o1, %l1
\n\t
"
/* store second argument */
"mov %o2, %sp
\n\t
"
/* store stack */
"call %l0, 0
\n\t
"
/* call func */
"mov %l1, %o0
\n\t
"
/* delay slot: arg for func */
"ta 0x01"
);
/* breakpoint - we never get here */
#elif defined(__powerpc__) && defined(__APPLE__)
__ASM_GLOBAL_FUNC
(
wine_switch_to_stack
,
"mtctr r3
\n\t
"
/* func -> ctr */
"mr r3,r4
\n\t
"
/* args -> function param 1 (r3) */
"mr r1,r5
\n\t
"
/* stack */
"bctr
\n
"
/* call ctr */
"1:
\t
b 1b"
);
/* loop */
#elif defined(__powerpc__) && defined(__GNUC__)
__ASM_GLOBAL_FUNC
(
wine_switch_to_stack
,
"mtctr 3
\n\t
"
/* func -> ctr */
"mr 3,4
\n\t
"
/* args -> function param 1 (r3) */
"mr 1,5
\n\t
"
/* stack */
"bctr
\n\t
"
/* call ctr */
"1:
\t
b 1b"
);
/* loop */
#else
#error You must implement wine_switch_to_stack for your platform
#endif
#if (defined(__svr4__) || defined(__NetBSD__)) && !defined(MAP_TRYFIXED)
/***********************************************************************
* try_mmap_fixed
*
* The purpose of this routine is to emulate the behaviour of
* the Linux mmap() routine if a non-NULL address is passed,
* but the MAP_FIXED flag is not set. Linux in this case tries
* to place the mapping at the specified address, *unless* the
* range is already in use. Solaris, however, completely ignores
* the address argument in this case.
*
* As Wine code occasionally relies on the Linux behaviour, e.g. to
* be able to map non-relocateable PE executables to their proper
* start addresses, or to map the DOS memory to 0, this routine
* emulates the Linux behaviour by checking whether the desired
* address range is still available, and placing the mapping there
* using MAP_FIXED if so.
*/
static
int
try_mmap_fixed
(
void
*
addr
,
size_t
len
,
int
prot
,
int
flags
,
int
fildes
,
off_t
off
)
{
char
*
volatile
result
=
NULL
;
int
pagesize
=
getpagesize
();
pid_t
pid
;
/* We only try to map to a fixed address if
addr is non-NULL and properly aligned,
and MAP_FIXED isn't already specified. */
if
(
!
addr
)
return
0
;
if
(
(
uintptr_t
)
addr
&
(
pagesize
-
1
)
)
return
0
;
if
(
flags
&
MAP_FIXED
)
return
0
;
/* We use vfork() to freeze all threads of the
current process. This allows us to check without
race condition whether the desired memory range is
already in use. Note that because vfork() shares
the address spaces between parent and child, we
can actually perform the mapping in the child. */
if
(
(
pid
=
vfork
())
==
-
1
)
{
perror
(
"try_mmap_fixed: vfork"
);
exit
(
1
);
}
if
(
pid
==
0
)
{
int
i
;
char
vec
;
/* We call mincore() for every page in the desired range.
If any of these calls succeeds, the page is already
mapped and we must fail. */
for
(
i
=
0
;
i
<
len
;
i
+=
pagesize
)
if
(
mincore
(
(
caddr_t
)
addr
+
i
,
pagesize
,
&
vec
)
!=
-
1
)
_exit
(
1
);
/* Perform the mapping with MAP_FIXED set. This is safe
now, as none of the pages is currently in use. */
result
=
mmap
(
addr
,
len
,
prot
,
flags
|
MAP_FIXED
,
fildes
,
off
);
if
(
result
==
addr
)
_exit
(
0
);
if
(
result
!=
(
void
*
)
-
1
)
/* This should never happen ... */
munmap
(
result
,
len
);
_exit
(
1
);
}
/* vfork() lets the parent continue only after the child
has exited. Furthermore, Wine sets SIGCHLD to SIG_IGN,
so we don't need to wait for the child. */
return
result
==
addr
;
}
#endif
/* (__svr4__ || __NetBSD__) && !MAP_TRYFIXED */
/***********************************************************************
* wine_anon_mmap
*
* Portable wrapper for anonymous mmaps
*/
void
*
wine_anon_mmap
(
void
*
start
,
size_t
size
,
int
prot
,
int
flags
)
{
#ifdef HAVE_MMAP
static
int
fdzero
=
-
1
;
#ifdef MAP_ANON
flags
|=
MAP_ANON
;
#else
if
(
fdzero
==
-
1
)
{
if
((
fdzero
=
open
(
"/dev/zero"
,
O_RDONLY
))
==
-
1
)
{
perror
(
"/dev/zero: open"
);
exit
(
1
);
}
}
#endif
/* MAP_ANON */
#ifdef MAP_SHARED
flags
&=
~
MAP_SHARED
;
#endif
/* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
#ifdef MAP_PRIVATE
flags
|=
MAP_PRIVATE
;
#endif
#ifdef MAP_TRYFIXED
/* If available, this will attempt a fixed mapping in-kernel */
flags
|=
MAP_TRYFIXED
;
#elif defined(__svr4__) || defined(__NetBSD__)
if
(
try_mmap_fixed
(
start
,
size
,
prot
,
flags
,
fdzero
,
0
)
)
return
start
;
#endif
return
mmap
(
start
,
size
,
prot
,
flags
,
fdzero
,
0
);
#else
return
(
void
*
)
-
1
;
#endif
}
scheduler/fiber.c
View file @
ca3bfd83
...
...
@@ -27,6 +27,7 @@
#include "winbase.h"
#include "winerror.h"
#include "wine/exception.h"
#include "wine/library.h"
#include "thread.h"
struct
fiber_data
...
...
@@ -190,7 +191,7 @@ void WINAPI SwitchToFiber( LPVOID fiber )
NtCurrentTeb
()
->
Tib
.
StackLimit
=
new_fiber
->
stack_limit
;
NtCurrentTeb
()
->
DeallocationStack
=
new_fiber
->
stack_allocation
;
if
(
new_fiber
->
start
)
/* first time */
SYSDEPS_SwitchToThreadStack
(
start_fiber
,
new_fiber
);
wine_switch_to_stack
(
start_fiber
,
new_fiber
,
new_fiber
->
stack_base
);
else
longjmp
(
new_fiber
->
jmpbuf
,
1
);
}
...
...
scheduler/process.c
View file @
ca3bfd83
...
...
@@ -586,7 +586,7 @@ void __wine_process_init( int argc, char *argv[] )
if
(
!
THREAD_InitStack
(
NtCurrentTeb
(),
stack_size
))
goto
error
;
/* switch to the new stack */
SYSDEPS_SwitchToThreadStack
(
start_process
,
NULL
);
wine_switch_to_stack
(
start_process
,
NULL
,
NtCurrentTeb
()
->
Tib
.
StackBase
);
error:
ExitProcess
(
GetLastError
()
);
...
...
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