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
7370f601
Commit
7370f601
authored
Oct 31, 2003
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implemented RtlCreateUserThread, and use it to move thread creation to
ntdll.
parent
ef65d2a6
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
182 additions
and
119 deletions
+182
-119
thread.c
dlls/kernel/thread.c
+34
-107
ntdll.spec
dlls/ntdll/ntdll.spec
+1
-5
thread.c
dlls/ntdll/thread.c
+144
-7
winbase.h
include/winbase.h
+1
-0
winternl.h
include/winternl.h
+2
-0
No files found.
dlls/kernel/thread.c
View file @
7370f601
...
...
@@ -49,30 +49,6 @@ WINE_DECLARE_DEBUG_CHANNEL(relay);
/***********************************************************************
* THREAD_InitTEB
*
* Initialization of a newly created TEB.
*/
static
BOOL
THREAD_InitTEB
(
TEB
*
teb
)
{
teb
->
Tib
.
ExceptionList
=
(
void
*
)
~
0UL
;
teb
->
Tib
.
StackBase
=
(
void
*
)
~
0UL
;
teb
->
Tib
.
Self
=
&
teb
->
Tib
;
teb
->
tibflags
=
TEBF_WIN32
;
teb
->
exit_code
=
STILL_ACTIVE
;
teb
->
request_fd
=
-
1
;
teb
->
reply_fd
=
-
1
;
teb
->
wait_fd
[
0
]
=
-
1
;
teb
->
wait_fd
[
1
]
=
-
1
;
teb
->
StaticUnicodeString
.
MaximumLength
=
sizeof
(
teb
->
StaticUnicodeBuffer
);
teb
->
StaticUnicodeString
.
Buffer
=
(
PWSTR
)
teb
->
StaticUnicodeBuffer
;
InitializeListHead
(
&
teb
->
TlsLinks
);
teb
->
teb_sel
=
wine_ldt_alloc_fs
();
return
(
teb
->
teb_sel
!=
0
);
}
/***********************************************************************
* THREAD_InitStack
*
* Allocate the stack of a thread.
...
...
@@ -83,22 +59,6 @@ TEB *THREAD_InitStack( TEB *teb, DWORD stack_size )
DWORD
page_size
=
getpagesize
();
void
*
base
;
/* Allocate the stack */
/* if size is smaller than default, get stack size from parent */
if
(
stack_size
<
1024
*
1024
)
{
if
(
teb
)
stack_size
=
1024
*
1024
;
/* no parent */
else
stack_size
=
((
char
*
)
NtCurrentTeb
()
->
Tib
.
StackBase
-
(
char
*
)
NtCurrentTeb
()
->
DeallocationStack
-
SIGNAL_STACK_SIZE
);
}
/* FIXME: some Wine functions use a lot of stack, so we add 64Kb here */
stack_size
+=
64
*
1024
;
/* Memory layout in allocated block:
*
* size contents
...
...
@@ -109,21 +69,10 @@ TEB *THREAD_InitStack( TEB *teb, DWORD stack_size )
stack_size
=
(
stack_size
+
(
page_size
-
1
))
&
~
(
page_size
-
1
);
total_size
=
stack_size
+
SIGNAL_STACK_SIZE
;
if
(
!
teb
)
total_size
+=
page_size
;
if
(
!
(
base
=
VirtualAlloc
(
NULL
,
total_size
,
MEM_COMMIT
,
PAGE_EXECUTE_READWRITE
)))
return
NULL
;
if
(
!
teb
)
{
teb
=
(
TEB
*
)((
char
*
)
base
+
total_size
-
page_size
);
if
(
!
THREAD_InitTEB
(
teb
))
{
VirtualFree
(
base
,
0
,
MEM_RELEASE
);
return
NULL
;
}
}
teb
->
DeallocationStack
=
base
;
teb
->
Tib
.
StackBase
=
(
char
*
)
base
+
SIGNAL_STACK_SIZE
+
stack_size
;
teb
->
Tib
.
StackLimit
=
base
;
/* note: limit is lower than base since the stack grows down */
...
...
@@ -136,23 +85,24 @@ TEB *THREAD_InitStack( TEB *teb, DWORD stack_size )
}
struct
new_thread_info
{
LPTHREAD_START_ROUTINE
func
;
void
*
arg
;
};
/***********************************************************************
* THREAD_Start
*
* Start execution of a newly created thread. Does not return.
*/
static
void
THREAD_Start
(
TEB
*
teb
)
static
void
CALLBACK
THREAD_Start
(
void
*
ptr
)
{
LPTHREAD_START_ROUTINE
func
=
(
LPTHREAD_START_ROUTINE
)
teb
->
entry_point
;
struct
debug_info
info
;
info
.
str_pos
=
info
.
strings
;
info
.
out_pos
=
info
.
output
;
teb
->
debug_info
=
&
info
;
struct
new_thread_info
*
info
=
ptr
;
LPTHREAD_START_ROUTINE
func
=
info
->
func
;
void
*
arg
=
info
->
arg
;
SYSDEPS_SetCurThread
(
teb
);
SIGNAL_Init
();
wine_server_init_thread
();
RtlFreeHeap
(
GetProcessHeap
(),
0
,
info
);
if
(
TRACE_ON
(
relay
))
DPRINTF
(
"%04lx:Starting thread (entryproc=%p)
\n
"
,
GetCurrentThreadId
(),
func
);
...
...
@@ -160,7 +110,7 @@ static void THREAD_Start( TEB *teb )
__TRY
{
MODULE_DllThreadAttach
(
NULL
);
ExitThread
(
func
(
NtCurrentTeb
()
->
entry_
arg
)
);
ExitThread
(
func
(
arg
)
);
}
__EXCEPT
(
UnhandledExceptionFilter
)
{
...
...
@@ -177,60 +127,37 @@ HANDLE WINAPI CreateThread( SECURITY_ATTRIBUTES *sa, SIZE_T stack,
LPTHREAD_START_ROUTINE
start
,
LPVOID
param
,
DWORD
flags
,
LPDWORD
id
)
{
HANDLE
handle
=
0
;
TEB
*
teb
;
DWORD
tid
=
0
;
int
request_pipe
[
2
];
HANDLE
handle
;
CLIENT_ID
client_id
;
NTSTATUS
status
;
SIZE_T
stack_reserve
=
0
,
stack_commit
=
0
;
struct
new_thread_info
*
info
;
if
(
pipe
(
request_pipe
)
==
-
1
)
if
(
!
(
info
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
sizeof
(
*
info
)
))
)
{
SetLastError
(
ERROR_
TOO_MANY_OPEN_FILES
);
SetLastError
(
ERROR_
NOT_ENOUGH_MEMORY
);
return
0
;
}
fcntl
(
request_pipe
[
1
],
F_SETFD
,
1
);
/* set close on exec flag */
wine_server_send_fd
(
request_pipe
[
0
]
)
;
info
->
func
=
start
;
info
->
arg
=
param
;
SERVER_START_REQ
(
new_thread
)
{
req
->
suspend
=
((
flags
&
CREATE_SUSPENDED
)
!=
0
);
req
->
inherit
=
(
sa
&&
(
sa
->
nLength
>=
sizeof
(
*
sa
))
&&
sa
->
bInheritHandle
);
req
->
request_fd
=
request_pipe
[
0
];
if
(
!
wine_server_call_err
(
req
))
{
handle
=
reply
->
handle
;
tid
=
reply
->
tid
;
}
close
(
request_pipe
[
0
]
);
}
SERVER_END_REQ
;
if
(
flags
&
STACK_SIZE_PARAM_IS_A_RESERVATION
)
stack_reserve
=
stack
;
else
stack_commit
=
stack
;
if
(
!
handle
||
!
(
teb
=
THREAD_InitStack
(
NULL
,
stack
)))
status
=
RtlCreateUserThread
(
GetCurrentProcess
(),
NULL
,
(
flags
&
CREATE_SUSPENDED
)
!=
0
,
NULL
,
stack_reserve
,
stack_commit
,
THREAD_Start
,
info
,
&
handle
,
&
client_id
);
if
(
status
==
STATUS_SUCCESS
)
{
close
(
request_pipe
[
1
]
);
return
0
;
if
(
id
)
*
id
=
(
DWORD
)
client_id
.
UniqueThread
;
if
(
sa
&&
(
sa
->
nLength
>=
sizeof
(
*
sa
))
&&
sa
->
bInheritHandle
)
SetHandleInformation
(
handle
,
HANDLE_FLAG_INHERIT
,
HANDLE_FLAG_INHERIT
);
}
teb
->
Peb
=
NtCurrentTeb
()
->
Peb
;
teb
->
ClientId
.
UniqueThread
=
(
HANDLE
)
tid
;
teb
->
request_fd
=
request_pipe
[
1
];
teb
->
entry_point
=
start
;
teb
->
entry_arg
=
param
;
teb
->
htask16
=
GetCurrentTask
();
RtlAcquirePebLock
();
InsertHeadList
(
&
NtCurrentTeb
()
->
TlsLinks
,
&
teb
->
TlsLinks
);
RtlReleasePebLock
();
if
(
id
)
*
id
=
tid
;
if
(
SYSDEPS_SpawnThread
(
THREAD_Start
,
teb
)
==
-
1
)
else
{
CloseHandle
(
handle
);
close
(
request_pipe
[
1
]
);
RtlAcquirePebLock
();
RemoveEntryList
(
&
teb
->
TlsLinks
);
RtlReleasePebLock
();
wine_ldt_free_fs
(
teb
->
teb_sel
);
VirtualFree
(
teb
->
DeallocationStack
,
0
,
MEM_RELEASE
);
return
0
;
RtlFreeHeap
(
GetProcessHeap
(),
0
,
info
);
SetLastError
(
RtlNtStatusToDosError
(
status
)
);
handle
=
0
;
}
return
handle
;
}
...
...
dlls/ntdll/ntdll.spec
View file @
7370f601
...
...
@@ -333,7 +333,7 @@
@ stdcall RtlCreateUnicodeStringFromAsciiz(ptr str)
@ stub RtlCreateUserProcess
@ stub RtlCreateUserSecurityObject
@ st
ub RtlCreateUserThread
@ st
dcall RtlCreateUserThread(long ptr long ptr long long ptr ptr ptr ptr)
@ stub RtlCustomCPToUnicodeN
@ stub RtlCutoverTimeToSystemTime
@ stdcall RtlDeNormalizeProcessParams(ptr)
...
...
@@ -1065,7 +1065,6 @@
# Server interface
@ cdecl -norelay wine_server_call(ptr)
@ cdecl wine_server_init_thread()
@ cdecl wine_server_fd_to_handle(long long long ptr)
@ cdecl wine_server_handle_to_fd(long long ptr ptr ptr)
@ cdecl wine_server_send_fd(long)
...
...
@@ -1084,9 +1083,6 @@
@ cdecl MODULE_DllThreadAttach(ptr)
@ cdecl MODULE_GetLoadOrderA(ptr str str long)
@ cdecl MODULE_GetLoadOrderW(ptr wstr wstr long)
@ cdecl SIGNAL_Init()
@ cdecl SYSDEPS_ExitThread(long)
@ cdecl SYSDEPS_SetCurThread(ptr)
@ cdecl SYSDEPS_SpawnThread(ptr ptr)
@ cdecl VERSION_Init(wstr)
@ cdecl VIRTUAL_SetFaultHandler(ptr ptr ptr)
dlls/ntdll/thread.c
View file @
7370f601
...
...
@@ -79,6 +79,149 @@ DECL_GLOBAL_CONSTRUCTOR(thread_init)
}
/* startup routine for a newly created thread */
static
void
start_thread
(
TEB
*
teb
)
{
LPTHREAD_START_ROUTINE
func
=
(
LPTHREAD_START_ROUTINE
)
teb
->
entry_point
;
struct
debug_info
info
;
info
.
str_pos
=
info
.
strings
;
info
.
out_pos
=
info
.
output
;
teb
->
debug_info
=
&
info
;
SYSDEPS_SetCurThread
(
teb
);
SIGNAL_Init
();
wine_server_init_thread
();
NtTerminateThread
(
GetCurrentThread
(),
func
(
NtCurrentTeb
()
->
entry_arg
)
);
}
/***********************************************************************
* RtlCreateUserThread (NTDLL.@)
*/
NTSTATUS
WINAPI
RtlCreateUserThread
(
HANDLE
process
,
const
SECURITY_DESCRIPTOR
*
descr
,
BOOLEAN
suspended
,
PVOID
stack_addr
,
SIZE_T
stack_reserve
,
SIZE_T
stack_commit
,
PRTL_THREAD_START_ROUTINE
start
,
void
*
param
,
HANDLE
*
handle_ptr
,
CLIENT_ID
*
id
)
{
HANDLE
handle
=
0
;
TEB
*
teb
;
DWORD
tid
=
0
;
SIZE_T
total_size
;
SIZE_T
page_size
=
getpagesize
();
void
*
ptr
,
*
base
=
NULL
;
int
request_pipe
[
2
];
NTSTATUS
status
;
if
(
pipe
(
request_pipe
)
==
-
1
)
return
STATUS_TOO_MANY_OPENED_FILES
;
fcntl
(
request_pipe
[
1
],
F_SETFD
,
1
);
/* set close on exec flag */
wine_server_send_fd
(
request_pipe
[
0
]
);
SERVER_START_REQ
(
new_thread
)
{
req
->
suspend
=
suspended
;
req
->
inherit
=
0
;
/* FIXME */
req
->
request_fd
=
request_pipe
[
0
];
if
(
!
(
status
=
wine_server_call
(
req
)))
{
handle
=
reply
->
handle
;
tid
=
reply
->
tid
;
}
close
(
request_pipe
[
0
]
);
}
SERVER_END_REQ
;
if
(
status
)
goto
error
;
if
(
!
stack_reserve
||
!
stack_commit
)
{
IMAGE_NT_HEADERS
*
nt
=
RtlImageNtHeader
(
NtCurrentTeb
()
->
Peb
->
ImageBaseAddress
);
if
(
!
stack_reserve
)
stack_reserve
=
nt
->
OptionalHeader
.
SizeOfStackReserve
;
if
(
!
stack_commit
)
stack_commit
=
nt
->
OptionalHeader
.
SizeOfStackCommit
;
}
if
(
stack_reserve
<
stack_commit
)
stack_reserve
=
stack_commit
;
stack_reserve
=
(
stack_reserve
+
0xffff
)
&
~
0xffff
;
/* round to 64K boundary */
/* Memory layout in allocated block:
*
* size contents
* SIGNAL_STACK_SIZE signal stack
* stack_size normal stack (including a PAGE_GUARD page at the bottom)
* 1 page TEB (except for initial thread)
*/
total_size
=
stack_reserve
+
SIGNAL_STACK_SIZE
+
page_size
;
if
((
status
=
NtAllocateVirtualMemory
(
GetCurrentProcess
(),
&
base
,
NULL
,
&
total_size
,
MEM_COMMIT
,
PAGE_EXECUTE_READWRITE
))
!=
STATUS_SUCCESS
)
goto
error
;
teb
=
(
TEB
*
)((
char
*
)
base
+
total_size
-
page_size
);
if
(
!
(
teb
->
teb_sel
=
wine_ldt_alloc_fs
()))
{
status
=
STATUS_TOO_MANY_THREADS
;
goto
error
;
}
teb
->
Tib
.
ExceptionList
=
(
void
*
)
~
0UL
;
teb
->
Tib
.
StackBase
=
(
char
*
)
base
+
SIGNAL_STACK_SIZE
+
stack_reserve
;
teb
->
Tib
.
StackLimit
=
base
;
/* limit is lower than base since the stack grows down */
teb
->
Tib
.
Self
=
&
teb
->
Tib
;
teb
->
ClientId
.
UniqueProcess
=
(
HANDLE
)
GetCurrentProcessId
();
teb
->
ClientId
.
UniqueThread
=
(
HANDLE
)
tid
;
teb
->
Peb
=
NtCurrentTeb
()
->
Peb
;
teb
->
DeallocationStack
=
base
;
teb
->
StaticUnicodeString
.
Buffer
=
teb
->
StaticUnicodeBuffer
;
teb
->
StaticUnicodeString
.
MaximumLength
=
sizeof
(
teb
->
StaticUnicodeBuffer
);
RtlAcquirePebLock
();
InsertHeadList
(
&
NtCurrentTeb
()
->
TlsLinks
,
&
teb
->
TlsLinks
);
RtlReleasePebLock
();
teb
->
tibflags
=
TEBF_WIN32
;
teb
->
exit_code
=
STILL_ACTIVE
;
teb
->
request_fd
=
request_pipe
[
1
];
teb
->
reply_fd
=
-
1
;
teb
->
wait_fd
[
0
]
=
-
1
;
teb
->
wait_fd
[
1
]
=
-
1
;
teb
->
entry_point
=
start
;
teb
->
entry_arg
=
param
;
teb
->
htask16
=
NtCurrentTeb
()
->
htask16
;
/* setup the guard page */
ptr
=
(
char
*
)
base
+
SIGNAL_STACK_SIZE
;
NtProtectVirtualMemory
(
GetCurrentProcess
(),
&
ptr
,
&
page_size
,
PAGE_EXECUTE_READWRITE
|
PAGE_GUARD
,
NULL
);
if
(
SYSDEPS_SpawnThread
(
start_thread
,
teb
)
==
-
1
)
{
RtlAcquirePebLock
();
RemoveEntryList
(
&
teb
->
TlsLinks
);
RtlReleasePebLock
();
wine_ldt_free_fs
(
teb
->
teb_sel
);
status
=
STATUS_TOO_MANY_THREADS
;
goto
error
;
}
if
(
id
)
id
->
UniqueThread
=
(
HANDLE
)
tid
;
if
(
handle_ptr
)
*
handle_ptr
=
handle
;
else
NtClose
(
handle
);
return
STATUS_SUCCESS
;
error
:
if
(
base
)
{
total_size
=
0
;
NtFreeVirtualMemory
(
GetCurrentProcess
(),
&
base
,
&
total_size
,
MEM_RELEASE
);
}
if
(
handle
)
NtClose
(
handle
);
close
(
request_pipe
[
1
]
);
return
status
;
}
/***********************************************************************
* NtOpenThread (NTDLL.@)
* ZwOpenThread (NTDLL.@)
...
...
@@ -159,13 +302,7 @@ NTSTATUS WINAPI NtTerminateThread( HANDLE handle, LONG exit_code )
if
(
self
)
{
if
(
last
)
exit
(
exit_code
);
else
{
RtlAcquirePebLock
();
RemoveEntryList
(
&
NtCurrentTeb
()
->
TlsLinks
);
RtlReleasePebLock
();
SYSDEPS_ExitThread
(
exit_code
);
}
else
SYSDEPS_AbortThread
(
exit_code
);
}
return
ret
;
}
...
...
include/winbase.h
View file @
7370f601
...
...
@@ -589,6 +589,7 @@ typedef struct _TIME_ZONE_INFORMATION{
#define CREATE_UNICODE_ENVIRONMENT 0x00000400
#define CREATE_SEPARATE_WOW_VDM 0x00000800
#define CREATE_SHARED_WOW_VDM 0x00001000
#define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
#define CREATE_DEFAULT_ERROR_MODE 0x04000000
#define CREATE_NO_WINDOW 0x08000000
#define PROFILE_USER 0x10000000
...
...
include/winternl.h
View file @
7370f601
...
...
@@ -935,6 +935,7 @@ typedef struct _LDR_RESOURCE_INFO
#define SERVERNAME_CURRENT ((HANDLE)NULL)
typedef
void
(
CALLBACK
*
PNTAPCFUNC
)(
ULONG_PTR
,
ULONG_PTR
,
ULONG_PTR
);
/* FIXME: not the right name */
typedef
void
(
CALLBACK
*
PRTL_THREAD_START_ROUTINE
)(
LPVOID
);
/* FIXME: not the right name */
/***********************************************************************
* Function declarations
...
...
@@ -1095,6 +1096,7 @@ NTSTATUS WINAPI RtlCreateProcessParameters(RTL_USER_PROCESS_PARAMETERS**,const
NTSTATUS
WINAPI
RtlCreateSecurityDescriptor
(
PSECURITY_DESCRIPTOR
,
DWORD
);
BOOLEAN
WINAPI
RtlCreateUnicodeString
(
PUNICODE_STRING
,
LPCWSTR
);
BOOLEAN
WINAPI
RtlCreateUnicodeStringFromAsciiz
(
PUNICODE_STRING
,
LPCSTR
);
NTSTATUS
WINAPI
RtlCreateUserThread
(
HANDLE
,
const
SECURITY_DESCRIPTOR
*
,
BOOLEAN
,
PVOID
,
SIZE_T
,
SIZE_T
,
PRTL_THREAD_START_ROUTINE
,
void
*
,
HANDLE
*
,
CLIENT_ID
*
);
NTSTATUS
WINAPI
RtlDeleteCriticalSection
(
RTL_CRITICAL_SECTION
*
);
void
WINAPI
RtlDeleteResource
(
LPRTL_RWLOCK
);
...
...
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