int mono_pages_not_faulted (void *addr, size_t size) { #ifdef HAVE_MINCORE int i; gint64 count; int pagesize = mono_pagesize (); int npages = (size + pagesize - 1) / pagesize; char *faulted = (char *) g_malloc0 (sizeof (char*) * npages); /* * We cast `faulted` to void* because Linux wants an unsigned * char* while BSD wants a char*. */ #ifdef __linux__ if (mincore (addr, size, (unsigned char *)faulted) != 0) { #else if (mincore (addr, size, (char *)faulted) != 0) { #endif count = -1; } else { count = 0; for (i = 0; i < npages; ++i) { if (faulted [i] != 0) ++count; } } g_free (faulted); return count; #else return -1; #endif }
static int32 addrspace_free(void *v, uintptr n) { int32 errval; uintptr chunk; uintptr off; // NOTE: vec must be just 1 byte long here. // Mincore returns ENOMEM if any of the pages are unmapped, // but we want to know that all of the pages are unmapped. // To make these the same, we can only ask about one page // at a time. See golang.org/issue/7476. static byte vec[1]; for(off = 0; off < n; off += chunk) { chunk = _PAGE_SIZE * sizeof vec; if(chunk > (n - off)) chunk = n - off; errval = runtime·mincore((int8*)v + off, chunk, vec); // ENOMEM means unmapped, which is what we want. // Anything else we assume means the pages are mapped. if (errval != -ENOMEM) return 0; } return 1; }
JNIEXPORT jboolean JNICALL Java_java_nio_MappedByteBuffer_isLoaded0(JNIEnv *env, jobject obj, jlong address, jlong len) { jboolean loaded = JNI_TRUE; jint pageSize = sysconf(_SC_PAGESIZE); jint numPages = (len + pageSize - 1) / pageSize; int result = 0; int i = 0; void *a = (void *) jlong_to_ptr(address); char * vec = (char *)malloc(numPages * sizeof(char)); if (vec == NULL) { JNU_ThrowOutOfMemoryError(env, NULL); return JNI_FALSE; } result = mincore(a, (size_t)len, vec); if (result != 0) { free(vec); JNU_ThrowIOExceptionWithLastError(env, "mincore failed"); return JNI_FALSE; } for (i=0; i<numPages; i++) { if (vec[i] == 0) { loaded = JNI_FALSE; break; } } free(vec); return loaded; }
EGLBoolean _eglPointerIsDereferencable(void *p) { #ifdef HAVE_MINCORE uintptr_t addr = (uintptr_t) p; unsigned char valid = 0; const long page_size = getpagesize(); if (p == NULL) return EGL_FALSE; /* align addr to page_size */ addr &= ~(page_size - 1); if (mincore((void *) addr, page_size, &valid) < 0) { _eglLog(_EGL_DEBUG, "mincore failed: %m"); return EGL_FALSE; } /* mincore() returns 0 on success, and -1 on failure. The last parameter * is a vector of bytes with one entry for each page queried. mincore * returns page residency information in the first bit of each byte in the * vector. * * Residency doesn't actually matter when determining whether a pointer is * dereferenceable, so the output vector can be ignored. What matters is * whether mincore succeeds. See: * * http://man7.org/linux/man-pages/man2/mincore.2.html */ return EGL_TRUE; #else return p != NULL; #endif }
int main(int argc, char **argv) { int lock_pages, counter; setup(); if (-1 == mincore((void *)position, num_pages * p_size, vec)) { tst_brkm(TBROK, cleanup, "Unable to execute mincore system call: %s", strerror(errno)); } /* check status of pages */ lock_pages = 0; for (counter = 0; counter < num_pages; counter++) { if (vec[counter] & 1) lock_pages++; } if (lock_pages == num_pages) tst_resm(TPASS, "%d pages locked, %d pages in-core", num_pages, lock_pages); else tst_resm(TFAIL, "not all locked pages are in-core: no. locked: %d, no. in-core: %d", num_pages, lock_pages); cleanup(); tst_exit(); }
int mincore_one(char *filename) { int fd, npg; struct stat st; char *outname; unsigned char *vec; void *map = 0; int retval = 1; if((fd = open(filename, O_RDONLY)) == -1) { fprintf(stderr, "%s: %s\n", filename, strerror(errno)); retval = 0; goto out; } if(fstat(fd, &st) == -1) { fprintf(stderr, "fstat: %s\n", strerror(errno)); retval = 0; goto out_close; } npg = st.st_size / pagesize + ((st.st_size % pagesize) != 0); vec = malloc(npg); if(!vec) { fprintf(stderr, "malloc(%d): %s\n", npg, strerror(errno)); retval = 0; goto out_close; } if(st.st_size) { map = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); if(map == MAP_FAILED) { fprintf(stderr, "mmap(%s): %s\n", filename, strerror(errno)); retval = 0; goto out_free; } if(mincore(map, st.st_size, vec) == -1) { fprintf(stderr, "mincore: %s\n", strerror(errno)); retval = 0; goto out_munmap; } } if(o_fullname) outname = filename; else { outname = strrchr(filename, '/'); outname = outname ? outname + 1 : filename; } info_func(outname, vec, npg); out_munmap: if(map && munmap(map, st.st_size) == -1) fprintf(stderr, "munmap(%p, %ld): %s\n", map, st.st_size, strerror(errno)); out_free: free(vec); out_close: close(fd); out: return retval; }
int os_mincore(void *addr, unsigned long len) { char *vec; int ret, i; if (len <= UM_KERN_PAGE_SIZE) return os_page_mincore(addr); vec = calloc(1, (len + UM_KERN_PAGE_SIZE - 1) / UM_KERN_PAGE_SIZE); if (!vec) return -ENOMEM; ret = mincore(addr, UM_KERN_PAGE_SIZE, vec); if (ret < 0) { if (errno == ENOMEM || errno == EINVAL) ret = 0; else ret = -errno; goto out; } for (i = 0; i < ((len + UM_KERN_PAGE_SIZE - 1) / UM_KERN_PAGE_SIZE); i++) { if (!(vec[i] & 1)) { ret = 0; goto out; } } ret = 1; out: free(vec); return ret; }
int mono_pages_not_faulted (void *addr, size_t size) { #ifdef HAVE_MINCORE int i; gint64 count; int pagesize = mono_pagesize (); int npages = (size + pagesize - 1) / pagesize; char *faulted = g_malloc0 (sizeof (char*) * npages); if (mincore (addr, size, faulted) != 0) { count = -1; } else { count = 0; for (i = 0; i < npages; ++i) { if (faulted [i] != 0) ++count; } } g_free (faulted); return count; #else return -1; #endif }
int main(int argc, char *argv[]) { int fd; struct stat file_stat; void *file_mmap; unsigned char *mincore_vec; size_t page_size = getpagesize(); size_t page_index; fd = open(argv[1],0); fstat(fd, &file_stat); file_mmap = mmap((void *)0, file_stat.st_size, PROT_NONE, MAP_SHARED, fd, 0); mincore_vec = calloc(1, (file_stat.st_size+page_size-1)/page_size); mincore(file_mmap, file_stat.st_size, mincore_vec); printf("Cached Blocks of %s: ",argv[1]); unsigned n_pages = 1 + file_stat.st_size/page_size; unsigned n_cached = 0; for (page_index = 0; page_index < n_pages; page_index++) { if (mincore_vec[page_index]&1) { printf("%lu ", (unsigned long)page_index); n_cached++; } } printf("\nSummary: %u of %u pages (%.2lf%%) cached.\n", n_cached, n_pages, (double)n_cached*100/n_pages ); free(mincore_vec); munmap(file_mmap, file_stat.st_size); close(fd); return 0; }
void *fill_bounds_dir_buf_self(long byte_offset_inside_bounds_dir, long buffer_size_bytes, void *buffer) { unsigned char vec[buffer_size_bytes / PAGE_SIZE]; char *dig_bounds_dir_ptr = (void *)(bounds_dir_global + byte_offset_inside_bounds_dir); /* * use mincore() to quickly find the areas of the bounds directory * that have memory and thus will be worth scanning. */ int incore_ret; int incore = 0; int i; dprintf4("%s() dig_bounds_dir_ptr: %p\n", __func__, dig_bounds_dir_ptr); incore_ret = mincore(dig_bounds_dir_ptr, buffer_size_bytes, &vec[0]); if (incore_ret) { printf("mincore ret: %d\n", incore_ret); perror("mincore"); mpx_dig_abort(); } for (i = 0; i < sizeof(vec); i++) incore += vec[i]; dprintf4("%s() total incore: %d\n", __func__, incore); if (!incore) return NULL; dprintf3("%s() total incore: %d\n", __func__, incore); return dig_bounds_dir_ptr; }
int Mono_Posix_Syscall_mincore (void *start, mph_size_t length, unsigned char *vec) { mph_return_if_size_t_overflow (length); return mincore (start, (size_t) length, (void*)vec); }
static void displayMincore(char *addr, size_t length) { unsigned char *vec; long pageSize, numPages, j; #ifndef _SC_PAGESIZE pageSize = getpagesize(); /* Some systems don't have _SC_PAGESIZE */ #else pageSize = sysconf(_SC_PAGESIZE); #endif numPages = (length + pageSize - 1) / pageSize; vec = malloc(numPages); if (vec == NULL) errExit("malloc"); if (mincore(addr, length, vec) == -1) errExit("mincore"); for (j = 0; j < numPages; j++) { if (j % 64 == 0) printf("%s%10p: ", (j == 0) ? "" : "\n", addr + (j * pageSize)); printf("%c", (vec[j] & 1) ? '*' : '.'); } printf("\n"); free(vec); }
static size_t check_residency(void *addr, size_t npgs) { size_t i, resident; char *vec; vec = malloc(npgs); ATF_REQUIRE(vec != NULL); ATF_REQUIRE(mincore(addr, npgs * page, vec) == 0); for (i = resident = 0; i < npgs; i++) { if (vec[i] != 0) resident++; #if 0 (void)fprintf(stderr, "page 0x%p is %sresident\n", (char *)addr + (i * page), vec[i] ? "" : "not "); #endif } free(vec); return resident; }
static void * mmap_fixed (void *addr, size_t len, int prot, int flags, int fd, off_t off) { void *base; base = mmap ((caddr_t) addr, len, prot, flags, fd, off); if (base != addr) { size_t page_size = getpagesize(); char one_byte; size_t i; if (base != (void *) MAP_FAILED) munmap ((caddr_t) base, len); errno = 0; for (i = 0; i < len; i += page_size) if (mincore ((char *)addr + i, page_size, (char *) &one_byte) == -1 && errno == ENOMEM) continue; /* The page is not mapped. */ else break; if (i >= len) base = mmap ((caddr_t) addr, len, prot, flags | MAP_FIXED, fd, off); } return base; }
/* * fwts_low_mmap_walkdown() * try to allocate a free space under the 2GB limit by * walking down memory in CHUNK_SIZE steps for an unmapped region */ static void *fwts_low_mmap_walkdown(const size_t requested_size) { void *addr; size_t page_size = fwts_page_size(); size_t sz = (requested_size + page_size) & ~(page_size - 1); size_t pages = sz / page_size; unsigned char vec[pages]; static void *last_addr = (void *)LIMIT_2GB; if (requested_size == 0) /* Illegal */ return MAP_FAILED; for (addr = last_addr - sz; addr > (void *)LIMIT_START; addr -= CHUNK_SIZE) { void *mapping; /* Already mapped? */ if (mincore(addr, pages, vec) == 0) continue; /* Not mapped but mincore returned something unexpected? */ if (errno != ENOMEM) continue; mapping = mmap(addr, requested_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0); if (mapping != MAP_FAILED) { last_addr = mapping; return mapping; } } /* We've scanned all of memory, give up on subsequent calls */ last_addr = (void *)LIMIT_START; return MAP_FAILED; }
static jboolean OSMemory_isLoaded(JNIEnv*, jclass, jint address, jlong size) { if (size == 0) { return JNI_TRUE; } static int page_size = getpagesize(); int align_offset = address % page_size;// addr should align with the boundary of a page. address -= align_offset; size += align_offset; int page_count = (size + page_size - 1) / page_size; UniquePtr<char[]> vec(new char[page_count]); int rc = mincore(cast<void*>(address), size, vec.get()); if (rc == -1) { return JNI_FALSE; } for (int i = 0; i < page_count; ++i) { if (vec[i] != 1) { return JNI_FALSE; } } return JNI_TRUE; }
bool ProcessInfo::blockInMemory(const void* start) { unsigned char x = 0; if (mincore(const_cast<void*>(alignToStartOfPage(start)), getPageSize(), &x)) { log() << "mincore failed: " << errnoWithDescription() << endl; return 1; } return x & 0x1; }
bool ProcessInfo::blockInMemory( char * start ) { start = getPageAddress(start); char x = 0; if ( mincore( start , 128 , &x ) ) { log() << "mincore failed: " << errnoWithDescription() << endl; return 1; } return x & 0x1; }
static void *gc_get_stackbottom(void) { void *stackbottom; stackbottom = (void *)gc_stacktop(); stackbottom = (void *)(((uintptr_t)(stackbottom + GC_PAGESIZE) / GC_PAGESIZE) * GC_PAGESIZE); unsigned char vec; #ifdef __APPLE__ while (mincore(stackbottom, GC_PAGESIZE, &vec) == 0 && vec != 0) stackbottom += GC_PAGESIZE; #else /* __APPLE__ */ while (mincore(stackbottom, GC_PAGESIZE, &vec) == 0) stackbottom += GC_PAGESIZE; if (errno != ENOMEM) return false; #endif /* __APPLE__ */ stackbottom -= sizeof(void *); return stackbottom; }
bool ProcessInfo::pagesInMemory(const void* start, size_t numPages, vector<char>* out) { out->resize(numPages); if (mincore(alignToStartOfPage(start), numPages * getPageSize(), &out->front())) { log() << "mincore failed: " << errnoWithDescription() << endl; return false; } for (size_t i = 0; i < numPages; ++i) { (*out)[i] &= 0x1; } return true; }
// static public bool ProcessInformation::BlockInMemory (const void* start) { unsigned char x = 0; if (mincore (const_cast<void*>(AlignToStartOfPage (start)), GetPageSize (), &x)) { LOG (ERROR) << "mincore failed: " << strerror (errno); return 1; } return x & 0x1; }
// maybe we should move this function to another .cpp file to avoid unwanted optimization? static int PrechargeImpl(TFile f, void* data, size_t dataSize, size_t off, size_t size) { if (off > dataSize) { assert(false); return 0; } size_t endOff = (size == (size_t)-1 ? dataSize : off + size); if (endOff > dataSize) { assert(false); endOff = dataSize; } size = endOff - off; if (dataSize == 0 || size == 0) return 0; const char *c = (char*)data + off, *e = c + size; int n = 0; #ifdef _freebsd_ if (off % PAGE_SIZE) { off = off / PAGE_SIZE * PAGE_SIZE; // align on PAGE_SIZE size = endOff - off; c = (char*)data + off; } madvise((void*)c, e - c, MADV_WILLNEED); f.Seek(0, sSet); const size_t rdSize1 = 64 << 20, rdSize2 = 4 << 20; const size_t rdSize = size > rdSize2 * 32? rdSize1 : rdSize2; TArrayHolder<char> pages(new char[(rdSize1 + PAGE_SIZE - 1) / PAGE_SIZE]); TBuffer buf(Min(rdSize, size)); ui32 nbufs = 0, nread = 0; for (size_t r = 0; r < size; r += rdSize) { bool needRead = true; size_t toRead = Min(rdSize, size - r); if (mincore(c + r, toRead, pages.Get()) != -1) needRead = memchr(pages.Get(), 0, (toRead + PAGE_SIZE - 1) / PAGE_SIZE) != 0; if (needRead) f.Read(buf.Data(), toRead); madvise((void*)(c + r), toRead, MADV_WILLNEED); for (const char *d = c; d < c + r; d += 512) n += *d; nbufs++; nread += needRead; } //warnx("precharge: read %u/%u (blk %"PRISZT")", nread, nbufs, rdSize); return 0; #else UNUSED(f); #endif for (; c < e; c += 512) n += *c; return n; // prevent loop optimization }
unsigned char *get_filePageMap(int fd, int offset, int size) { int idx; void *file_mmap; struct stat file_stat; ssize_t page_size = getpagesize(); ssize_t table_size; if (table != NULL) { free(table); } /* if (fstat(fd, &file_stat) < 0) { printf("[Error] Fail to fstat\n"); return NULL; } */ if (size == 0 ) { printf("[Error] Fail to get file size\n"); return NULL; } file_mmap = mmap((void *)0, size, PROT_NONE, MAP_SHARED, fd, offset); if (file_mmap == MAP_FAILED) { printf("[Error] Fail to mmap\n"); return NULL; } table_size = (size + page_size - 1) / page_size; table = calloc(1, table_size); if (table == NULL) { printf("[Error] Fail to calloc\n"); return NULL; } if (mincore(file_mmap, size, table) != 0) { printf("[Error] Fail to mincore\n"); return NULL; } /* toDo: parallel bit converting */ for (idx = 0; idx < table_size; idx++) { table[idx] &= 1; } munmap(file_mmap, size); return table; }
bool ProcessInfo::blockInMemory( char * start ) { static long pageSize = 0; if ( pageSize == 0 ) { pageSize = sysconf( _SC_PAGESIZE ); } start = start - ( (unsigned long long)start % pageSize ); char x = 0; if ( mincore( start , 128 , &x ) ) { log() << "mincore failed: " << errnoWithDescription() << endl; return 1; } return x & 0x1; }
ATF_TC_BODY(mincore_err, tc) { char *map, *vec; map = mmap(NULL, page, PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); vec = malloc(page); ATF_REQUIRE(vec != NULL); ATF_REQUIRE(map != MAP_FAILED); errno = 0; ATF_REQUIRE_ERRNO(EINVAL, mincore(map, 0, vec) == -1); errno = 0; ATF_REQUIRE_ERRNO(ENOMEM, mincore(0, page, vec) == -1); errno = 0; ATF_REQUIRE_ERRNO(EFAULT, mincore(map, page, (void *)-1) == -1); free(vec); ATF_REQUIRE(munmap(map, page) == 0); }
int main(int ac, char **av) { int lc; /* loop counter */ int i; char *msg; /* message returned from parse_opts */ /* parse standard options */ if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) { tst_brkm(TBROK, cleanup, "error parsing options: %s", msg); } setup(); /* global setup */ /* The following loop checks looping state if -i option given */ for (lc = 0; TEST_LOOPING(lc); lc++) { /* reset Tst_count in case we are looping */ Tst_count = 0; /* loop through the test cases */ for (i = 0; i < TST_TOTAL; i++) { /* perform test specific setup */ if (TC[i].setupfunc != NULL) { TC[i].setupfunc(); } TEST(mincore(TC[i].addr, TC[i].len, TC[i].vector)); if (TEST_RETURN != -1) { tst_resm(TFAIL, "call succeeded unexpectedly"); continue; } TEST_ERROR_LOG(TEST_ERRNO); if (TEST_ERRNO == TC[i].exp_errno) { tst_resm(TPASS, "expected failure: " "errno = %d (%s)", TEST_ERRNO, strerror(TEST_ERRNO)); } else { tst_resm(TFAIL, "unexpected error %d (%s), " "expected %d", TEST_ERRNO, strerror(TEST_ERRNO), TC[i].exp_errno); } } } cleanup(); tst_exit(); }
static int os_page_mincore(void *addr) { char vec[2]; int ret; ret = mincore(addr, UM_KERN_PAGE_SIZE, vec); if (ret < 0) { if (errno == ENOMEM || errno == EINVAL) return 0; else return -errno; } return vec[0] & 1; }
void pagesize_init (void) { unsigned int i; int n; u_char c; for (i = 1; i < (unsigned) pagesize_init ; i <<= 1) { if ((n = mincore ((void *)i, 1, &c)) >= 0) break; if (errno == ENOMEM) break; } if (i < (unsigned) pagesize_init) pagesize = i; }
static int validate_mem (unw_word_t addr) { int i, victim; #ifdef HAVE_MINCORE unsigned char mvec[2]; /* Unaligned access may cross page boundary */ #endif size_t len; if (PAGE_START(addr + sizeof (unw_word_t) - 1) == PAGE_START(addr)) len = PAGE_SIZE; else len = PAGE_SIZE * 2; addr = PAGE_START(addr); if (addr == 0) return -1; for (i = 0; i < NLGA; i++) { if (last_good_addr[i] && (addr == last_good_addr[i])) return 0; } #ifdef HAVE_MINCORE if (mincore ((void *) addr, len, mvec) == -1) #else if (msync ((void *) addr, len, MS_ASYNC) == -1) #endif return -1; victim = lga_victim; for (i = 0; i < NLGA; i++) { if (!last_good_addr[victim]) { last_good_addr[victim++] = addr; return 0; } victim = (victim + 1) % NLGA; } /* All slots full. Evict the victim. */ last_good_addr[victim] = addr; victim = (victim + 1) % NLGA; lga_victim = victim; return 0; }
/* Initialise memory validation method. On linux kernels <2.6.21, mincore() returns incorrect value for MAP_PRIVATE mappings, such as stacks. If mincore() was available at compile time, check if we can actually use it. If not, use msync() instead. */ HIDDEN void tdep_init_mem_validate (void) { #ifdef HAVE_MINCORE unsigned char present = 1; if (mincore (&present, 1, &present) == 0) { Debug(1, "using mincore to validate memory\n"); mem_validate_func = mincore_validate; } else #endif { Debug(1, "using msync to validate memory\n"); mem_validate_func = msync_validate; } }