// +build !windows,!plan9,!solaris,!aix

package bbolt

import (
	
	
	
	
)

// flock acquires an advisory lock on a file descriptor.
func ( *DB,  bool,  time.Duration) error {
	var  time.Time
	if  != 0 {
		 = time.Now()
	}
	 := .file.Fd()
	 := syscall.LOCK_NB
	if  {
		 |= syscall.LOCK_EX
	} else {
		 |= syscall.LOCK_SH
	}
	for {
		// Attempt to obtain an exclusive lock.
		 := syscall.Flock(int(), )
		if  == nil {
			return nil
		} else if  != syscall.EWOULDBLOCK {
			return 
		}

		// If we timed out then return an error.
		if  != 0 && time.Since() > -flockRetryTimeout {
			return ErrTimeout
		}

		// Wait for a bit and try again.
		time.Sleep(flockRetryTimeout)
	}
}

// funlock releases an advisory lock on a file descriptor.
func ( *DB) error {
	return syscall.Flock(int(.file.Fd()), syscall.LOCK_UN)
}

// mmap memory maps a DB's data file.
func ( *DB,  int) error {
	// Map the data file to memory.
	,  := syscall.Mmap(int(.file.Fd()), 0, , syscall.PROT_READ, syscall.MAP_SHARED|.MmapFlags)
	if  != nil {
		return 
	}

	// Advise the kernel that the mmap is accessed randomly.
	 = madvise(, syscall.MADV_RANDOM)
	if  != nil &&  != syscall.ENOSYS {
		// Ignore not implemented error in kernel because it still works.
		return fmt.Errorf("madvise: %s", )
	}

	// Save the original byte slice and convert to a byte array pointer.
	.dataref = 
	.data = (*[maxMapSize]byte)(unsafe.Pointer(&[0]))
	.datasz = 
	return nil
}

// munmap unmaps a DB's data file from memory.
func ( *DB) error {
	// Ignore the unmap if we have no mapped data.
	if .dataref == nil {
		return nil
	}

	// Unmap using the original byte slice.
	 := syscall.Munmap(.dataref)
	.dataref = nil
	.data = nil
	.datasz = 0
	return 
}

// NOTE: This function is copied from stdlib because it is not available on darwin.
func ( []byte,  int) ( error) {
	, ,  := syscall.Syscall(syscall.SYS_MADVISE, uintptr(unsafe.Pointer(&[0])), uintptr(len()), uintptr())
	if  != 0 {
		 = 
	}
	return
}