Browse Source

libs: Make bitarray functions lock parameters that aren't the caller (#2081)

This now makes bit array functions which take in a second bit array, thread
safe. Previously there was a warning on bitarray.Update to be lock the
second parameter externally if thread safety wasrequired.
This was not done within the codebase, so it was fine to change here.

Closes #2080
pull/2107/head
Dev Ojha 6 years ago
committed by Alexander Simmerl
parent
commit
bc526f18a4
2 changed files with 27 additions and 10 deletions
  1. +1
    -0
      CHANGELOG_PENDING.md
  2. +26
    -10
      libs/common/bit_array.go

+ 1
- 0
CHANGELOG_PENDING.md View File

@ -17,6 +17,7 @@ IMPROVEMENTS:
- tweak params - tweak params
- only process one block at a time to avoid starving - only process one block at a time to avoid starving
- [crypto] Switch hkdfchachapoly1305 to xchachapoly1305 - [crypto] Switch hkdfchachapoly1305 to xchachapoly1305
- [common] bit array functions which take in another parameter are now thread safe
BUG FIXES: BUG FIXES:
- [privval] fix a deadline for accepting new connections in socket private - [privval] fix a deadline for accepting new connections in socket private


+ 26
- 10
libs/common/bit_array.go View File

@ -118,7 +118,11 @@ func (bA *BitArray) Or(o *BitArray) *BitArray {
return bA.Copy() return bA.Copy()
} }
bA.mtx.Lock() bA.mtx.Lock()
defer bA.mtx.Unlock()
o.mtx.Lock()
defer func() {
bA.mtx.Unlock()
o.mtx.Unlock()
}()
c := bA.copyBits(MaxInt(bA.Bits, o.Bits)) c := bA.copyBits(MaxInt(bA.Bits, o.Bits))
for i := 0; i < len(c.Elems); i++ { for i := 0; i < len(c.Elems); i++ {
c.Elems[i] |= o.Elems[i] c.Elems[i] |= o.Elems[i]
@ -134,7 +138,11 @@ func (bA *BitArray) And(o *BitArray) *BitArray {
return nil return nil
} }
bA.mtx.Lock() bA.mtx.Lock()
defer bA.mtx.Unlock()
o.mtx.Lock()
defer func() {
bA.mtx.Unlock()
o.mtx.Unlock()
}()
return bA.and(o) return bA.and(o)
} }
@ -153,6 +161,10 @@ func (bA *BitArray) Not() *BitArray {
} }
bA.mtx.Lock() bA.mtx.Lock()
defer bA.mtx.Unlock() defer bA.mtx.Unlock()
return bA.not()
}
func (bA *BitArray) not() *BitArray {
c := bA.copy() c := bA.copy()
for i := 0; i < len(c.Elems); i++ { for i := 0; i < len(c.Elems); i++ {
c.Elems[i] = ^c.Elems[i] c.Elems[i] = ^c.Elems[i]
@ -169,7 +181,11 @@ func (bA *BitArray) Sub(o *BitArray) *BitArray {
return nil return nil
} }
bA.mtx.Lock() bA.mtx.Lock()
defer bA.mtx.Unlock()
o.mtx.Lock()
defer func() {
bA.mtx.Unlock()
o.mtx.Unlock()
}()
if bA.Bits > o.Bits { if bA.Bits > o.Bits {
c := bA.copy() c := bA.copy()
for i := 0; i < len(o.Elems)-1; i++ { for i := 0; i < len(o.Elems)-1; i++ {
@ -178,13 +194,12 @@ func (bA *BitArray) Sub(o *BitArray) *BitArray {
i := len(o.Elems) - 1 i := len(o.Elems) - 1
if i >= 0 { if i >= 0 {
for idx := i * 64; idx < o.Bits; idx++ { for idx := i * 64; idx < o.Bits; idx++ {
// NOTE: each individual GetIndex() call to o is safe.
c.setIndex(idx, c.getIndex(idx) && !o.GetIndex(idx))
c.setIndex(idx, c.getIndex(idx) && !o.getIndex(idx))
} }
} }
return c return c
} }
return bA.and(o.Not()) // Note degenerate case where o == nil
return bA.and(o.not()) // Note degenerate case where o == nil
} }
// IsEmpty returns true iff all bits in the bit array are 0 // IsEmpty returns true iff all bits in the bit array are 0
@ -332,15 +347,16 @@ func (bA *BitArray) Bytes() []byte {
// Update sets the bA's bits to be that of the other bit array. // Update sets the bA's bits to be that of the other bit array.
// The copying begins from the begin of both bit arrays. // The copying begins from the begin of both bit arrays.
// Note, the other bitarray o is not locked when reading,
// so if necessary, caller must copy or lock o prior to calling Update.
// If bA is nil, does nothing.
func (bA *BitArray) Update(o *BitArray) { func (bA *BitArray) Update(o *BitArray) {
if bA == nil || o == nil { if bA == nil || o == nil {
return return
} }
bA.mtx.Lock() bA.mtx.Lock()
defer bA.mtx.Unlock()
o.mtx.Lock()
defer func() {
bA.mtx.Unlock()
o.mtx.Unlock()
}()
copy(bA.Elems, o.Elems) copy(bA.Elems, o.Elems)
} }


Loading…
Cancel
Save