diff options
Diffstat (limited to 'vendor/modernc.org/sqlite/lib/mutex.go')
| -rw-r--r-- | vendor/modernc.org/sqlite/lib/mutex.go | 251 |
1 files changed, 83 insertions, 168 deletions
diff --git a/vendor/modernc.org/sqlite/lib/mutex.go b/vendor/modernc.org/sqlite/lib/mutex.go index 0780f5f94..305b24610 100644 --- a/vendor/modernc.org/sqlite/lib/mutex.go +++ b/vendor/modernc.org/sqlite/lib/mutex.go @@ -59,170 +59,40 @@ var ( }{mutexNotheld})), } - MutexCounters = libc.NewPerfCounter([]string{ - "enter-fast", - "enter-recursive", - "enter-recursive-loop", - "try-fast", - "try-recursive", - }) - MutexEnterCallers = libc.NewStackCapture(4) - - mutexes mutexPool - - mutexApp1 = mutexes.alloc(false) - mutexApp2 = mutexes.alloc(false) - mutexApp3 = mutexes.alloc(false) - mutexLRU = mutexes.alloc(false) - mutexMaster = mutexes.alloc(false) - mutexMem = mutexes.alloc(false) - mutexOpen = mutexes.alloc(false) - mutexPMem = mutexes.alloc(false) - mutexPRNG = mutexes.alloc(false) - mutexVFS1 = mutexes.alloc(false) - mutexVFS2 = mutexes.alloc(false) - mutexVFS3 = mutexes.alloc(false) + mutexApp10 mutex + mutexApp20 mutex + mutexApp30 mutex + mutexLRU0 mutex + mutexMaster0 mutex + mutexMem0 mutex + mutexOpen0 mutex + mutexPMem0 mutex + mutexPRNG0 mutex + mutexVFS10 mutex + mutexVFS20 mutex + mutexVFS30 mutex + + mutexApp1 = uintptr(unsafe.Pointer(&mutexApp10)) + mutexApp2 = uintptr(unsafe.Pointer(&mutexApp20)) + mutexApp3 = uintptr(unsafe.Pointer(&mutexApp30)) + mutexLRU = uintptr(unsafe.Pointer(&mutexLRU0)) + mutexMaster = uintptr(unsafe.Pointer(&mutexMaster0)) + mutexMem = uintptr(unsafe.Pointer(&mutexMem0)) + mutexOpen = uintptr(unsafe.Pointer(&mutexOpen0)) + mutexPMem = uintptr(unsafe.Pointer(&mutexPMem0)) + mutexPRNG = uintptr(unsafe.Pointer(&mutexPRNG0)) + mutexVFS1 = uintptr(unsafe.Pointer(&mutexVFS10)) + mutexVFS2 = uintptr(unsafe.Pointer(&mutexVFS20)) + mutexVFS3 = uintptr(unsafe.Pointer(&mutexVFS30)) ) -type mutexPool struct { - sync.Mutex - a []*[256]mutex - freeList []int -} - -func mutexFromPtr(p uintptr) *mutex { - if p == 0 { - return nil - } - - ix := p - 1 - - mutexes.Lock() - defer mutexes.Unlock() - - return &mutexes.a[ix>>8][ix&255] -} - -func (m *mutexPool) alloc(recursive bool) uintptr { - m.Lock() - defer m.Unlock() - - n := len(m.freeList) - if n == 0 { - outer := len(m.a) << 8 - m.a = append(m.a, &[256]mutex{}) - for i := 0; i < 256; i++ { - m.freeList = append(m.freeList, outer+i) - } - n = len(m.freeList) - } - ix := m.freeList[n-1] - outer := ix >> 8 - inner := ix & 255 - m.freeList = m.freeList[:n-1] - p := &m.a[outer][inner] - p.poolIndex = ix - p.recursive = recursive - return uintptr(ix) + 1 -} - -func (m *mutexPool) free(p uintptr) { - ptr := mutexFromPtr(p) - ix := ptr.poolIndex - *ptr = mutex{} - - m.Lock() - defer m.Unlock() - - m.freeList = append(m.freeList, ix) -} - type mutex struct { sync.Mutex - wait sync.Mutex - - poolIndex int - - cnt int32 - id int32 - + cnt int32 + id int32 // tls.ID recursive bool } -func (m *mutex) enter(id int32) { - // MutexEnterCallers.Record() - if !m.recursive { - // MutexCounters.Inc(0) - m.Lock() - m.id = id - return - } - - // MutexCounters.Inc(1) - for { - m.Lock() - switch m.id { - case 0: - m.cnt = 1 - m.id = id - m.wait.Lock() - m.Unlock() - return - case id: - m.cnt++ - m.Unlock() - return - } - - // MutexCounters.Inc(2) - m.Unlock() - m.wait.Lock() - //lint:ignore SA2001 TODO report staticcheck issue - m.wait.Unlock() - } -} - -func (m *mutex) try(id int32) int32 { - if !m.recursive { - // MutexCounters.Inc(3) - return SQLITE_BUSY - } - - // MutexCounters.Inc(4) - m.Lock() - switch m.id { - case 0: - m.cnt = 1 - m.id = id - m.wait.Lock() - m.Unlock() - return SQLITE_OK - case id: - m.cnt++ - m.Unlock() - return SQLITE_OK - } - - m.Unlock() - return SQLITE_BUSY -} - -func (m *mutex) leave(id int32) { - if !m.recursive { - m.id = 0 - m.Unlock() - return - } - - m.Lock() - m.cnt-- - if m.cnt == 0 { - m.id = 0 - m.wait.Unlock() - } - m.Unlock() -} - // int (*xMutexInit)(void); // // The xMutexInit method defined by this structure is invoked as part of system @@ -287,14 +157,15 @@ func mutexEnd(tls *libc.TLS) int32 { return SQLITE_OK } // SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() returns a // different mutex on every call. For the static mutex types, the same mutex is // returned on every call that has the same type number. -func mutexAlloc(tls *libc.TLS, typ int32) uintptr { - defer func() { - }() +func mutexAlloc(tls *libc.TLS, typ int32) (r uintptr) { switch typ { case SQLITE_MUTEX_FAST: - return mutexes.alloc(false) + r = libc.Xcalloc(tls, 1, types.Size_t(unsafe.Sizeof(mutex{}))) + return r case SQLITE_MUTEX_RECURSIVE: - return mutexes.alloc(true) + r = libc.Xcalloc(tls, 1, types.Size_t(unsafe.Sizeof(mutex{}))) + (*mutex)(unsafe.Pointer(r)).recursive = true + return r case SQLITE_MUTEX_STATIC_MASTER: return mutexMaster case SQLITE_MUTEX_STATIC_MEM: @@ -325,7 +196,9 @@ func mutexAlloc(tls *libc.TLS, typ int32) uintptr { } // void (*xMutexFree)(sqlite3_mutex *); -func mutexFree(tls *libc.TLS, m uintptr) { mutexes.free(m) } +func mutexFree(tls *libc.TLS, m uintptr) { + libc.Xfree(tls, m) +} // The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt to enter // a mutex. If another thread is already within the mutex, @@ -346,7 +219,34 @@ func mutexEnter(tls *libc.TLS, m uintptr) { if m == 0 { return } - mutexFromPtr(m).enter(tls.ID) + + if !(*mutex)(unsafe.Pointer(m)).recursive { + (*mutex)(unsafe.Pointer(m)).Lock() + (*mutex)(unsafe.Pointer(m)).id = tls.ID + return + } + + id := tls.ID + if atomic.CompareAndSwapInt32(&(*mutex)(unsafe.Pointer(m)).id, 0, id) { + (*mutex)(unsafe.Pointer(m)).cnt = 1 + (*mutex)(unsafe.Pointer(m)).Lock() + return + } + + if atomic.LoadInt32(&(*mutex)(unsafe.Pointer(m)).id) == id { + (*mutex)(unsafe.Pointer(m)).cnt++ + return + } + + for { + (*mutex)(unsafe.Pointer(m)).Lock() + if atomic.CompareAndSwapInt32(&(*mutex)(unsafe.Pointer(m)).id, 0, id) { + (*mutex)(unsafe.Pointer(m)).cnt = 1 + return + } + + (*mutex)(unsafe.Pointer(m)).Unlock() + } } // int (*xMutexTry)(sqlite3_mutex *); @@ -355,7 +255,13 @@ func mutexTry(tls *libc.TLS, m uintptr) int32 { return SQLITE_OK } - return mutexFromPtr(m).try(tls.ID) + if !(*mutex)(unsafe.Pointer(m)).recursive { + if (*mutex)(unsafe.Pointer(m)).TryLock() { + return SQLITE_OK + } + } + + return SQLITE_BUSY } // void (*xMutexLeave)(sqlite3_mutex *); @@ -364,7 +270,16 @@ func mutexLeave(tls *libc.TLS, m uintptr) { return } - mutexFromPtr(m).leave(tls.ID) + if !(*mutex)(unsafe.Pointer(m)).recursive { + (*mutex)(unsafe.Pointer(m)).id = 0 + (*mutex)(unsafe.Pointer(m)).Unlock() + return + } + + if atomic.AddInt32(&(*mutex)(unsafe.Pointer(m)).cnt, -1) == 0 { + atomic.StoreInt32(&(*mutex)(unsafe.Pointer(m)).id, 0) + (*mutex)(unsafe.Pointer(m)).Unlock() + } } // The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines are intended @@ -397,7 +312,7 @@ func mutexHeld(tls *libc.TLS, m uintptr) int32 { return 1 } - return libc.Bool32(atomic.LoadInt32(&mutexFromPtr(m).id) == tls.ID) + return libc.Bool32(atomic.LoadInt32(&(*mutex)(unsafe.Pointer(m)).id) == tls.ID) } // int (*xMutexNotheld)(sqlite3_mutex *); @@ -406,5 +321,5 @@ func mutexNotheld(tls *libc.TLS, m uintptr) int32 { return 1 } - return libc.Bool32(atomic.LoadInt32(&mutexFromPtr(m).id) != tls.ID) + return libc.Bool32(atomic.LoadInt32(&(*mutex)(unsafe.Pointer(m)).id) != tls.ID) } |
