# HG changeset patch # User Bruno Haible # Date 1296124965 -3600 # Node ID 6b8b94f919ce9b6ca47ccbf4caf6c0266a2cb2fa # Parent 3a91ae6c2f465c407847db55ce4289059df2dde2 vma-iter, get-rusage-as: Add OpenBSD support. * modules/vma-iter (configure.ac): Test for mquery. * lib/vma-iter.h (VMA_ITERATE_SUPPORTED): Define also on OpenBSD. * lib/vma-iter.c: Include . (vma_iterate): Add an implementation based on mquery(). * lib/resource-ext.h (get_rusage_as): Update comments. * lib/get-rusage-as.c: Likewise. * lib/get-rusage-data.c: Likewise. diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2011-01-27 Bruno Haible + + vma-iter, get-rusage-as: Add OpenBSD support. + * modules/vma-iter (configure.ac): Test for mquery. + * lib/vma-iter.h (VMA_ITERATE_SUPPORTED): Define also on OpenBSD. + * lib/vma-iter.c: Include . + (vma_iterate): Add an implementation based on mquery(). + * lib/resource-ext.h (get_rusage_as): Update comments. + * lib/get-rusage-as.c: Likewise. + * lib/get-rusage-data.c: Likewise. + 2011-01-26 Karl Berry * doc/Makefile (lang_env, makeinfo_prog, manual_opts): new diff --git a/lib/get-rusage-as.c b/lib/get-rusage-as.c --- a/lib/get-rusage-as.c +++ b/lib/get-rusage-as.c @@ -66,7 +66,7 @@ OpenBSD: a) setrlimit exists, but RLIMIT_AS is not defined. - b) No VMA iteration API exists. + b) mquery() can be used to find out about the virtual memory areas. AIX: a) setrlimit with RLIMIT_AS succeeds but does not really work: The OS diff --git a/lib/get-rusage-data.c b/lib/get-rusage-data.c --- a/lib/get-rusage-data.c +++ b/lib/get-rusage-data.c @@ -69,7 +69,9 @@ OpenBSD: a) setrlimit with RLIMIT_DATA works. - b) No VMA iteration API exists. + b) mquery() can be used to find out about the virtual memory areas. + get_rusage_data_via_setrlimit() works much better than + get_rusage_data_via_iterator(). Note that malloc() appears to use mmap() for both large and small allocations. diff --git a/lib/resource-ext.h b/lib/resource-ext.h --- a/lib/resource-ext.h +++ b/lib/resource-ext.h @@ -28,7 +28,7 @@ /* Returns the amount of address space currently in use by the current process, or zero if unknown. This is the quantity which is limited by setrlimit(RLIMIT_AS,...). - Note: This function always returns zero on OpenBSD and AIX. */ + Note: This function always returns zero on AIX. */ extern uintptr_t get_rusage_as (void); /* Returns the size of the data segment, or zero if unknown. diff --git a/lib/vma-iter.c b/lib/vma-iter.c --- a/lib/vma-iter.c +++ b/lib/vma-iter.c @@ -44,6 +44,11 @@ # include #endif +#if HAVE_MQUERY /* OpenBSD */ +# include +# include /* mquery */ +#endif + /* Support for reading text files in the /proc file system. */ @@ -490,6 +495,99 @@ break; } +#elif HAVE_MQUERY /* OpenBSD */ + + uintptr_t pagesize; + uintptr_t address; + int /*bool*/ address_known_mapped; + + pagesize = getpagesize (); + /* Avoid calling mquery with a NULL first argument, because this argument + value has a specific meaning. We know the NULL page is unmapped. */ + address = pagesize; + address_known_mapped = 0; + for (;;) + { + /* Test whether the page at address is mapped. */ + if (address_known_mapped + || mquery ((void *) address, pagesize, 0, MAP_FIXED, -1, 0) + == (void *) -1) + { + /* The page at address is mapped. + This is the start of an interval. */ + uintptr_t start = address; + uintptr_t end; + + /* Find the end of the interval. */ + end = (uintptr_t) mquery ((void *) address, pagesize, 0, 0, -1, 0); + if (end == (uintptr_t) (void *) -1) + end = 0; /* wrap around */ + address = end; + + /* It's too complicated to find out about the flags. Just pass 0. */ + if (callback (data, start, end, 0)) + break; + + if (address < pagesize) /* wrap around? */ + break; + } + /* Here we know that the page at address is unmapped. */ + { + uintptr_t query_size = pagesize; + + address += pagesize; + + /* Query larger and larger blocks, to get through the unmapped address + range with few mquery() calls. */ + for (;;) + { + if (2 * query_size > query_size) + query_size = 2 * query_size; + if (address + query_size - 1 < query_size) /* wrap around? */ + { + address_known_mapped = 0; + break; + } + if (mquery ((void *) address, query_size, 0, MAP_FIXED, -1, 0) + == (void *) -1) + { + /* Not all the interval [address .. address + query_size - 1] + is unmapped. */ + address_known_mapped = (query_size == pagesize); + break; + } + /* The interval [address .. address + query_size - 1] is + unmapped. */ + address += query_size; + } + /* Reduce the query size again, to determine the precise size of the + unmapped interval that starts at address. */ + while (query_size > pagesize) + { + query_size = query_size / 2; + if (address + query_size - 1 >= query_size) + { + if (mquery ((void *) address, query_size, 0, MAP_FIXED, -1, 0) + != (void *) -1) + { + /* The interval [address .. address + query_size - 1] is + unmapped. */ + address += query_size; + address_known_mapped = 0; + } + else + address_known_mapped = (query_size == pagesize); + } + } + /* Here again query_size = pagesize, and + either address + pagesize - 1 < pagesize, or + mquery ((void *) address, pagesize, 0, MAP_FIXED, -1, 0) fails. + So, the unmapped area ends at address. */ + } + if (address + pagesize - 1 < pagesize) /* wrap around? */ + break; + } + #endif } diff --git a/lib/vma-iter.h b/lib/vma-iter.h --- a/lib/vma-iter.h +++ b/lib/vma-iter.h @@ -51,7 +51,7 @@ this platform. Note that even when this macro is defined, vma_iterate() may still fail to find any virtual memory area, for example if /proc is not mounted. */ -#if defined __linux__ || defined __FreeBSD__ || defined __NetBSD__ || defined __sgi || defined __osf__ || (defined __APPLE__ && defined __MACH__) || (defined _WIN32 || defined __WIN32__) || defined __CYGWIN__ || defined __BEOS__ || defined __HAIKU__ +#if defined __linux__ || defined __FreeBSD__ || defined __NetBSD__ || defined __sgi || defined __osf__ || (defined __APPLE__ && defined __MACH__) || (defined _WIN32 || defined __WIN32__) || defined __CYGWIN__ || defined __BEOS__ || defined __HAIKU__ || HAVE_MQUERY # define VMA_ITERATE_SUPPORTED 1 #endif diff --git a/modules/vma-iter b/modules/vma-iter --- a/modules/vma-iter +++ b/modules/vma-iter @@ -14,6 +14,7 @@ configure.ac: gl_FUNC_MMAP_ANON +AC_CHECK_FUNCS_ONCE([mquery]) Makefile.am: lib_SOURCES += vma-iter.c