mutex.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. // Copyright 2021 The Sqlite Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package sqlite3
  5. import (
  6. "fmt"
  7. "sync"
  8. "sync/atomic"
  9. "unsafe"
  10. "modernc.org/libc"
  11. "modernc.org/libc/sys/types"
  12. )
  13. func init() {
  14. tls := libc.NewTLS()
  15. if Xsqlite3_threadsafe(tls) == 0 {
  16. panic(fmt.Errorf("sqlite: thread safety configuration error"))
  17. }
  18. varArgs := libc.Xmalloc(tls, types.Size_t(unsafe.Sizeof(uintptr(0))))
  19. if varArgs == 0 {
  20. panic(fmt.Errorf("cannot allocate memory"))
  21. }
  22. // int sqlite3_config(int, ...);
  23. if rc := Xsqlite3_config(tls, SQLITE_CONFIG_MUTEX, libc.VaList(varArgs, uintptr(unsafe.Pointer(&mutexMethods)))); rc != SQLITE_OK {
  24. p := Xsqlite3_errstr(tls, rc)
  25. str := libc.GoString(p)
  26. panic(fmt.Errorf("sqlite: failed to configure mutex methods: %v", str))
  27. }
  28. libc.Xfree(tls, varArgs)
  29. tls.Close()
  30. }
  31. var (
  32. mutexMethods = Sqlite3_mutex_methods{
  33. FxMutexInit: *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS) int32 }{mutexInit})),
  34. FxMutexEnd: *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS) int32 }{mutexEnd})),
  35. FxMutexAlloc: *(*uintptr)(unsafe.Pointer(&struct {
  36. f func(*libc.TLS, int32) uintptr
  37. }{mutexAlloc})),
  38. FxMutexFree: *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{mutexFree})),
  39. FxMutexEnter: *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{mutexEnter})),
  40. FxMutexTry: *(*uintptr)(unsafe.Pointer(&struct {
  41. f func(*libc.TLS, uintptr) int32
  42. }{mutexTry})),
  43. FxMutexLeave: *(*uintptr)(unsafe.Pointer(&struct{ f func(*libc.TLS, uintptr) }{mutexLeave})),
  44. FxMutexHeld: *(*uintptr)(unsafe.Pointer(&struct {
  45. f func(*libc.TLS, uintptr) int32
  46. }{mutexHeld})),
  47. FxMutexNotheld: *(*uintptr)(unsafe.Pointer(&struct {
  48. f func(*libc.TLS, uintptr) int32
  49. }{mutexNotheld})),
  50. }
  51. MutexCounters = libc.NewPerfCounter([]string{
  52. "enter-fast",
  53. "enter-recursive",
  54. "enter-recursive-loop",
  55. "try-fast",
  56. "try-recursive",
  57. })
  58. MutexEnterCallers = libc.NewStackCapture(4)
  59. mutexes mutexPool
  60. mutexApp1 = mutexes.alloc(false)
  61. mutexApp2 = mutexes.alloc(false)
  62. mutexApp3 = mutexes.alloc(false)
  63. mutexLRU = mutexes.alloc(false)
  64. mutexMaster = mutexes.alloc(false)
  65. mutexMem = mutexes.alloc(false)
  66. mutexOpen = mutexes.alloc(false)
  67. mutexPMem = mutexes.alloc(false)
  68. mutexPRNG = mutexes.alloc(false)
  69. mutexVFS1 = mutexes.alloc(false)
  70. mutexVFS2 = mutexes.alloc(false)
  71. mutexVFS3 = mutexes.alloc(false)
  72. )
  73. type mutexPool struct {
  74. sync.Mutex
  75. a []*[256]mutex
  76. freeList []int
  77. }
  78. func mutexFromPtr(p uintptr) *mutex {
  79. if p == 0 {
  80. return nil
  81. }
  82. ix := p - 1
  83. return &mutexes.a[ix>>8][ix&255]
  84. }
  85. func (m *mutexPool) alloc(recursive bool) uintptr {
  86. m.Lock()
  87. defer m.Unlock()
  88. n := len(m.freeList)
  89. if n == 0 {
  90. outer := len(m.a) << 8
  91. m.a = append(m.a, &[256]mutex{})
  92. for i := 0; i < 256; i++ {
  93. m.freeList = append(m.freeList, outer+i)
  94. }
  95. n = len(m.freeList)
  96. }
  97. ix := m.freeList[n-1]
  98. outer := ix >> 8
  99. inner := ix & 255
  100. m.freeList = m.freeList[:n-1]
  101. p := &m.a[outer][inner]
  102. p.poolIndex = ix
  103. p.recursive = recursive
  104. return uintptr(ix) + 1
  105. }
  106. func (m *mutexPool) free(p uintptr) {
  107. ptr := mutexFromPtr(p)
  108. ix := ptr.poolIndex
  109. *ptr = mutex{}
  110. m.Lock()
  111. defer m.Unlock()
  112. m.freeList = append(m.freeList, ix)
  113. }
  114. type mutex struct {
  115. sync.Mutex
  116. wait sync.Mutex
  117. poolIndex int
  118. cnt int32
  119. id int32
  120. recursive bool
  121. }
  122. func (m *mutex) enter(id int32) {
  123. // MutexEnterCallers.Record()
  124. if !m.recursive {
  125. // MutexCounters.Inc(0)
  126. m.Lock()
  127. m.id = id
  128. return
  129. }
  130. // MutexCounters.Inc(1)
  131. for {
  132. m.Lock()
  133. switch m.id {
  134. case 0:
  135. m.cnt = 1
  136. m.id = id
  137. m.wait.Lock()
  138. m.Unlock()
  139. return
  140. case id:
  141. m.cnt++
  142. m.Unlock()
  143. return
  144. }
  145. // MutexCounters.Inc(2)
  146. m.Unlock()
  147. m.wait.Lock()
  148. //lint:ignore SA2001 TODO report staticcheck issue
  149. m.wait.Unlock()
  150. }
  151. }
  152. func (m *mutex) try(id int32) int32 {
  153. if !m.recursive {
  154. // MutexCounters.Inc(3)
  155. return SQLITE_BUSY
  156. }
  157. // MutexCounters.Inc(4)
  158. m.Lock()
  159. switch m.id {
  160. case 0:
  161. m.cnt = 1
  162. m.id = id
  163. m.wait.Lock()
  164. m.Unlock()
  165. return SQLITE_OK
  166. case id:
  167. m.cnt++
  168. m.Unlock()
  169. return SQLITE_OK
  170. }
  171. m.Unlock()
  172. return SQLITE_BUSY
  173. }
  174. func (m *mutex) leave(id int32) {
  175. if !m.recursive {
  176. m.id = 0
  177. m.Unlock()
  178. return
  179. }
  180. m.Lock()
  181. m.cnt--
  182. if m.cnt == 0 {
  183. m.id = 0
  184. m.wait.Unlock()
  185. }
  186. m.Unlock()
  187. }
  188. // int (*xMutexInit)(void);
  189. //
  190. // The xMutexInit method defined by this structure is invoked as part of system
  191. // initialization by the sqlite3_initialize() function. The xMutexInit routine
  192. // is called by SQLite exactly once for each effective call to
  193. // sqlite3_initialize().
  194. //
  195. // The xMutexInit() method must be threadsafe. It must be harmless to invoke
  196. // xMutexInit() multiple times within the same process and without intervening
  197. // calls to xMutexEnd(). Second and subsequent calls to xMutexInit() must be
  198. // no-ops. xMutexInit() must not use SQLite memory allocation (sqlite3_malloc()
  199. // and its associates).
  200. //
  201. // If xMutexInit fails in any way, it is expected to clean up after itself
  202. // prior to returning.
  203. func mutexInit(tls *libc.TLS) int32 { return SQLITE_OK }
  204. // int (*xMutexEnd)(void);
  205. func mutexEnd(tls *libc.TLS) int32 { return SQLITE_OK }
  206. // sqlite3_mutex *(*xMutexAlloc)(int);
  207. //
  208. // The sqlite3_mutex_alloc() routine allocates a new mutex and returns a
  209. // pointer to it. The sqlite3_mutex_alloc() routine returns NULL if it is
  210. // unable to allocate the requested mutex. The argument to
  211. // sqlite3_mutex_alloc() must one of these integer constants:
  212. //
  213. // SQLITE_MUTEX_FAST
  214. // SQLITE_MUTEX_RECURSIVE
  215. // SQLITE_MUTEX_STATIC_MASTER
  216. // SQLITE_MUTEX_STATIC_MEM
  217. // SQLITE_MUTEX_STATIC_OPEN
  218. // SQLITE_MUTEX_STATIC_PRNG
  219. // SQLITE_MUTEX_STATIC_LRU
  220. // SQLITE_MUTEX_STATIC_PMEM
  221. // SQLITE_MUTEX_STATIC_APP1
  222. // SQLITE_MUTEX_STATIC_APP2
  223. // SQLITE_MUTEX_STATIC_APP3
  224. // SQLITE_MUTEX_STATIC_VFS1
  225. // SQLITE_MUTEX_STATIC_VFS2
  226. // SQLITE_MUTEX_STATIC_VFS3
  227. //
  228. // The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) cause
  229. // sqlite3_mutex_alloc() to create a new mutex. The new mutex is recursive when
  230. // SQLITE_MUTEX_RECURSIVE is used but not necessarily so when SQLITE_MUTEX_FAST
  231. // is used. The mutex implementation does not need to make a distinction
  232. // between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does not want to.
  233. // SQLite will only request a recursive mutex in cases where it really needs
  234. // one. If a faster non-recursive mutex implementation is available on the host
  235. // platform, the mutex subsystem might return such a mutex in response to
  236. // SQLITE_MUTEX_FAST.
  237. //
  238. // The other allowed parameters to sqlite3_mutex_alloc() (anything other than
  239. // SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) each return a pointer to a
  240. // static preexisting mutex. Nine static mutexes are used by the current
  241. // version of SQLite. Future versions of SQLite may add additional static
  242. // mutexes. Static mutexes are for internal use by SQLite only. Applications
  243. // that use SQLite mutexes should use only the dynamic mutexes returned by
  244. // SQLITE_MUTEX_FAST or SQLITE_MUTEX_RECURSIVE.
  245. //
  246. // Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST or
  247. // SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() returns a
  248. // different mutex on every call. For the static mutex types, the same mutex is
  249. // returned on every call that has the same type number.
  250. func mutexAlloc(tls *libc.TLS, typ int32) uintptr {
  251. defer func() {
  252. }()
  253. switch typ {
  254. case SQLITE_MUTEX_FAST:
  255. return mutexes.alloc(false)
  256. case SQLITE_MUTEX_RECURSIVE:
  257. return mutexes.alloc(true)
  258. case SQLITE_MUTEX_STATIC_MASTER:
  259. return mutexMaster
  260. case SQLITE_MUTEX_STATIC_MEM:
  261. return mutexMem
  262. case SQLITE_MUTEX_STATIC_OPEN:
  263. return mutexOpen
  264. case SQLITE_MUTEX_STATIC_PRNG:
  265. return mutexPRNG
  266. case SQLITE_MUTEX_STATIC_LRU:
  267. return mutexLRU
  268. case SQLITE_MUTEX_STATIC_PMEM:
  269. return mutexPMem
  270. case SQLITE_MUTEX_STATIC_APP1:
  271. return mutexApp1
  272. case SQLITE_MUTEX_STATIC_APP2:
  273. return mutexApp2
  274. case SQLITE_MUTEX_STATIC_APP3:
  275. return mutexApp3
  276. case SQLITE_MUTEX_STATIC_VFS1:
  277. return mutexVFS1
  278. case SQLITE_MUTEX_STATIC_VFS2:
  279. return mutexVFS2
  280. case SQLITE_MUTEX_STATIC_VFS3:
  281. return mutexVFS3
  282. default:
  283. return 0
  284. }
  285. }
  286. // void (*xMutexFree)(sqlite3_mutex *);
  287. func mutexFree(tls *libc.TLS, m uintptr) { mutexes.free(m) }
  288. // The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt to enter
  289. // a mutex. If another thread is already within the mutex,
  290. // sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
  291. // SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK upon
  292. // successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can be
  293. // entered multiple times by the same thread. In such cases, the mutex must be
  294. // exited an equal number of times before another thread can enter. If the same
  295. // thread tries to enter any mutex other than an SQLITE_MUTEX_RECURSIVE more
  296. // than once, the behavior is undefined.
  297. //
  298. // If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or
  299. // sqlite3_mutex_leave() is a NULL pointer, then all three routines behave as
  300. // no-ops.
  301. // void (*xMutexEnter)(sqlite3_mutex *);
  302. func mutexEnter(tls *libc.TLS, m uintptr) {
  303. if m == 0 {
  304. return
  305. }
  306. mutexFromPtr(m).enter(tls.ID)
  307. }
  308. // int (*xMutexTry)(sqlite3_mutex *);
  309. func mutexTry(tls *libc.TLS, m uintptr) int32 {
  310. if m == 0 {
  311. return SQLITE_OK
  312. }
  313. return mutexFromPtr(m).try(tls.ID)
  314. }
  315. // void (*xMutexLeave)(sqlite3_mutex *);
  316. func mutexLeave(tls *libc.TLS, m uintptr) {
  317. if m == 0 {
  318. return
  319. }
  320. mutexFromPtr(m).leave(tls.ID)
  321. }
  322. // The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines are intended
  323. // for use inside assert() statements. The SQLite core never uses these
  324. // routines except inside an assert() and applications are advised to follow
  325. // the lead of the core. The SQLite core only provides implementations for
  326. // these routines when it is compiled with the SQLITE_DEBUG flag. External
  327. // mutex implementations are only required to provide these routines if
  328. // SQLITE_DEBUG is defined and if NDEBUG is not defined.
  329. //
  330. // These routines should return true if the mutex in their argument is held or
  331. // not held, respectively, by the calling thread.
  332. //
  333. // The implementation is not required to provide versions of these routines
  334. // that actually work. If the implementation does not provide working versions
  335. // of these routines, it should at least provide stubs that always return true
  336. // so that one does not get spurious assertion failures.
  337. //
  338. // If the argument to sqlite3_mutex_held() is a NULL pointer then the routine
  339. // should return 1. This seems counter-intuitive since clearly the mutex cannot
  340. // be held if it does not exist. But the reason the mutex does not exist is
  341. // because the build is not using mutexes. And we do not want the assert()
  342. // containing the call to sqlite3_mutex_held() to fail, so a non-zero return is
  343. // the appropriate thing to do. The sqlite3_mutex_notheld() interface should
  344. // also return 1 when given a NULL pointer.
  345. // int (*xMutexHeld)(sqlite3_mutex *);
  346. func mutexHeld(tls *libc.TLS, m uintptr) int32 {
  347. if m == 0 {
  348. return 1
  349. }
  350. return libc.Bool32(atomic.LoadInt32(&mutexFromPtr(m).id) == tls.ID)
  351. }
  352. // int (*xMutexNotheld)(sqlite3_mutex *);
  353. func mutexNotheld(tls *libc.TLS, m uintptr) int32 {
  354. if m == 0 {
  355. return 1
  356. }
  357. return libc.Bool32(atomic.LoadInt32(&mutexFromPtr(m).id) != tls.ID)
  358. }