[Local GC] Unify background GC thread and server GC thread creation #14821
Conversation
src/gc/env/gcenv.ee.h
Outdated
@@ -82,6 +79,7 @@ class GCToEEInterface | |||
static void FreeStringConfigValue(const char* key); | |||
static bool IsGCThread(); | |||
static bool IsGCSpecialThread(); | |||
static bool CreateThread(void (*threadStart)(void*), void* arg, bool is_special, const wchar_t* name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would try to avoid naming things special wherever possible. special
is very cryptic.
What about calling this flag suspendable
?
(Also, it would be nice to rename IsGCSpecialThread to something more self-descriptive.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will do!
src/gc/sample/gcenv.ee.cpp
Outdated
|
||
bool GCToEEInterface::CreateThread(void (*threadStart)(void*), void* arg, bool is_special, const wchar_t* name) | ||
{ | ||
return nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method returns bool...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ack, you're right - this is left over from a previous refactor.
src/vm/gcenv.ee.h
Outdated
@@ -60,6 +59,7 @@ class GCToEEInterface : public IGCToCLR { | |||
void FreeStringConfigValue(const char* value); | |||
bool IsGCThread(); | |||
bool IsGCSpecialThread(); | |||
bool CreateThread(void (*threadStart)(void*), void* arg, bool is_special, const wchar_t* name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Indentation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think my merge tool inserts tabs... 😭 . will fix.
Looks like I have wide-char issues... I'll fix that. I'm also thinking of naming |
src/vm/gcenv.ee.cpp
Outdated
|
||
WCHAR threadName[MaxThreadNameSize]; | ||
LPWSTR wideName = nullptr; | ||
if (MultiByteToWideChar(CP_ACP, 0, name, -1 /* null terminated */, threadName, MaxThreadNameSize)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should use UTF8 here. Or even better - use SString that will do this conversion for you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will do! was not aware that SString
existed.
src/vm/gcenv.ee.cpp
Outdated
{ | ||
#ifdef BACKGROUND_GC | ||
// For background GC we revert to doing a blocking GC. | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It the BACKGROUND_GC
defined when compiling VM?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Also, CommitThreadStack is no-op in CoreCLR. You can just delete the whole block.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably not - I've been looking around and it looks like this is supposed to be defined by gcpriv.h
, so it won't have any effect in VM code.
Evidence that it does nothing is this block of code: https://github.com/dotnet/coreclr/blob/master/src/vm/finalizerthread.cpp#L1121-L1126, which definitely would not compile if BACKGROUND_GC
were defined...
at any rate, I'll just delete the block.
src/vm/gcenv.ee.cpp
Outdated
|
||
if (!args.Thread->CreateNewThread(0, threadStub, &args, wideName)) | ||
{ | ||
args.Thread->DecExternalCount(FALSE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Close ThreadStartedEvent
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Looks like this leak exists today: https://github.com/dotnet/coreclr/blob/master/src/vm/gcenv.ee.cpp#L468-L470
src/gc/env/gcenv.ee.h
Outdated
@@ -81,7 +78,8 @@ class GCToEEInterface | |||
static bool GetStringConfigValue(const char* key, const char** value); | |||
static void FreeStringConfigValue(const char* key); | |||
static bool IsGCThread(); | |||
static bool IsGCSpecialThread(); | |||
static bool CurrentThreadWasCreatedByGC(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A nit - it seems it would be nice to start this function name with the verb (WasCurrentThreadCreatedByGC)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok!
could be a server GC deadlock on startup... re-running to see if it repros. I'm currently trying to repro on a mac right now. @dotnet-bot test Ubuntu x64 Checked Innerloop Build and Test |
…restarting a non-suspended thread is incorrect
src/vm/gcenv.ee.cpp
Outdated
return true; | ||
} | ||
|
||
bool CreateUnsuspendableThread( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: CreateNonSuspendableThread
may look better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok!
I'm not sure if this is expected behavior in the PAL's implementation of |
@dotnet-bot test Ubuntu16.04 armlb Cross Debug Innerloop Build |
@dotnet-bot test Tizen armel Cross Checked Innerloop Build and Test |
Not really sure what "Perf Build and Test" is, but I believe I've addressed all outstanding code review comments and passed the CI so I think this should be ready to merge if there aren't any objections. |
thanks for the reviews! |
Apologies for the big PR - this ended up being a nontrivial refactoring that resulted in a fair amount of code shuffle.
The big idea behind this PR is to unify the creation of threads in the GC so that they all go through the same code path. The GC creates threads for two reasons:
Previously, these two threads were created with two different APIs: background GC threads were created with
GCToEEInterface::CreateBackgroundThread
while server GC threads were created withGCToOSInterface::CreateThread
. This PR unifies them to instead both useGCToEEInterface::CreateThread
, a new API.In order to accomodate these two thread types,
GCToEEInterface::CreateThread
has two code paths; one for threads that can be suspended and ones that can't. They are adapted from the existing code in bothGCToEEInterface::CreateBackgroundThread
andGCToOSInterface::CreateThread
, respectively. Some additional thread setup code that previously lived ingc.cpp
(e.g. committing the thread stack and settingThreadType_GC
on server GC thrads) was also moved toGCToEEInterface::CreateThread
, where it should be.Since
GCToEEInterface::CreateThread
doesn't set thread affinity or thread priority, two newGCToOSInterface
APIs were added to do so:GCToOSInterface::SetThreadAffinity
andGCToOSInterface::BoostThreadPriority
. These have been implemented for the non-standalone GC case and in the standalone GC case for Windows platforms:@jkotas @janvorli @sergiy-k PTAL? also cc @Maoni0 who is OOF