-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
boehmgc: Crude support for coroutines
Fixes the problem where a stack pointer outside the original thread causes the collector to crash. It could be made more accurate by recording the stack pointer every time we switch to a coroutine. We can use this information to update our own coroutine stacks like normal data. When the stack pointer is on a thread, we can add a field to GC_thread "fallback_sp" to be used when the thread sp is outside the original thread range.
- Loading branch information
Showing
2 changed files
with
51 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
diff --git a/pthread_stop_world.c b/pthread_stop_world.c | ||
index 1cee6a0b..8977b0dd 100644 | ||
--- a/pthread_stop_world.c | ||
+++ b/pthread_stop_world.c | ||
@@ -674,6 +674,8 @@ GC_INNER void GC_push_all_stacks(void) | ||
struct GC_traced_stack_sect_s *traced_stack_sect; | ||
pthread_t self = pthread_self(); | ||
word total_size = 0; | ||
+ size_t stack_limit; | ||
+ pthread_attr_t pattr; | ||
|
||
if (!EXPECT(GC_thr_initialized, TRUE)) | ||
GC_thr_init(); | ||
@@ -723,6 +725,30 @@ GC_INNER void GC_push_all_stacks(void) | ||
hi = p->altstack + p->altstack_size; | ||
/* FIXME: Need to scan the normal stack too, but how ? */ | ||
/* FIXME: Assume stack grows down */ | ||
+ } else { | ||
+ if (pthread_getattr_np(p->id, &pattr)) { | ||
+ ABORT("GC_push_all_stacks: pthread_getattr_np failed!"); | ||
+ } | ||
+ if (pthread_attr_getstacksize(&pattr, &stack_limit)) { | ||
+ ABORT("GC_push_all_stacks: pthread_attr_getstacksize failed!"); | ||
+ } | ||
+ // When a thread goes into a coroutine, we lose its original sp until | ||
+ // control flow returns to the thread. | ||
+ // While in the coroutine, the sp points outside the thread stack, | ||
+ // so we can detect this and push the entire thread stack instead, | ||
+ // as an approximation. | ||
+ // We assume that the coroutine has similarly added its entire stack. | ||
+ // This could be made accurate by cooperating with the application | ||
+ // via new functions and/or callbacks. | ||
+ #ifndef STACK_GROWS_UP | ||
+ if (lo >= hi || lo < hi - stack_limit) { // sp outside stack | ||
+ lo = hi - stack_limit; | ||
+ } | ||
+ #else | ||
+ if (lo < hi || lo >= hi + stack_limit) { // sp outside stack | ||
+ lo = hi + stack_limit; | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
roberth
Author
Member
|
||
+ } | ||
+ #endif | ||
} | ||
GC_push_all_stack_sections(lo, hi, traced_stack_sect); | ||
# ifdef STACK_GROWS_UP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
So, if sp is outside stack, we scan the entire stack (e.g. 8MB by default on Linux), right? But it might contain unmapped pages and thus cause SIGSEV in GC_mark_from. Is there some trick on nix side to avoid this?