[D-runtime] A cooperative suspension API

Alex Rønne Petersen xtzgzorex at gmail.com
Sat May 5 08:11:50 PDT 2012


> Here the compiler can coalesce every read to g_shouldSuspend into a single read because it assumes g_shouldSuspend is thread local and sees no code in the loop that could potentially change the variable. Hence why you need volatile to force the compiler to always read from memory.

OK, I understand what you are getting at. A C compiler would probably
make this assumption at -O3 or something. However, things aren't quite
the same in D as they are in C here. In D, __gshared explicitly tells
the compiler "this variable is global -- it is shared among threads --
and can change at any time". If a compiler still chooses to do the
read only once, then it is generating wrong code. Keep in mind that in
D, we have an explicit differentiation between thread-local and global
data.

Besides, if the compiler did do this optimization, I think a lot of
druntime and phobos code would break.

Regards,
Alex

On Sat, May 5, 2012 at 4:54 PM, Michel Fortin <michel.fortin at michelf.com> wrote:
> Le 2012-05-05 à 10:37, Alex Rønne Petersen a écrit :
>
>> I don't follow. Why would inlining the function have any impact on how
>> many times the variable is actually read? That seems like a totally
>> separate issue.
>
> Ok, for one thing, I quoted the wrong code. I'm still unsure about isCooperative, but I meant to quote shouldSuspend and suspendIfNeeded.
>
>    __gshared bool g_shouldSuspend; // set by thread_suspendAll()
>
>    @property static bool shouldSuspend()
>    {
>        return g_shouldSuspend;
>    }
>
>    final void suspendIfNeeded()
>    {
>        if (g_shouldSuspend) // can only race against thread_suspendAll() setting it to false, which is ok
>            suspend(this);
>    }
>
> If you inline shouldSuspend and suspendIfNeeded inside a loop in some function, here's what you get:
>
>        int i = 0;
>        while (true)
>        {
>                if (g_shouldSuspend)
>                        suspend();
>                ++i;
>        }
>
> Here the compiler can coalesce every read to g_shouldSuspend into a single read because it assumes g_shouldSuspend is thread local and sees no code in the loop that could potentially change the variable. Hence why you need volatile to force the compiler to always read from memory.
>
> The optimized code would behave like this one, which is obviously not what you want:
>
>        int i = 0;
>        bool local_shouldSuspend = g_shouldSuspend; // single read from memory to a register
>        while (true)
>        {
>                if (local_shouldSuspend)
>                        suspend();
>                ++i;
>        }
>
>
> --
> Michel Fortin
> michel.fortin at michelf.com
> http://michelf.com/
>
>
>
>
>
> _______________________________________________
> D-runtime mailing list
> D-runtime at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/d-runtime


More information about the D-runtime mailing list