github.com/ooni/psiphon/tunnel-core@v0.0.0-20230105123940-fe12a24c96ee/oovendor/bolt/bolt_unix_solaris.go (about) 1 package bolt 2 3 import ( 4 "fmt" 5 "syscall" 6 "time" 7 "unsafe" 8 9 "golang.org/x/sys/unix" 10 ) 11 12 // flock acquires an advisory lock on a file descriptor. 13 func flock(db *DB, exclusive bool, timeout time.Duration) error { 14 var t time.Time 15 if timeout != 0 { 16 t = time.Now() 17 } 18 fd := db.file.Fd() 19 var lockType int16 20 if exclusive { 21 lockType = syscall.F_WRLCK 22 } else { 23 lockType = syscall.F_RDLCK 24 } 25 for { 26 // Attempt to obtain an exclusive lock. 27 lock := syscall.Flock_t{Type: lockType} 28 err := syscall.FcntlFlock(fd, syscall.F_SETLK, &lock) 29 if err == nil { 30 return nil 31 } else if err != syscall.EAGAIN { 32 return err 33 } 34 35 // If we timed out then return an error. 36 if timeout != 0 && time.Since(t) > timeout-flockRetryTimeout { 37 return ErrTimeout 38 } 39 40 // Wait for a bit and try again. 41 time.Sleep(flockRetryTimeout) 42 } 43 } 44 45 // funlock releases an advisory lock on a file descriptor. 46 func funlock(db *DB) error { 47 var lock syscall.Flock_t 48 lock.Start = 0 49 lock.Len = 0 50 lock.Type = syscall.F_UNLCK 51 lock.Whence = 0 52 return syscall.FcntlFlock(uintptr(db.file.Fd()), syscall.F_SETLK, &lock) 53 } 54 55 // mmap memory maps a DB's data file. 56 func mmap(db *DB, sz int) error { 57 // Map the data file to memory. 58 b, err := unix.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED|db.MmapFlags) 59 if err != nil { 60 return err 61 } 62 63 // Advise the kernel that the mmap is accessed randomly. 64 if err := unix.Madvise(b, syscall.MADV_RANDOM); err != nil { 65 return fmt.Errorf("madvise: %s", err) 66 } 67 68 // Save the original byte slice and convert to a byte array pointer. 69 db.dataref = b 70 db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0])) 71 db.datasz = sz 72 return nil 73 } 74 75 // munmap unmaps a DB's data file from memory. 76 func munmap(db *DB) error { 77 // Ignore the unmap if we have no mapped data. 78 if db.dataref == nil { 79 return nil 80 } 81 82 // Unmap using the original byte slice. 83 err := unix.Munmap(db.dataref) 84 db.dataref = nil 85 db.data = nil 86 db.datasz = 0 87 return err 88 }