Skip to content
This repository has been archived by the owner on Jul 12, 2024. It is now read-only.

Commit

Permalink
feat: support std::thread
Browse files Browse the repository at this point in the history
  • Loading branch information
MiroKaku committed May 9, 2023
1 parent 25d71e2 commit 1321885
Show file tree
Hide file tree
Showing 11 changed files with 490 additions and 27 deletions.
2 changes: 2 additions & 0 deletions msvc/ucxxrt.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\src\crt\stl\cond.cpp" />
<ClCompile Include="..\src\crt\stl\cthread.cpp" />
<ClCompile Include="..\src\crt\stl\memory_resource.cpp" />
<ClCompile Include="..\src\crt\stl\mexcptptr.cpp" />
<ClCompile Include="..\src\crt\stl\multprec.cpp" />
Expand Down Expand Up @@ -375,6 +376,7 @@
<ClCompile Include="..\src\ucrt\startup\exit.cpp" />
<ClCompile Include="..\src\ucrt\startup\initterm.cpp" />
<ClCompile Include="..\src\ucrt\startup\onexit.cpp" />
<ClCompile Include="..\src\ucrt\startup\thread.cpp" />
<ClCompile Include="..\src\ucrt\stdio\output.cpp" />
<ClCompile Include="..\src\ucrt\stdlib\abs.cpp" />
<ClCompile Include="..\src\ucrt\stdlib\ceil.cpp" />
Expand Down
6 changes: 6 additions & 0 deletions msvc/ucxxrt.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,12 @@
<ClCompile Include="..\src\crt\stl\xnotify.cpp">
<Filter>ucxxrt\crt\stl</Filter>
</ClCompile>
<ClCompile Include="..\src\crt\stl\cthread.cpp">
<Filter>ucxxrt\crt\stl</Filter>
</ClCompile>
<ClCompile Include="..\src\ucrt\startup\thread.cpp">
<Filter>ucxxrt\ucrt\startup</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<MARMASM Include="..\src\crt\arm\chkstk.asm">
Expand Down
159 changes: 159 additions & 0 deletions src/crt/stl/cthread.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

// thread functions

#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <process.h>
#include <xthreads.h>

#include "corecrt_internal.h"

//#include <Windows.h>

//#include "awint.hpp"

namespace {
using _Thrd_start_t = int (*)(void*);

struct _Thrd_binder { // bind function pointer and data to pass to thread entry point
_Thrd_start_t func;
void* data;
_Cnd_t* cond;
_Mtx_t* mtx;
int* started;
};

using _Thrd_callback_t = unsigned int(__stdcall*)(void*);

unsigned int __stdcall _Thrd_runner(void* d) { // call thread function
_Thrd_binder b = *static_cast<_Thrd_binder*>(d);
_Mtx_lock(*b.mtx);
*b.started = 1;
_Cnd_signal(*b.cond);
_Mtx_unlock(*b.mtx);
const unsigned int res = b.func(b.data);
_Cnd_do_broadcast_at_thread_exit();
return res;
}
} // unnamed namespace

_EXTERN_C

// TRANSITION, ABI: _Thrd_exit() is preserved for binary compatibility
_CRTIMP2_PURE void _Thrd_exit(int res) { // terminate execution of calling thread
_endthreadex(res);
}

// TRANSITION, ABI: _Thrd_start() is preserved for binary compatibility
_CRTIMP2_PURE int _Thrd_start(_Thrd_t* thr, _Thrd_callback_t func, void* b) { // start a thread
thr->_Hnd = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, func, b, 0, &thr->_Id));
return thr->_Hnd == nullptr ? _Thrd_error : _Thrd_success;
}

int _Thrd_join(_Thrd_t thr, int* code) { // returns when thread terminates
if (ZwWaitForSingleObject(thr._Hnd, FALSE, nullptr) != STATUS_SUCCESS) {
return _Thrd_error;
}

if (code) { // TRANSITION, ABI: code is preserved for binary compatibility
THREAD_BASIC_INFORMATION info{};

if (!NT_SUCCESS(ZwQueryInformationThread(thr._Hnd, ThreadBasicInformation,
&info, sizeof(info), nullptr))) {
return _Thrd_error;
}
*code = static_cast<int>(info.ExitStatus);
}

return NT_SUCCESS(ZwClose(thr._Hnd)) ? _Thrd_success : _Thrd_error;
}

int _Thrd_detach(_Thrd_t thr) { // tell OS to release thread's resources when it terminates
return NT_SUCCESS(ZwClose(thr._Hnd)) ? _Thrd_success : _Thrd_error;
}

void _Thrd_sleep(const xtime* xt) { // suspend thread until time xt
xtime now;
xtime_get(&now, TIME_UTC);
do { // sleep and check time

LARGE_INTEGER wait_time{};
wait_time.QuadPart = Int32x32To64(_Xtime_diff_to_millis2(xt, &now), -10000);
(void)KeDelayExecutionThread(KernelMode, FALSE, &wait_time);

xtime_get(&now, TIME_UTC);
} while (now.sec < xt->sec || now.sec == xt->sec && now.nsec < xt->nsec);
}

void _Thrd_yield() { // surrender remainder of timeslice
(void)ZwYieldExecution();
}

// TRANSITION, ABI: _Thrd_equal() is preserved for binary compatibility
_CRTIMP2_PURE int _Thrd_equal(_Thrd_t thr0, _Thrd_t thr1) { // return 1 if thr0 and thr1 identify same thread
return thr0._Id == thr1._Id;
}

// TRANSITION, ABI: _Thrd_current() is preserved for binary compatibility
_CRTIMP2_PURE _Thrd_t _Thrd_current() { // return _Thrd_t identifying current thread
_Thrd_t result;
result._Hnd = nullptr;
result._Id = static_cast<_Thrd_id_t>(reinterpret_cast<size_t>(PsGetCurrentThreadId()));
return result;
}

_Thrd_id_t _Thrd_id() { // return unique id for current thread
return static_cast<_Thrd_id_t>(reinterpret_cast<size_t>(PsGetCurrentThreadId()));
}

unsigned int _Thrd_hardware_concurrency() { // return number of processors
return KeQueryActiveProcessorCount(nullptr);
}

// TRANSITION, ABI: _Thrd_create() is preserved for binary compatibility
_CRTIMP2_PURE int _Thrd_create(_Thrd_t* thr, _Thrd_start_t func, void* d) { // create thread
int res;
_Thrd_binder b;
int started = 0;
_Cnd_t cond;
_Mtx_t mtx;
_Cnd_init(&cond);
_Mtx_init(&mtx, _Mtx_plain);
b.func = func;
b.data = d;
b.cond = &cond;
b.mtx = &mtx;
b.started = &started;
_Mtx_lock(mtx);
if ((res = _Thrd_start(thr, _Thrd_runner, &b)) == _Thrd_success) { // wait for handshake
while (!started) {
_Cnd_wait(cond, mtx);
}
}
_Mtx_unlock(mtx);
_Cnd_destroy(cond);
_Mtx_destroy(mtx);
return res;
}

_END_EXTERN_C

/*
* This file is derived from software bearing the following
* restrictions:
*
* (c) Copyright William E. Kempf 2001
*
* Permission to use, copy, modify, distribute and sell this
* software and its documentation for any purpose is hereby
* granted without fee, provided that the above copyright
* notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting
* documentation. William E. Kempf makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*/
1 change: 0 additions & 1 deletion src/crt/stl/primitives.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ namespace Concurrency {
const auto status = KeWaitForSingleObject(&m_semaphore, Executive,
KernelMode, FALSE, timeout == INFINITE ? nullptr : &wait_time);
if (status != STATUS_SUCCESS) {
_set_errno(status);
return false;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/crt/vcruntime/sys_common.inl
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ static __declspec(noinline) long __cdecl __scrt_common_main_seh(PDRIVER_OBJECT d

return main_result;
}
__except (_seh_filter_sys(GetExceptionCode(), GetExceptionInformation()))
__except (_seh_filter_dll(GetExceptionCode(), GetExceptionInformation()))
{
// Note: We should never reach this except clause.
int const main_result = GetExceptionCode();
Expand Down
11 changes: 0 additions & 11 deletions src/crt/vcruntime/vcstartup_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,6 @@



//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// Exception Filters for main()
//
//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

extern "C" int __cdecl _seh_filter_sys(
_In_ unsigned long _ExceptionNum,
_In_ struct _EXCEPTION_POINTERS* _ExceptionPtr
);

//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// Utility Macros
Expand Down
35 changes: 35 additions & 0 deletions src/ucrt/inc/corecrt_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,36 @@ void __cdecl __acrt_initialize_new_handler(_In_opt_ void* encoded_null);



//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// AppCRT Threading
//
//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
typedef struct __acrt_thread_parameter
{
// The thread procedure and context argument
void* _procedure;
void* _context;

// The handle for the newly created thread. This is initialized only from
// _beginthread (not _beginthreadex). When a thread created via _beginthread
// exits, it frees this handle.
HANDLE _thread_handle;

// The handle for the module in which the user's thread procedure is defined.
// This may be null if the handle could not be obtained. This handle enables
// us to bump the reference count of the user's module, to ensure that the
// module will not be unloaded while the thread is executing. When the thread
// exits, it frees this handle.
HMODULE _module_handle;

// This flag is true if RoInitialized was called on the thread to initialize
// it into the MTA.
bool _initialized_apartment;
} __acrt_thread_parameter;



//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// AppCRT Per-Thread Data
Expand All @@ -133,6 +163,11 @@ typedef struct __acrt_ptd
// The thread-local invalid parameter handler
_invalid_parameter_handler _thread_local_iph;

// If this thread was started by the CRT (_beginthread or _beginthreadex),
// then this points to the context with which the thread was created. If
// this thread was not started by the CRT, this pointer is null.
__acrt_thread_parameter* _beginthread_context;

} __acrt_ptd;

__acrt_ptd* __cdecl __acrt_getptd(void);
Expand Down
5 changes: 3 additions & 2 deletions src/ucrt/internal/per_thread_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,9 @@ VOID NTAPI __acrt_ptd_table_free(
)
{
auto ptd = reinterpret_cast<__acrt_ptd*>(static_cast<uint8_t*>(buffer) + sizeof(RTL_BALANCED_LINKS));
free(ptd->_strerror_buffer);
free(ptd->_wcserror_buffer);
_free_crt(ptd->_strerror_buffer);
_free_crt(ptd->_wcserror_buffer);
_free_crt(ptd->_beginthread_context);

return ExFreeToNPagedLookasideList(&__acrt_startup_ptd_pools, buffer);
}
Expand Down
2 changes: 1 addition & 1 deletion src/ucrt/misc/exception_filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@


// Wrapper that only calls the exception filter for C++ exceptions
extern "C" int __cdecl _seh_filter_sys(
extern "C" int __cdecl _seh_filter_dll(
unsigned long const xcptnum,
PEXCEPTION_POINTERS const /*pxcptinfoptrs*/
)
Expand Down
Loading

0 comments on commit 1321885

Please sign in to comment.