Commit 58030c54 authored by Dmitriy Vyukov's avatar Dmitriy Vyukov

runtime: change Note from union to struct

Unions can break precise GC.
Update #5193.

R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/8362046
parent d6174543
...@@ -111,9 +111,9 @@ runtime·noteclear(Note *n) ...@@ -111,9 +111,9 @@ runtime·noteclear(Note *n)
void void
runtime·notewakeup(Note *n) runtime·notewakeup(Note *n)
{ {
if(runtime·xchg(&n->key, 1)) if(runtime·xchg((uint32*)&n->key, 1))
runtime·throw("notewakeup - double wakeup"); runtime·throw("notewakeup - double wakeup");
runtime·futexwakeup(&n->key, 1); runtime·futexwakeup((uint32*)&n->key, 1);
} }
void void
...@@ -121,8 +121,8 @@ runtime·notesleep(Note *n) ...@@ -121,8 +121,8 @@ runtime·notesleep(Note *n)
{ {
if(m->profilehz > 0) if(m->profilehz > 0)
runtime·setprof(false); runtime·setprof(false);
while(runtime·atomicload(&n->key) == 0) while(runtime·atomicload((uint32*)&n->key) == 0)
runtime·futexsleep(&n->key, 0, -1); runtime·futexsleep((uint32*)&n->key, 0, -1);
if(m->profilehz > 0) if(m->profilehz > 0)
runtime·setprof(true); runtime·setprof(true);
} }
...@@ -137,15 +137,15 @@ runtime·notetsleep(Note *n, int64 ns) ...@@ -137,15 +137,15 @@ runtime·notetsleep(Note *n, int64 ns)
return; return;
} }
if(runtime·atomicload(&n->key) != 0) if(runtime·atomicload((uint32*)&n->key) != 0)
return; return;
if(m->profilehz > 0) if(m->profilehz > 0)
runtime·setprof(false); runtime·setprof(false);
deadline = runtime·nanotime() + ns; deadline = runtime·nanotime() + ns;
for(;;) { for(;;) {
runtime·futexsleep(&n->key, 0, ns); runtime·futexsleep((uint32*)&n->key, 0, ns);
if(runtime·atomicload(&n->key) != 0) if(runtime·atomicload((uint32*)&n->key) != 0)
break; break;
now = runtime·nanotime(); now = runtime·nanotime();
if(now >= deadline) if(now >= deadline)
......
...@@ -118,7 +118,7 @@ runtime·unlock(Lock *l) ...@@ -118,7 +118,7 @@ runtime·unlock(Lock *l)
void void
runtime·noteclear(Note *n) runtime·noteclear(Note *n)
{ {
n->waitm = nil; n->key = 0;
} }
void void
...@@ -127,8 +127,8 @@ runtime·notewakeup(Note *n) ...@@ -127,8 +127,8 @@ runtime·notewakeup(Note *n)
M *mp; M *mp;
do do
mp = runtime·atomicloadp(&n->waitm); mp = runtime·atomicloadp((void**)&n->key);
while(!runtime·casp(&n->waitm, mp, (void*)LOCKED)); while(!runtime·casp((void**)&n->key, mp, (void*)LOCKED));
// Successfully set waitm to LOCKED. // Successfully set waitm to LOCKED.
// What was it before? // What was it before?
...@@ -148,8 +148,8 @@ runtime·notesleep(Note *n) ...@@ -148,8 +148,8 @@ runtime·notesleep(Note *n)
{ {
if(m->waitsema == 0) if(m->waitsema == 0)
m->waitsema = runtime·semacreate(); m->waitsema = runtime·semacreate();
if(!runtime·casp(&n->waitm, nil, m)) { // must be LOCKED (got wakeup) if(!runtime·casp((void**)&n->key, nil, m)) { // must be LOCKED (got wakeup)
if(n->waitm != (void*)LOCKED) if(n->key != LOCKED)
runtime·throw("notesleep - waitm out of sync"); runtime·throw("notesleep - waitm out of sync");
return; return;
} }
...@@ -176,8 +176,8 @@ runtime·notetsleep(Note *n, int64 ns) ...@@ -176,8 +176,8 @@ runtime·notetsleep(Note *n, int64 ns)
m->waitsema = runtime·semacreate(); m->waitsema = runtime·semacreate();
// Register for wakeup on n->waitm. // Register for wakeup on n->waitm.
if(!runtime·casp(&n->waitm, nil, m)) { // must be LOCKED (got wakeup already) if(!runtime·casp((void**)&n->key, nil, m)) { // must be LOCKED (got wakeup already)
if(n->waitm != (void*)LOCKED) if(n->key != LOCKED)
runtime·throw("notetsleep - waitm out of sync"); runtime·throw("notetsleep - waitm out of sync");
return; return;
} }
...@@ -212,10 +212,10 @@ runtime·notetsleep(Note *n, int64 ns) ...@@ -212,10 +212,10 @@ runtime·notetsleep(Note *n, int64 ns)
// so that any notewakeup racing with the return does not // so that any notewakeup racing with the return does not
// try to grant us the semaphore when we don't expect it. // try to grant us the semaphore when we don't expect it.
for(;;) { for(;;) {
mp = runtime·atomicloadp(&n->waitm); mp = runtime·atomicloadp((void**)&n->key);
if(mp == m) { if(mp == m) {
// No wakeup yet; unregister if possible. // No wakeup yet; unregister if possible.
if(runtime·casp(&n->waitm, mp, nil)) if(runtime·casp((void**)&n->key, mp, nil))
return; return;
} else if(mp == (M*)LOCKED) { } else if(mp == (M*)LOCKED) {
// Wakeup happened so semaphore is available. // Wakeup happened so semaphore is available.
......
...@@ -54,7 +54,7 @@ typedef struct Lock Lock; ...@@ -54,7 +54,7 @@ typedef struct Lock Lock;
typedef struct M M; typedef struct M M;
typedef struct P P; typedef struct P P;
typedef struct Mem Mem; typedef struct Mem Mem;
typedef union Note Note; typedef struct Note Note;
typedef struct Slice Slice; typedef struct Slice Slice;
typedef struct Stktop Stktop; typedef struct Stktop Stktop;
typedef struct String String; typedef struct String String;
...@@ -163,10 +163,12 @@ struct Lock ...@@ -163,10 +163,12 @@ struct Lock
// Used to be a union, but unions break precise GC. // Used to be a union, but unions break precise GC.
uintptr key; uintptr key;
}; };
union Note struct Note
{ {
uint32 key; // futex-based impl // Futex-based impl treats it as uint32 key,
M* waitm; // waiting M (sema-based impl) // while sema-based impl as M* waitm.
// Used to be a union, but unions break precise GC.
uintptr key;
}; };
struct String struct String
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment