{"id":23177,"date":"2006-06-07T21:02:00","date_gmt":"2006-06-07T21:02:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/maoni\/2006\/06\/07\/suspending-and-resuming-threads-for-gc\/"},"modified":"2021-10-04T16:34:40","modified_gmt":"2021-10-04T23:34:40","slug":"suspending-and-resuming-threads-for-gc","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/suspending-and-resuming-threads-for-gc\/","title":{"rendered":"Suspending and resuming threads for GC"},"content":{"rendered":"<p><P><SPAN>First of all, suspension and resumption of threads is not really part of the GC. GC calls functions to do the suspension and the resumption as a service provided in the CLR. Other components in the CLR also use this service such as the debugger implementation. But it\u2019s true that suspending and resuming because of the GC is the most significant usage of this service.<\/SPAN><\/P>\n<P><SPAN>Secondly, how threads are suspended and resumed works the same way in Workstation GC (with or without Concurrent GC) and Server GC. Workstation GC with Concurrent GC just suspends and resumes threads more times than the other two cases. <\/SPAN><\/P>\n<P><SPAN>Now let&#8217;s talk about suspension. A managed thread could be running either managed code or native code at the time. If it\u2019s running native code which can either be from <\/SPAN><\/P>\n<P><SPAN><SPAN>\u00b7<SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/SPAN><\/SPAN><\/SPAN><SPAN>the EE (Execution Engine) of the CLR \u2013 for example, EE implements some helper function for your managed call which is on the stack at the time. In this case the EE code tells the suspension code how it should be suspended. A common scenario is the EE code will wait for GC to finish so the suspension code doesn\u2019t need to suspend it (it already suspends itself). Or <\/SPAN><\/P>\n<P><SPAN><SPAN>\u00b7<SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/SPAN><\/SPAN><\/SPAN><SPAN>the native code is not from the EE, which means it\u2019s running some native code via Interop, we don\u2019t need to suspend this thread because it shouldn\u2019t be doing anything with managed objects that can are not pinned. When this thread needs to return to managed code, however, it will need to check if a GC is in progress and if so it needs to wait for GC to finish.<\/SPAN><\/P>\n<P><SPAN>For the managed threads that <I>are running managed code<\/I> it can be in either <\/SPAN><\/P>\n<P><SPAN><SPAN>\u00a7<SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/SPAN><\/SPAN><\/SPAN><SPAN>a mode where it can be stopped at any time (because the JIT recorded enough info for each instruction) in which case it can be suspended right there. We then redirect it to some function that will make this thread wait for GC to complete. Or <\/SPAN><\/P>\n<P><SPAN><SPAN>\u00b7<SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/SPAN><\/SPAN><\/SPAN><SPAN>a mode where it can\u2019t be stopped at any time, in which case the thread\u2019s return address will be hijacked, meaning we replace the return address by a stub which will suspend this thread. What this stub does is it will suspend this thread to wait for GC to finish.<\/SPAN><\/P>\n<P><SPAN>In both case the function that was used to suspend the thread knows how to resume them correctly when GC finishes.<\/SPAN><\/P>\n<P><SPAN>Resumption works much simpler. When a GC is finished, all the threads that were suspended will wake up (they were waiting on an event for GC to finish) to resume execution.&nbsp;<\/SPAN><\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>First of all, suspension and resumption of threads is not really part of the GC. GC calls functions to do the suspension and the resumption as a service provided in the CLR. Other components in the CLR also use this service such as the debugger implementation. But it\u2019s true that suspending and resuming because of [&hellip;]<\/p>\n","protected":false},"author":3542,"featured_media":58792,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685],"tags":[3010,3011],"class_list":["post-23177","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","tag-general","tag-maoniposts"],"acf":[],"blog_post_summary":"<p>First of all, suspension and resumption of threads is not really part of the GC. GC calls functions to do the suspension and the resumption as a service provided in the CLR. Other components in the CLR also use this service such as the debugger implementation. But it\u2019s true that suspending and resuming because of [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/23177","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/3542"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=23177"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/23177\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=23177"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=23177"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=23177"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}