Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1764)

Unified Diff: node.go

Issue 1415183010: Fix race in gkvlite introduced when removing `unsafe` (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/gkvlite.git@master
Patch Set: oops Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: node.go
diff --git a/node.go b/node.go
index 88ff70f7bae914b189ff1fde9889ad1cca56a5f1..4ee1fa2bdbcf614afdb6dccaf8f17f2fd7356930 100644
--- a/node.go
+++ b/node.go
@@ -15,10 +15,10 @@ type node struct {
next *node // For free-list tracking.
}
+var nodeLocGL = sync.RWMutex{}
+
// A persistable node and its persistence location.
type nodeLoc struct {
- m sync.Mutex
-
loc *ploc // *ploc - can be nil if node is dirty (not yet persisted).
node *node // *node - can be nil if node is not fetched into memory yet.
next *nodeLoc // For free-list tracking.
@@ -27,50 +27,59 @@ type nodeLoc struct {
var empty_nodeLoc = &nodeLoc{} // Sentinel.
func (nloc *nodeLoc) Loc() *ploc {
- nloc.m.Lock()
- defer nloc.m.Unlock()
+ nodeLocGL.RLock()
+ defer nodeLocGL.RUnlock()
return nloc.loc
}
func (nloc *nodeLoc) setLoc(n *ploc) {
- nloc.m.Lock()
- defer nloc.m.Unlock()
+ nodeLocGL.Lock()
+ defer nodeLocGL.Unlock()
nloc.loc = n
}
func (nloc *nodeLoc) Node() *node {
- nloc.m.Lock()
- defer nloc.m.Unlock()
+ nodeLocGL.RLock()
+ defer nodeLocGL.RUnlock()
return nloc.node
}
func (nloc *nodeLoc) setNode(n *node) {
- nloc.m.Lock()
- defer nloc.m.Unlock()
+ nodeLocGL.Lock()
+ defer nodeLocGL.Unlock()
nloc.node = n
}
+func (nloc *nodeLoc) LocNode() (*ploc, *node) {
+ nodeLocGL.RLock()
+ defer nodeLocGL.RUnlock()
+ return nloc.loc, nloc.node
+}
+
func (nloc *nodeLoc) Copy(src *nodeLoc) *nodeLoc {
if src == nil {
return nloc.Copy(empty_nodeLoc)
}
- newloc := src.Loc()
- newnode := src.Node()
- nloc.m.Lock()
- defer nloc.m.Unlock()
- nloc.loc = newloc
- nloc.node = newnode
+ nodeLocGL.Lock()
+ defer nodeLocGL.Unlock()
+ // NOTE: This trick only works because of the global lock. No reason to lock
+ // src independently of nlock.
+ nloc.loc = src.loc
+ nloc.node = src.node
return nloc
}
func (nloc *nodeLoc) isEmpty() bool {
- return nloc == nil || (nloc.Loc().isEmpty() && nloc.Node() == nil)
+ nodeLocGL.RLock()
+ defer nodeLocGL.RUnlock()
+ return nloc == nil || (nloc.loc.isEmpty() && nloc.node == nil)
}
func (nloc *nodeLoc) write(o *Store) error {
- if nloc != nil && nloc.Loc().isEmpty() {
- node := nloc.Node()
+ loc, node := nloc.LocNode()
+
+ if nloc != nil && loc.isEmpty() {
if node == nil {
return nil
}
@@ -102,11 +111,10 @@ func (nloc *nodeLoc) read(o *Store) (n *node, err error) {
if nloc == nil {
return nil, nil
}
- n = nloc.Node()
+ loc, n := nloc.LocNode()
if n != nil {
return n, nil
}
- loc := nloc.Loc()
if loc.isEmpty() {
return nil, nil
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698