LOCK_THREAD (thread);
/* MonoThread::interruption_requested can only be changed with atomics */
- if (mono_thread_clear_interruption_requested (thread)) {
- /* this will consume pending APC calls */
+ if (!mono_thread_clear_interruption_requested (thread)) {
+ UNLOCK_THREAD (thread);
+ return NULL;
+ }
+
+ /* this will consume pending APC calls */
#ifdef HOST_WIN32
- WaitForSingleObjectEx (GetCurrentThread(), 0, TRUE);
+ WaitForSingleObjectEx (GetCurrentThread(), 0, TRUE);
#endif
- /* Clear the interrupted flag of the thread so it can wait again */
- mono_thread_info_clear_self_interrupt ();
- }
+ /* Clear the interrupted flag of the thread so it can wait again */
+ mono_thread_info_clear_self_interrupt ();
/* If there's a pending exception and an AbortRequested, the pending exception takes precedence */
if (sys_thread->pending_exception) {
public static void Main ()
{
bool finished = false;
+ int can_gc = 0;
Thread t1 = Thread.CurrentThread;
Thread t2 = new Thread (() => {
while (!finished) {
- GC.Collect ();
+ int local_can_gc = can_gc;
+ if (local_can_gc > 0 && Interlocked.CompareExchange (ref can_gc, local_can_gc - 1, local_can_gc) == local_can_gc)
+ GC.Collect ();
try {
t1.Resume ();
Thread.Sleep (10);
- for (int i = 0; i < 50 * 40 * 20; ++i) {
+ for (int i = 0; i < 50 * 40 * 5; ++i) {
+ Interlocked.Increment (ref can_gc);
Thread.CurrentThread.Suspend ();
if ((i + 1) % (50) == 0)
Console.Write (".");
public static void Main ()
{
bool finished = false;
+ int can_gc = 0;
Thread t1 = new Thread (() => {
while (!finished) {}
Thread t2 = new Thread (() => {
while (!finished) {
- GC.Collect ();
+ int local_can_gc = can_gc;
+ if (local_can_gc > 0 && Interlocked.CompareExchange (ref can_gc, local_can_gc - 1, local_can_gc) == local_can_gc)
+ GC.Collect ();
Thread.Yield ();
}
});
Thread.Sleep (10);
- for (int i = 0; i < 50 * 40 * 20; ++i) {
+ for (int i = 0; i < 50 * 40 * 5; ++i) {
t1.Suspend ();
+ Interlocked.Increment (ref can_gc);
Thread.Yield ();
t1.Resume ();
if ((i + 1) % (50) == 0)