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