-
Notifications
You must be signed in to change notification settings - Fork 575
[NativeAOT] Use POSIX primitives for GC bridge processing #12141
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9e579ea
8d263b1
a8d4e86
58dd1b6
12bc257
98fcba6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,7 @@ | ||
| #include <cerrno> | ||
| #include <pthread.h> | ||
| #include <semaphore.h> | ||
|
|
||
| #include <host/gc-bridge.hh> | ||
| #include <host/bridge-processing.hh> | ||
| #include <host/os-bridge.hh> | ||
|
|
@@ -7,6 +11,41 @@ | |
|
|
||
| using namespace xamarin::android; | ||
|
|
||
| void GCBridge::initialize_shared_args_semaphore () noexcept | ||
| { | ||
| int ret = sem_init (&shared_args_semaphore, 0, 0); | ||
| abort_unless (ret == 0, "Failed to initialize GC bridge semaphore"); | ||
| } | ||
|
|
||
| void GCBridge::start_bridge_processing_thread () noexcept | ||
| { | ||
| pthread_t thread {}; | ||
| int ret = pthread_create (&thread, nullptr, bridge_processing_thread_entry, nullptr); | ||
| abort_unless (ret == 0, "Failed to create GC bridge processing thread"); | ||
|
|
||
| ret = pthread_detach (thread); | ||
| abort_unless (ret == 0, "Failed to detach GC bridge processing thread"); | ||
| } | ||
|
|
||
| void GCBridge::publish_shared_args (MarkCrossReferencesArgs *args) noexcept | ||
| { | ||
| __atomic_store_n (&shared_args, args, __ATOMIC_RELEASE); | ||
|
|
||
| int ret = sem_post (&shared_args_semaphore); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤖 💡 Native C++ — (Rule: Documentation of concurrency intent) |
||
| abort_unless (ret == 0, "Failed to release GC bridge semaphore"); | ||
| } | ||
|
|
||
| auto GCBridge::wait_for_shared_args () noexcept -> MarkCrossReferencesArgs* | ||
| { | ||
| int ret; | ||
| do { | ||
| ret = sem_wait (&shared_args_semaphore); | ||
| } while (ret == -1 && errno == EINTR); | ||
| abort_unless (ret == 0, "Failed to acquire GC bridge semaphore"); | ||
|
|
||
| return __atomic_load_n (&shared_args, __ATOMIC_ACQUIRE); | ||
| } | ||
|
|
||
| void GCBridge::initialize_on_onload (JNIEnv *env) noexcept | ||
| { | ||
| abort_if_invalid_pointer_argument (env, "env"); | ||
|
|
@@ -55,8 +94,7 @@ void GCBridge::mark_cross_references (MarkCrossReferencesArgs *args) noexcept | |
| abort_unless (args->CrossReferences != nullptr || args->CrossReferenceCount == 0, "CrossReferences must not be null if CrossReferenceCount is greater than 0"); | ||
| log_mark_cross_references_args_if_enabled (args); | ||
|
|
||
| shared_args.store (args); | ||
| shared_args_semaphore.release (); | ||
| publish_shared_args (args); | ||
| } | ||
|
|
||
| void GCBridge::bridge_processing () noexcept | ||
|
|
@@ -66,8 +104,7 @@ void GCBridge::bridge_processing () noexcept | |
|
|
||
| while (true) { | ||
| // wait until mark cross references args are set by the GC callback | ||
| shared_args_semaphore.acquire (); | ||
| MarkCrossReferencesArgs *args = shared_args.load (); | ||
| MarkCrossReferencesArgs *args = wait_for_shared_args (); | ||
|
|
||
| bridge_processing_started_callback (args); | ||
|
|
||
|
|
@@ -78,6 +115,12 @@ void GCBridge::bridge_processing () noexcept | |
| } | ||
| } | ||
|
|
||
| auto GCBridge::bridge_processing_thread_entry ([[maybe_unused]] void *arg) noexcept -> void* | ||
| { | ||
| bridge_processing (); | ||
| return nullptr; | ||
| } | ||
|
|
||
| [[gnu::always_inline]] | ||
| void GCBridge::log_mark_cross_references_args_if_enabled (MarkCrossReferencesArgs *args) noexcept | ||
| { | ||
|
|
||
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.
🤖 💡 Native C++ — Consider creating the worker already-detached via
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED)beforepthread_create, matching the sibling pattern inassembly-store.cc(start_writer_locked). The current create-then-pthread_detachsequence works, but a single-step detached creation is consistent with the rest of the CLR host and avoids a separate failure/abort path.While here,
pthread_setname_np (thread, "gc-bridge")would make this worker identifiable inlogcat/tombstones and traces — helpful given it runs the GC bridge on every collection.(Rule: Consistency with repo native patterns)