Esempio n. 1
0
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
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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
}
Esempio n. 5
0
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();
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
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
}
Esempio n. 9
0
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;
}
Esempio n. 10
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;
}
Esempio n. 11
0
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);
}
Esempio n. 12
0
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);
}
Esempio n. 13
0
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;
}
Esempio n. 14
0
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;
}
Esempio n. 15
0
/*
 *  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;
}
Esempio n. 17
0
 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;
 }
Esempio n. 18
0
    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;
    }
Esempio n. 19
0
File: gc.c Progetto: GJDuck/SMCHR
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;
}
Esempio n. 20
0
 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;
 }
Esempio n. 21
0
// 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;
}
Esempio n. 22
0
// 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
}
Esempio n. 23
0
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;
}
Esempio n. 24
0
 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;
 }
Esempio n. 25
0
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);
}
Esempio n. 26
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();
}
Esempio n. 27
0
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;
}
Esempio n. 28
0
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;
}
Esempio n. 29
0
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;
    }
}