MMap::MMap (const FileDescriptor& fd, bool const sequential) : size (fd.size()), ptr (mmap (NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_NORESERVE, fd.get(), 0)), mapped (ptr != GU_MAP_FAILED) { if (!mapped) { gu_throw_error(errno) << "mmap() on '" << fd.name() << "' failed"; } #if !defined(__sun__) && !defined(__APPLE__) && !defined(__FreeBSD__) /* Solaris, Darwin, and FreeBSD do not have MADV_DONTFORK */ if (posix_madvise (ptr, size, MADV_DONTFORK)) { int const err(errno); log_warn << "Failed to set MADV_DONTFORK on " << fd.name() << ": " << err << " (" << strerror(err) << ")"; } #endif /* benefits are questionable */ if (sequential && posix_madvise (ptr, size, MADV_SEQUENTIAL)) { int const err(errno); log_warn << "Failed to set MADV_SEQUENTIAL on " << fd.name() << ": " << err << " (" << strerror(err) << ")"; } log_debug << "Memory mapped: " << ptr << " (" << size << " bytes)"; }
static int __file_invalidate_cache(struct thread_data *td, struct fio_file *f, unsigned long long off, unsigned long long len) { int ret = 0; #ifdef CONFIG_ESX return 0; #endif if (len == -1ULL) len = f->io_size; if (off == -1ULL) off = f->file_offset; if (len == -1ULL || off == -1ULL) return 0; dprint(FD_IO, "invalidate cache %s: %llu/%llu\n", f->file_name, off, len); if (td->io_ops->invalidate) ret = td->io_ops->invalidate(td, f); else if (f->mmap_ptr) { ret = posix_madvise(f->mmap_ptr, f->mmap_sz, POSIX_MADV_DONTNEED); #ifdef FIO_MADV_FREE if (f->filetype == FIO_TYPE_BD) (void) posix_madvise(f->mmap_ptr, f->mmap_sz, FIO_MADV_FREE); #endif } else if (f->filetype == FIO_TYPE_FILE) { ret = posix_fadvise(f->fd, off, len, POSIX_FADV_DONTNEED); } else if (f->filetype == FIO_TYPE_BD) { ret = blockdev_invalidate_cache(f); if (ret < 0 && errno == EACCES && geteuid()) { if (!root_warn) { log_err("fio: only root may flush block " "devices. Cache flush bypassed!\n"); root_warn = 1; } ret = 0; } } else if (f->filetype == FIO_TYPE_CHAR || f->filetype == FIO_TYPE_PIPE) ret = 0; /* * Cache flushing isn't a fatal condition, and we know it will * happen on some platforms where we don't have the proper * function to flush eg block device caches. So just warn and * continue on our way. */ if (ret) { log_info("fio: cache invalidation of %s failed: %s\n", f->file_name, strerror(errno)); ret = 0; } return 0; }
static int __file_invalidate_cache(struct thread_data *td, struct fio_file *f, unsigned long long off, unsigned long long len) { int ret = 0; if (len == -1ULL) len = f->io_size; if (off == -1ULL) off = f->file_offset; if (len == -1ULL || off == -1ULL) return 0; dprint(FD_IO, "invalidate cache %s: %llu/%llu\n", f->file_name, off, len); /* * FIXME: add blockdev flushing too */ if (f->mmap_ptr) { ret = posix_madvise(f->mmap_ptr, f->mmap_sz, POSIX_MADV_DONTNEED); #ifdef FIO_MADV_FREE if (f->filetype == FIO_TYPE_BD) (void) posix_madvise(f->mmap_ptr, f->mmap_sz, FIO_MADV_FREE); #endif } else if (f->filetype == FIO_TYPE_FILE) { ret = posix_fadvise(f->fd, off, len, POSIX_FADV_DONTNEED); } else if (f->filetype == FIO_TYPE_BD) { ret = blockdev_invalidate_cache(f); if (ret < 0 && errno == EACCES && geteuid()) { if (!root_warn) { log_err("fio: only root may flush block " "devices. Cache flush bypassed!\n"); root_warn = 1; } ret = 0; } } else if (f->filetype == FIO_TYPE_CHAR || f->filetype == FIO_TYPE_PIPE) ret = 0; if (ret < 0) { td_verror(td, errno, "invalidate_cache"); return 1; } else if (ret > 0) { td_verror(td, ret, "invalidate_cache"); return 1; } return ret; }
bool memory_sub_session::unfreeze() { if (!is_frozen()) return true; d_assert(!*parent->frozen.get(), "Unfreezing sub session while parent session still frozen"); scoped_lock pl(parent->mutex); scoped_lock l(mutex); if (unfrozen_threads_count == 0) { if (parent->ram_allocated_bytes + allocated_bytes > parent->ram_limit_bytes) return false; parent->ram_allocated_bytes += allocated_bytes; pl.unlock(); for (std::map<byte*, std::pair<size_t, int> >::const_iterator i = allocs.begin(); i != allocs.end(); ++i) { if (posix_madvise(i->first, i->second.first, i->second.second)) LOG(ERROR, "madvise error on unfreezing\n"); } } ++unfrozen_threads_count; *frozen.get() = false; return true; }
bool FrAdviseMemoryUse(void *start, size_t length, FrMemUseAdvice advice) { if (start == 0 || length == 0) return false ; #if defined(__USE_BSD) int adv ; switch (advice) { case FrMADV_NORMAL: adv = MADV_NORMAL ; break ; case FrMADV_RANDOM: adv = MADV_RANDOM ; break ; case FrMADV_SEQUENTIAL: adv = MADV_SEQUENTIAL ; break ; default: adv = MADV_NORMAL ; break ; } return madvise(start, length, adv) == 0 ; #elif defined(__USE_XOPEN2K) int adv ; switch (advice) { case FrMADV_NORMAL: adv = POSIX_MADV_NORMAL ; break ; case FrMADV_RANDOM: adv = POSIX_MADV_RANDOM ; break ; case FrMADV_SEQUENTIAL: adv = POSIX_MADV_SEQUENTIAL ; break ; default: adv = POSIX_MADV_NORMAL ; break ; } return posix_madvise(start, length, adv) == 0 ; #else (void)advice; return false ; #endif }
void MMapFile::fadvise() { if(!handle) return; #if defined(HAVE_POSIX_MADVISE) && defined(POSIX_MADV_SEQUENTIAL) posix_madvise((char*)handle+pos, len-pos, POSIX_MADV_SEQUENTIAL); #elif defined(HAVE_MADVISE) && defined(MADV_SEQUENTIAL) madvise((char*)handle+pos, len-pos, MADV_SEQUENTIAL); #endif }
void MMap::dont_need() const { if (posix_madvise(reinterpret_cast<char*>(ptr), size, MADV_DONTNEED)) { log_warn << "Failed to set MADV_DONTNEED on " << ptr << ": " << errno << " (" << strerror(errno) << ')'; } }
TEST(sys_mman, posix_madvise) { TemporaryFile tempfile; size_t pagesize = sysconf(_SC_PAGESIZE); char buf[pagesize]; // Prepare environment. ASSERT_EQ(static_cast<ssize_t>(pagesize), write(tempfile.fd, buf, pagesize)); void* map = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, tempfile.fd, 0); ASSERT_NE(MAP_FAILED, map); // Verify different options of posix_madvise. ASSERT_EQ(0, posix_madvise(map, pagesize, POSIX_MADV_NORMAL)); ASSERT_EQ(0, posix_madvise(map, pagesize, POSIX_MADV_SEQUENTIAL)); ASSERT_EQ(0, posix_madvise(map, pagesize, POSIX_MADV_RANDOM)); ASSERT_EQ(0, posix_madvise(map, pagesize, POSIX_MADV_WILLNEED)); ASSERT_EQ(0, munmap(map, pagesize)); }
/* * _prop_object_internalize_unmap_file -- * Unmap a file previously mapped for internalizing. */ void _prop_object_internalize_unmap_file( struct _prop_object_internalize_mapped_file *mf) { (void)posix_madvise(mf->poimf_xml, mf->poimf_mapsize, POSIX_MADV_DONTNEED); (void)munmap(mf->poimf_xml, mf->poimf_mapsize); _PROP_FREE(mf, M_TEMP); }
bool MarkPagesUnused(void* p, size_t size) { if (!DecommitEnabled()) return false; MOZ_ASSERT(OffsetFromAligned(p, pageSize) == 0); int result = posix_madvise(p, size, MADV_DONTNEED); return result != -1; }
gint32 Mono_Posix_Syscall_posix_madvise (void *addr, mph_size_t len, gint32 advice) { mph_return_if_size_t_overflow (len); if (Mono_Posix_FromPosixMadviseAdvice (advice, &advice) == -1) return -1; return posix_madvise (addr, (size_t) len, advice); }
bool mapped_region::advise(advisemode_t mode) { unsigned int mode_padv = 0; unsigned int mode_madv = 0; switch(mode) { case Normal: #if defined(POSIX_MADV_NORMAL) mode_padv = POSIX_MADV_NORMAL; #elif defined(MADV_NORMAL) mode_madv = MADV_NORMAL; #endif break; case Random: #if defined(POSIX_MADV_RANDOM) mode_padv = POSIX_MADV_RANDOM; #elif defined(MADV_RANDOM) mode_madv = MADV_RANDOM; #endif break; case Sequential: #if defined(POSIX_MADV_SEQUENTIAL) mode_padv = POSIX_MADV_SEQUENTIAL; #elif defined(MADV_SEQUENTIAL) mode_madv = MADV_SEQUENTIAL; #endif break; case WillNeed: #if defined(POSIX_MADV_WILLNEED) mode_padv = POSIX_MADV_WILLNEED; #elif defined(MADV_WILLNEED) mode_madv = MADV_WILLNEED; #endif break; case DontNeed: #if defined(POSIX_MADV_DONTNEED) mode_padv = POSIX_MADV_DONTNEED; #elif defined(MADV_DONTNEED) mode_madv = MADV_DONTNEED; #endif break; default: return false; break; } char* address = static_cast<char * >(buffer_) - extoff_; size_t length = length_ + extoff_; if(mode_padv != 0) { return posix_madvise(address, length, mode_padv) == 0; } else if(mode_madv != 0) { return madvise(address, length, mode_madv) == 0; } return false; }
static int fio_mmap_file(struct thread_data *td, struct fio_file *f, size_t length, off_t off) { struct fio_mmap_data *fmd = FILE_ENG_DATA(f); int flags = 0; if (td_rw(td) && !td->o.verify_only) flags = PROT_READ | PROT_WRITE; else if (td_write(td) && !td->o.verify_only) { flags = PROT_WRITE; if (td->o.verify != VERIFY_NONE) flags |= PROT_READ; } else flags = PROT_READ; fmd->mmap_ptr = mmap(NULL, length, flags, MAP_SHARED, f->fd, off); if (fmd->mmap_ptr == MAP_FAILED) { fmd->mmap_ptr = NULL; td_verror(td, errno, "mmap"); goto err; } if (!fio_madvise_file(td, f, length)) goto err; if (posix_madvise(fmd->mmap_ptr, length, POSIX_MADV_DONTNEED) < 0) { td_verror(td, errno, "madvise"); goto err; } #ifdef FIO_MADV_FREE if (f->filetype == FIO_TYPE_BLOCK) (void) posix_madvise(fmd->mmap_ptr, fmd->mmap_sz, FIO_MADV_FREE); #endif err: if (td->error && fmd->mmap_ptr) munmap(fmd->mmap_ptr, length); return td->error; }
bool FrWillNeedMemory(void *memory, size_t length) { #if defined(__USE_BSD) return madvise(memory, length, MADV_WILLNEED) == 0 ; #elif defined(__USE_XOPEN2K) return posix_madvise(memory, length, POSIX_MADV_WILLNEED) == 0 ; #else (void)memory; (void)length; return true ; #endif }
// Tells the virtual memory system that the these pages will not be needed soon and so // their physical memory should have highest priority for being swapped out if needed. // This prevents other pages, which may be needed sooner, from being swapped out // unnecessarily and so can greatly reduce page thrashing in certain situations. static INLINE void madv_dontneed( const void *addr, size_t len ) { // const intptr_t pagemask = getpagesize() - 1; const intptr_t pagemask = sysconf( _SC_PAGESIZE ) - 1; // round start and finish inward to nearest page boundaries intptr_t start = (((intptr_t)addr - 1) | pagemask) + 1; intptr_t finish = (((intptr_t)addr + len) | pagemask) - pagemask; intptr_t diff = finish - start; if (diff > 0) { // protect against negative length posix_madvise( (void *)start, diff, POSIX_MADV_DONTNEED ); } }
binary_collection(const char* filename) { m_file.open(filename); if ( !m_file.is_open() ) { throw std::runtime_error("Error opening file"); } m_data = (posting_type const*)m_file.data(); m_data_size = m_file.size() / sizeof(m_data[0]); auto ret = posix_madvise((void*)m_data, m_data_size, POSIX_MADV_SEQUENTIAL); if (ret) logger() << "Error calling madvise: " << errno << std::endl; }
err_t sys_posix_madvise(void* addr, size_t len, int advice) { int got; err_t err_out; got = 0; #ifdef POSIX_MADV_NORMAL got = posix_madvise(addr, len, advice); #endif err_out = got; return err_out; }
static bool fio_madvise_file(struct thread_data *td, struct fio_file *f, size_t length) { struct fio_mmap_data *fmd = FILE_ENG_DATA(f); if (!td->o.fadvise_hint) return true; if (!td_random(td)) { if (posix_madvise(fmd->mmap_ptr, length, POSIX_MADV_SEQUENTIAL) < 0) { td_verror(td, errno, "madvise"); return false; } } else { if (posix_madvise(fmd->mmap_ptr, length, POSIX_MADV_RANDOM) < 0) { td_verror(td, errno, "madvise"); return false; } } return true; }
/* * Take some premature optimizations: * - don't prolong caching of the chunk * - ask the OS to prefault the chunk, as it'll be used soon */ static inline void *map_chunk(struct db *db, uint32_t nr) { void *chunk; if (nr >= db->next_nr) return ERR_PTR(ERANGE); chunk = __map_chunk(db, nr, MAP_NOCACHE|MAP_POPULATE); #if MAP_POPULATE == 0 if (!IS_ERR(chunk)) posix_madvise(chunk, CHUNK_SIZE, POSIX_MADV_WILLNEED); #endif return chunk; }
int psivshmem_close_device(ivshmem_pci_dev_t *dev) { int ret_madvise; int ret_msync; if (dev->status != IVSHMEM_INITIALIZED) return -1; ret_madvise = posix_madvise((void*)dev->ivshmem_base, dev->mem_size_byte,POSIX_MADV_DONTNEED); assert(munmap((void*)dev->ivshmem_base, dev->mem_size_byte) == 0); close(dev->fd); memset(dev, 0, sizeof(ivshmem_pci_dev_t)); // init with zeros DPRINT(1,"ivshmem: device closed"); return 0; // ToDo: Check returnvalue of close(dev->fd); }
int qemu_madvise(void *addr, size_t len, int advice) { if (advice == QEMU_MADV_INVALID) { errno = EINVAL; return -1; } #if defined(CONFIG_MADVISE) return madvise(addr, len, advice); #elif defined(CONFIG_POSIX_MADVISE) return posix_madvise(addr, len, advice); #else errno = EINVAL; return -1; #endif }
bool FrDontNeedMemory(void *memory, size_t length, bool never_again) { (void)never_again ; #if defined(__USE_BSD) # ifdef MADV_FREE if (never_again) return madvise(memory, length, MADV_FREE) == 0 ; else #endif /* MADV_FREE */ return madvise(memory, length, MADV_DONTNEED) == 0 ; #elif defined(__USE_XOPEN2K) return posix_madvise(memory, length, POSIX_MADV_DONTNEED) == 0 ; #else (void)memory; (void)length; return true ; #endif }
void memory_sub_session::hint(void* pointer, memory_advice advice) { byte * const ptr = reinterpret_cast<byte*> (pointer); scoped_lock l(mutex); d_assert(allocs.find(ptr) != allocs.end()); if (!is_small_alloc(ptr)) { allocs[ptr].second = advice; if (!is_frozen()) { if (posix_madvise(pointer, allocs[ptr].first, advice)) LOG(WARN, "madvise error on processing hint\n"); } } }
void pa_shm_punch(pa_shm *m, size_t offset, size_t size) { void *ptr; size_t o; pa_assert(m); pa_assert(m->ptr); pa_assert(m->size > 0); pa_assert(offset+size <= m->size); #ifdef MAP_FAILED pa_assert(m->ptr != MAP_FAILED); #endif /* You're welcome to implement this as NOOP on systems that don't * support it */ /* Align the pointer up to multiples of the page size */ ptr = (uint8_t*) m->ptr + offset; o = (size_t) ((uint8_t*) ptr - (uint8_t*) PA_PAGE_ALIGN_PTR(ptr)); if (o > 0) { size_t delta = PA_PAGE_SIZE - o; ptr = (uint8_t*) ptr + delta; size -= delta; } /* Align the size down to multiples of page size */ size = (size / PA_PAGE_SIZE) * PA_PAGE_SIZE; #ifdef MADV_REMOVE if (madvise(ptr, size, MADV_REMOVE) >= 0) return; #endif #ifdef MADV_FREE if (madvise(ptr, size, MADV_FREE) >= 0) return; #endif #ifdef MADV_DONTNEED madvise(ptr, size, MADV_DONTNEED); #elif defined(POSIX_MADV_DONTNEED) posix_madvise(ptr, size, POSIX_MADV_DONTNEED); #endif }
/* * __wt_mmap_discard -- * Discard a chunk of the memory map. */ int __wt_mmap_discard(WT_SESSION_IMPL *session, void *p, size_t size) { #ifdef HAVE_POSIX_MADVISE /* Linux requires the address be aligned to a 4KB boundary. */ WT_DECL_RET; void *blk = (void *)((uintptr_t)p & ~(uintptr_t)(WT_VM_PAGESIZE - 1)); size += WT_PTRDIFF(p, blk); if ((ret = posix_madvise(blk, size, POSIX_MADV_DONTNEED)) != 0) WT_RET_MSG(session, ret, "posix_madvise don't need"); #else WT_UNUSED(session); WT_UNUSED(p); WT_UNUSED(size); #endif return (0); }
// Verify that memory can still access after posix_madvise(POSIX_MADV_DONTNEED). // We should test on MAP_ANONYMOUS memory to verify whether the memory is discarded, // because the content of non MAP_ANONYMOUS memory can be reread from file. TEST(sys_mman, posix_madvise_POSIX_MADV_DONTNEED) { size_t pagesize = sysconf(_SC_PAGESIZE); void* map = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ASSERT_NE(MAP_FAILED, map); int* int_ptr = reinterpret_cast<int*>(map); for (int i = 0; i < static_cast<int>(pagesize / sizeof(int)); ++i) { *int_ptr++ = i; } ASSERT_EQ(0, posix_madvise(map, pagesize, POSIX_MADV_DONTNEED)); int_ptr = reinterpret_cast<int*>(map); for (int i = 0; i < static_cast<int>(pagesize / sizeof(int)); ++i) { ASSERT_EQ(i, *int_ptr++); } ASSERT_EQ(0, munmap(map, pagesize)); }
int MtpFfsCompatHandle::start() { mLock.lock(); if (!openEndpoints()) return -1; for (unsigned i = 0; i < NUM_IO_BUFS; i++) { mIobuf[i].bufs.resize(MAX_FILE_CHUNK_SIZE); posix_madvise(mIobuf[i].bufs.data(), MAX_FILE_CHUNK_SIZE, POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED); } // Get device specific r/w size mMaxWrite = android::base::GetIntProperty("sys.usb.ffs.max_write", USB_FFS_MAX_WRITE); mMaxRead = android::base::GetIntProperty("sys.usb.ffs.max_read", USB_FFS_MAX_READ); size_t attempts = 0; while (mMaxWrite >= USB_FFS_MAX_WRITE && mMaxRead >= USB_FFS_MAX_READ && attempts < ENDPOINT_ALLOC_RETRIES) { // If larger contiguous chunks of memory aren't available, attempt to try // smaller allocations. if (ioctl(mBulkIn, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(mMaxWrite)) || ioctl(mBulkOut, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(mMaxRead))) { if (errno == ENODEV) { // Driver hasn't enabled endpoints yet. std::this_thread::sleep_for(std::chrono::milliseconds(100)); attempts += 1; continue; } mMaxWrite /= 2; mMaxRead /=2; } else { return 0; } } // Try to start MtpServer anyway, with the smallest max r/w values mMaxWrite = USB_FFS_MAX_WRITE; mMaxRead = USB_FFS_MAX_READ; PLOG(ERROR) << "Functionfs could not allocate any memory!"; return 0; }
static enum fio_q_status fio_mmapio_queue(struct thread_data *td, struct io_u *io_u) { struct fio_file *f = io_u->file; struct fio_mmap_data *fmd = FILE_ENG_DATA(f); fio_ro_check(td, io_u); if (io_u->ddir == DDIR_READ) memcpy(io_u->xfer_buf, io_u->mmap_data, io_u->xfer_buflen); else if (io_u->ddir == DDIR_WRITE) memcpy(io_u->mmap_data, io_u->xfer_buf, io_u->xfer_buflen); else if (ddir_sync(io_u->ddir)) { if (msync(fmd->mmap_ptr, fmd->mmap_sz, MS_SYNC)) { io_u->error = errno; td_verror(td, io_u->error, "msync"); } } else if (io_u->ddir == DDIR_TRIM) { int ret = do_io_u_trim(td, io_u); if (!ret) td_verror(td, io_u->error, "trim"); } /* * not really direct, but should drop the pages from the cache */ if (td->o.odirect && ddir_rw(io_u->ddir)) { if (msync(io_u->mmap_data, io_u->xfer_buflen, MS_SYNC) < 0) { io_u->error = errno; td_verror(td, io_u->error, "msync"); } if (posix_madvise(io_u->mmap_data, io_u->xfer_buflen, POSIX_MADV_DONTNEED) < 0) { io_u->error = errno; td_verror(td, io_u->error, "madvise"); } } return FIO_Q_COMPLETED; }
static int mmap_window_mmap(struct mmap_window *self, off_t offset, size_t length) { if (length > self->max_window_len) length = self->max_window_len; self->mmap_pos = offset & ~PAGE_MASK; self->mmap_len = length + self->mmap_pos; self->mmap = mmap(NULL, self->mmap_len, PROT_READ, MAP_PRIVATE, self->fd, offset & PAGE_MASK); if (self->mmap == MAP_FAILED) return -1; self->pos = offset - self->start_off; if (posix_madvise(self->mmap, self->mmap_len, POSIX_MADV_SEQUENTIAL) < 0) return -1; self->mmap_end = mmap_window_end(self); return 0; }
U_CFUNC UBool uprv_mapFile(UDataMemory *pData, const char *path) { int fd; int length; struct stat mystat; void *data; UDataMemory_init(pData); /* Clear the output struct. */ /* determine the length of the file */ if(stat(path, &mystat)!=0 || mystat.st_size<=0) { return FALSE; } length=mystat.st_size; /* open the file */ fd=open(path, O_RDONLY); if(fd==-1) { return FALSE; } /* get a view of the mapping */ #if U_PLATFORM != U_PF_HPUX data=mmap(0, length, PROT_READ, MAP_SHARED, fd, 0); #else data=mmap(0, length, PROT_READ, MAP_PRIVATE, fd, 0); #endif close(fd); /* no longer needed */ if(data==MAP_FAILED) { return FALSE; } pData->map = (char *)data + length; pData->pHeader=(const DataHeader *)data; pData->mapAddr = data; #if U_PLATFORM == U_PF_IPHONE posix_madvise(data, length, POSIX_MADV_RANDOM); #endif return TRUE; }