Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
module github.com/erigontech/mdbx-go

go 1.20
go 1.23.0

toolchain go1.24.1

require github.com/ianlancetaylor/cgosymbolizer v0.0.0-20241129212102-9c50ad6b591e

require golang.org/x/sys v0.31.0 // indirect
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
github.com/ianlancetaylor/cgosymbolizer v0.0.0-20241129212102-9c50ad6b591e h1:8AnObPi8WmIgjwcidUxaREhXMSpyUJeeSrIkZTXdabw=
github.com/ianlancetaylor/cgosymbolizer v0.0.0-20241129212102-9c50ad6b591e/go.mod h1:DvXTE/K/RtHehxU8/GtDs4vFtfw64jJ3PaCnFri8CRg=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
23 changes: 23 additions & 0 deletions mdbx/threads/threads_darwin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//go:build darwin

package threads

/*
#include <pthread.h>
#include <stdint.h>

// getThreadID uses the pthread API to get the thread ID.
uint64_t getThreadID() {
uint64_t tid;
pthread_threadid_np(NULL, &tid);
return tid;
}
*/
import "C"

//TODO: maybe there's go func for that)

// CurrentThreadID returns the macOS thread ID.
func CurrentThreadID() uint64 {
return uint64(C.getThreadID())
}
12 changes: 12 additions & 0 deletions mdbx/threads/threads_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//go:build linux

package threads

import "syscall"

// CurrentThreadID returns the Linux thread ID.
// Note: gettid() is not directly available in Go so we use a raw syscall.
func CurrentThreadID() uint64 {
tid, _, _ := syscall.RawSyscall(syscall.SYS_GETTID, 0, 0, 0)
return uint64(tid)
}
12 changes: 12 additions & 0 deletions mdbx/threads/threads_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//go:build windows

package threads

import (
"golang.org/x/sys/windows"
)

// CurrentThreadID returns the Windows thread ID.
func CurrentThreadID() uint64 {
return uint64(windows.GetCurrentThreadId())
}
15 changes: 15 additions & 0 deletions mdbx/txn.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ package mdbx
import "C"

import (
"fmt"
"github.com/erigontech/mdbx-go/mdbx/threads"
"log"
"time"
"unsafe"
Expand Down Expand Up @@ -77,6 +79,8 @@ type Txn struct {
// be paid. The id of a Txn cannot change over its life, even if it is
// reset/renewed
id uint64

tid uint64
}

// beginTxn does not lock the OS thread which is a prerequisite for creating a
Expand All @@ -86,6 +90,7 @@ func beginTxn(env *Env, parent *Txn, flags uint) (*Txn, error) {
readonly: flags&Readonly != 0,
env: env,
}
txn.tid = threads.CurrentThreadID()

var ptxn *C.MDBX_txn
if parent != nil {
Expand Down Expand Up @@ -243,6 +248,7 @@ type CommitLatencyGC struct {

func (txn *Txn) commit() (CommitLatency, error) {
var _stat C.MDBX_commit_latency
txn.strictThreadCheck()
ret := C.mdbx_txn_commit_ex(txn._txn, &_stat)
txn.clearTxn()
s := CommitLatency{
Expand Down Expand Up @@ -297,6 +303,14 @@ func (txn *Txn) Abort() {
txn.abort()
}

func (txn *Txn) strictThreadCheck() {
currentThread := threads.CurrentThreadID()
if currentThread != txn.tid {
msg := fmt.Sprintf("thread mismatch. not allowed current %d, open in %d", currentThread, txn.tid)
panic(msg)
}
}

func (txn *Txn) abort() {
if txn._txn == nil {
return
Expand All @@ -305,6 +319,7 @@ func (txn *Txn) abort() {
// Get a read-lock on the environment so we can abort txn if needed.
// txn.env **should** terminate all readers otherwise when it closes.
txn.env.closeLock.RLock()
txn.strictThreadCheck()
if txn.env._env != nil {
C.mdbx_txn_abort(txn._txn)
}
Expand Down
Loading