Skip to content

Instantly share code, notes, and snippets.

@radcapricorn
Created May 25, 2017 02:51
Show Gist options
  • Save radcapricorn/45c3fe9587ffa7d122ec9010837ce9e9 to your computer and use it in GitHub Desktop.
Save radcapricorn/45c3fe9587ffa7d122ec9010837ce9e9 to your computer and use it in GitHub Desktop.
Spinlock bug
import core.thread;
import core.sync.semaphore;
import core.atomic;
import std.stdio;
import std.typecons;
shared uint initialized;
__gshared uint a;
__gshared uint b;
auto makeGlobalWithSpinLock()
{
if (!atomicLoad(initialized))
{
for (;;)
{
if (atomicLoad(initialized) > uint.max / 2)
break;
if (atomicOp!"+="(initialized, 1) == 1)
{
a = 1;
b = 1;
atomicOp!"+="(initialized, uint.max / 2);
break;
}
atomicOp!"-="(initialized, 1);
}
}
return tuple(a, b);
}
void threadFunc(int id, Semaphore start, Semaphore end)
{
for (;;)
{
start.wait;
auto ab = makeGlobalWithSpinLock();
if (ab[0] != 1) writefln("bugbug in thread %d, reorder a", id);
if (ab[1] != 1) writefln("bugbug in thread %d, reorder b", id);
end.notify;
}
}
Thread spawnThread(int id, Semaphore start, Semaphore end)
{
static class Impl : Thread {
int id;
Semaphore s, e;
this(int id, Semaphore s, Semaphore e)
{
this.id = id;
this.s = s;
this.e = e;
super(&run);
}
void run()
{
threadFunc(this.id, this.s, this.e);
}
}
auto thr = new Impl(id, start, end);
thr.start;
return thr;
}
void main()
{
Semaphore start1 = new Semaphore();
Semaphore start2 = new Semaphore();
Semaphore end = new Semaphore();
auto t1 = spawnThread(1, start1, end);
auto t2 = spawnThread(2, start2, end);
for (;;)
{
// reset state
a = 0;
b = 0;
initialized = 0;
// propagate changes made above
asm { mfence; }
// allow threads to start next iteration
start1.notify;
start2.notify;
auto ab = makeGlobalWithSpinLock();
if (ab[0] != 1) writeln("bugbug in main, reorder a");
if (ab[1] != 1) writeln("bugbug in main, reorder b");
// wait for both threads to finish their iteration
end.wait;
end.wait;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment