ReactOS 0.4.16-dev-942-g91fadeb
thread.cpp File Reference
#include <corecrt_internal.h>
#include <process.h>
#include <roapi.h>
Include dependency graph for thread.cpp:

Go to the source code of this file.

Classes

struct  anonymous_namespace{thread.cpp}::thread_parameter_free_policy
 

Namespaces

namespace  anonymous_namespace{thread.cpp}
 

Typedefs

using anonymous_namespace{thread.cpp}::unique_thread_parameter = __crt_unique_heap_ptr< __acrt_thread_parameter, thread_parameter_free_policy >
 

Functions

template<typename ThreadProcedure , bool Ex>
static unsigned long WINAPI thread_start (void *const parameter) throw ()
 
static __acrt_thread_parameter *__cdecl create_thread_parameter (void *const procedure, void *const context) throw ()
 
uintptr_t __cdecl _beginthread (_beginthread_proc_type const procedure, unsigned int const stack_size, void *const context)
 
uintptr_t __cdecl _beginthreadex (void *const security_descriptor, unsigned int const stack_size, _beginthreadex_proc_type const procedure, void *const context, unsigned int const creation_flags, unsigned int *const thread_id_result)
 
static void __cdecl common_end_thread (unsigned int const return_code) throw ()
 
void __cdecl _endthread ()
 
void __cdecl _endthreadex (unsigned int const return_code)
 

Function Documentation

◆ _beginthread()

uintptr_t __cdecl _beginthread ( _beginthread_proc_type const  procedure,
unsigned int const  stack_size,
void *const  context 
)

Definition at line 145 of file thread.cpp.

150{
151 _VALIDATE_RETURN(procedure != nullptr, EINVAL, reinterpret_cast<uintptr_t>(INVALID_HANDLE_VALUE));
152
153 unique_thread_parameter parameter(create_thread_parameter(reinterpret_cast<void*>(procedure), context));
154 if (!parameter)
155 {
156 return reinterpret_cast<uintptr_t>(INVALID_HANDLE_VALUE);
157 }
158
159 // We create the new thread in a suspended state so that we can update
160 // the parameter structure with the thread handle. The newly created
161 // thread is responsible for closing this handle.
163 HANDLE const thread_handle = CreateThread(
164 nullptr,
165 stack_size,
166 thread_start<_beginthread_proc_type, false>,
167 parameter.get(),
169 &thread_id);
170
171 if (!thread_handle)
172 {
174 return reinterpret_cast<uintptr_t>(INVALID_HANDLE_VALUE);
175 }
176
177 parameter.get()->_thread_handle = thread_handle;
178
179 // Now we can start the thread...
180 if (ResumeThread(thread_handle) == static_cast<DWORD>(-1))
181 {
183 return reinterpret_cast<uintptr_t>(INVALID_HANDLE_VALUE);
184 }
185
186 // If we successfully created the thread, the thread now owns its parameter:
187 parameter.detach();
188
189 return reinterpret_cast<uintptr_t>(thread_handle);
190}
#define EINVAL
Definition: acclib.h:90
void __cdecl __acrt_errno_map_os_error(unsigned long)
Definition: errno.cpp:91
#define _VALIDATE_RETURN(expr, errorcode, retexpr)
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
DWORD WINAPI ResumeThread(IN HANDLE hThread)
Definition: thread.c:567
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned int uintptr_t
Definition: intrin.h:47
static DWORD thread_id
Definition: protocol.c:159
__crt_unique_heap_ptr< __acrt_thread_parameter, thread_parameter_free_policy > unique_thread_parameter
Definition: thread.cpp:72
static __acrt_thread_parameter *__cdecl create_thread_parameter(void *const procedure, void *const context)
Definition: thread.cpp:119
Definition: http.c:7252
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define CREATE_SUSPENDED
Definition: winbase.h:181

◆ _beginthreadex()

uintptr_t __cdecl _beginthreadex ( void *const  security_descriptor,
unsigned int const  stack_size,
_beginthreadex_proc_type const  procedure,
void *const  context,
unsigned int const  creation_flags,
unsigned int *const  thread_id_result 
)

Definition at line 192 of file thread.cpp.

200{
201 _VALIDATE_RETURN(procedure != nullptr, EINVAL, 0);
202
203 unique_thread_parameter parameter(create_thread_parameter((void*)procedure, context));
204 if (!parameter)
205 {
206 return 0;
207 }
208
210 HANDLE const thread_handle = CreateThread(
211 reinterpret_cast<LPSECURITY_ATTRIBUTES>(security_descriptor),
212 stack_size,
213 thread_start<_beginthreadex_proc_type, true>,
214 parameter.get(),
215 creation_flags,
216 &thread_id);
217
218 if (!thread_handle)
219 {
221 return 0;
222 }
223
224 if (thread_id_result)
225 {
226 *thread_id_result = thread_id;
227 }
228
229 // If we successfully created the thread, the thread now owns its parameter:
230 parameter.detach();
231
232 return reinterpret_cast<uintptr_t>(thread_handle);
233}

◆ _endthread()

void __cdecl _endthread ( void  )

Definition at line 271 of file thread.cpp.

272{
273 return common_end_thread(0);
274}
static void __cdecl common_end_thread(unsigned int const return_code)
Definition: thread.cpp:237

Referenced by DefragThread(), init(), internal_thread_proc(), processRequest(), test_thread_func(), and test_thread_func_ex().

◆ _endthreadex()

void __cdecl _endthreadex ( unsigned int const  return_code)

Definition at line 276 of file thread.cpp.

277{
278 return common_end_thread(return_code);
279}

Referenced by ActionThread(), internal_thread_proc(), test_thread_func(), and thread_start().

◆ common_end_thread()

static void __cdecl common_end_thread ( unsigned int const  return_code)
throw (
)
static

Definition at line 237 of file thread.cpp.

238{
240 if (!ptd)
241 {
242 ExitThread(return_code);
243 }
244
245 __acrt_thread_parameter* const parameter = ptd->_beginthread_context;
246 if (!parameter)
247 {
248 ExitThread(return_code);
249 }
250
251 if (parameter->_initialized_apartment)
252 {
254 }
255
256 if (parameter->_thread_handle != INVALID_HANDLE_VALUE && parameter->_thread_handle != nullptr)
257 {
258 CloseHandle(parameter->_thread_handle);
259 }
260
261 if (parameter->_module_handle != INVALID_HANDLE_VALUE && parameter->_module_handle != nullptr)
262 {
263 FreeLibraryAndExitThread(parameter->_module_handle, return_code);
264 }
265 else
266 {
267 ExitThread(return_code);
268 }
269}
void WINAPI __acrt_RoUninitialize(void)
__acrt_ptd *__cdecl __acrt_getptd_noexit(void)
_In_ size_t const _In_ int _In_ bool const _In_ unsigned const _In_ __acrt_rounding_mode const _Inout_ __crt_cached_ptd_host & ptd
Definition: cvt.cpp:355
#define CloseHandle
Definition: compat.h:739
VOID WINAPI FreeLibraryAndExitThread(HMODULE hLibModule, DWORD dwExitCode)
Definition: loader.c:507
VOID WINAPI ExitThread(IN DWORD uExitCode)
Definition: thread.c:365

Referenced by _endthread(), and _endthreadex().

◆ create_thread_parameter()

static __acrt_thread_parameter *__cdecl create_thread_parameter ( void *const  procedure,
void *const  context 
)
throw (
)
static

Definition at line 119 of file thread.cpp.

123{
124 unique_thread_parameter parameter(_calloc_crt_t(__acrt_thread_parameter, 1).detach());
125 if (!parameter)
126 {
127 return nullptr;
128 }
129
130 parameter.get()->_procedure = reinterpret_cast<void*>(procedure);
131 parameter.get()->_context = context;
132
133 // Attempt to bump the reference count of the module in which the user's
134 // thread procedure is defined, to ensure that the module will stay loaded
135 // as long as the thread is executing. We will release this HMDOULE when
136 // the thread procedure returns or _endthreadex is called.
138 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
139 reinterpret_cast<LPCWSTR>(procedure),
140 &parameter.get()->_module_handle);
141
142 return parameter.detach();
143}
BOOL WINAPI GetModuleHandleExW(IN DWORD dwFlags, IN LPCWSTR lpwModuleName OPTIONAL, OUT HMODULE *phModule)
Definition: loader.c:866
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185

Referenced by _beginthread(), and _beginthreadex().

◆ thread_start()

template<typename ThreadProcedure , bool Ex>
static unsigned long WINAPI thread_start ( void *const  parameter)
throw (
)
static

Definition at line 76 of file thread.cpp.

77{
78 if (!parameter)
79 {
81 }
82
83 __acrt_thread_parameter* const context = static_cast<__acrt_thread_parameter*>(parameter);
84
86
88 {
89 context->_initialized_apartment = __acrt_RoInitialize(RO_INIT_MULTITHREADED) == S_OK;
90 }
91
92 __try
93 {
94 ThreadProcedure const procedure = reinterpret_cast<ThreadProcedure>(context->_procedure);
95 if constexpr (Ex)
96 {
97 _endthreadex(procedure(context->_context));
98 }
99 else
100 {
101 procedure(context->_context);
102 _endthreadex(0);
103 }
104 }
106 {
107 // Execution should never reach here:
109 }
111
112 // This return statement will never be reached. All execution paths result
113 // in the thread or process exiting.
114 return 0;
115}
void _exit(int exitcode)
Definition: _exit.c:25
__acrt_ptd *__cdecl __acrt_getptd(void)
begin_thread_init_policy __cdecl __acrt_get_begin_thread_init_policy(void)
@ begin_thread_init_policy_ro_initialize
_ACRTIMP int __cdecl _seh_filter_exe(_In_ unsigned long _ExceptionNum, _In_ struct _EXCEPTION_POINTERS *_ExceptionPtr)
#define S_OK
Definition: intsafe.h:52
#define __try
Definition: pseh2_64.h:188
#define __except
Definition: pseh2_64.h:189
#define __endtry
Definition: pseh2_64.h:191
#define GetExceptionInformation()
Definition: exception.h:72
#define GetExceptionCode()
Definition: exception.h:68
@ RO_INIT_MULTITHREADED
Definition: roapi.h:26
void __cdecl _endthreadex(unsigned int const return_code)
Definition: thread.cpp:276
__acrt_thread_parameter * _beginthread_context
HRESULT WINAPI __acrt_RoInitialize(RO_INIT_TYPE const init_type)